博客园出海记-组装集装箱:自建 Kubernetes 集群

在开篇中我们宣布了博客园出海计划的启航,出海航船选择了阿里云。

第一件准备工作是在航船上组装集装箱 ------ 搭建 Kubernetes 集群。

出海根据地选在了阿里云新加坡机房,Kubernetes 集群用阿里云 ECS 自己搭建,没有使用阿里云容器服务 ACK。

首先购买一台 ECS 用于部署 Control Plane 节点,Control Plane 是指挥协调控制中心,不干具体活,所以不需要很高的配置,选择了2核4G的经济型 ECS 实例(ecs.e-c1m2.large),操作系统选用了 Ubuntu 24.04,加入新建的 kube 安全组(集群中的节点服务器都会加入这个安全组),主机名是 kube-cp-01。

准备工作

安装 k8s 三驾马车

安装 kubelet + kubeadm + kubectl,使用的版本是 1.33.4

安装所需的软件包

shell 复制代码
apt-get update
apt-get install -y apt-transport-https ca-certificates curl gnupg

添加 k8e 安装源的签名秘钥

shell 复制代码
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg

添加 k8e 安装源

shell 复制代码
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
chmod 644 /etc/apt/sources.list.d/kubernetes.list

apt-get 命令安装三驾马车

shell 复制代码
apt-get update
apt-get install -y kubelet kubectl kubeadm

确认版本

shell 复制代码
~# kubelet --version
Kubernetes v1.33.4
~# kubectl version
Client Version: v1.33.4
~# kubeadm version -o short
v1.33.4

配置网络

开启 IPv4 包转发

shell 复制代码
echo "net.ipv4.ip_forward = 1" | tee /etc/sysctl.d/k8s.conf
sysctl --system

安装容器运行时 containerd

采用手动安装方式,安装的 containerd 版本是 2.1.4

下载并解压至 /usr/local

shell 复制代码
wget -c https://github.com/containerd/containerd/releases/download/v2.1.4/containerd-2.1.4-linux-amd64.tar.gz
tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gz

通过 systemd 自动运行 containerd

shell 复制代码
mkdir -p /usr/local/lib/systemd/system
wget -c https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -O /usr/local/lib/systemd/system/containerd.service 
systemctl daemon-reload
systemctl enable --now containerd

安装 runc

shell 复制代码
wget -c https://github.com/opencontainers/runc/releases/download/v1.3.1/runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc

安装 CNI 插件

shell 复制代码
wget -c https://github.com/containernetworking/plugins/releases/download/v1.8.0/cni-plugins-linux-amd64-v1.8.0.tgz
mkdir -p /opt/cni/bin
tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.8.0.tgz

生成 containerd 配置

shell 复制代码
mkdir /etc/containerd
containerd config default > /etc/containerd/config.toml

在 /etc/containerd/config.toml 中启用 SystemdCgroup

toml 复制代码
[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc]
  ...
  [plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
    SystemdCgroup = true

重启 containerd 使配置生效

shell 复制代码
systemctl restart containerd

安装 containerd 命令行工具 nerdctl

shell 复制代码
wget -c https://github.com/containerd/nerdctl/releases/download/v2.1.4/nerdctl-2.1.4-linux-amd64.tar.gz
tar -zxf nerdctl-2.1.4-linux-amd64.tar.gz
mv nerdctl /usr/bin/nerdctl

将 nerdctl 的默认命名空间设置为 k8s.io

shell 复制代码
mkdir /etc/nerdctl
echo 'namespace = "k8s.io"' | tee /etc/nerdctl/nerdctl.toml

创建高可用集群

在 /etc/hosts 中添加 control-plane-endpoint 的主机名解析

复制代码
127.0.0.1  kube-api

用 kubeadmin 命令创建集群

shell 复制代码
kubeadm init \
    --control-plane-endpoint "kube-api:6443"  \
    --upload-certs \
    --pod-network-cidr=10.0.0.0/8 \
    --skip-phases=addon/kube-proxy

注:没有安装 kube-proxy 是因为会用 cilium 取代它

出现下面的输出说明集群创建成功了

复制代码
Your Kubernetes control-plane has initialized successfully!
...

注:上面的输出内容中包含加入 control-plane 与 worker 节点的命令,后面会用到

用 nerdctl ps 命令查看容器运行情况

text 复制代码
root@kube-cp-01 ~ # nerdctl ps    
CONTAINER ID    IMAGE                                              COMMAND                   CREATED               STATUS
f54d0fc6215a    registry.k8s.io/kube-proxy:v1.33.4                 "/usr/local/bin/kube..."    About a minute ago    Up    
73cbd7ab3d69    registry.k8s.io/kube-scheduler:v1.33.4             "kube-scheduler --au..."    About a minute ago    Up
5ff05420d284    registry.k8s.io/kube-controller-manager:v1.33.4    "kube-controller-man..."    About a minute ago    Up
7031f91cfc16    registry.k8s.io/kube-apiserver:v1.33.4             "kube-apiserver --ad..."    About a minute ago    Up
2c79907098d4    registry.k8s.io/etcd:3.5.21-0                      "etcd --advertise-cl..."    About a minute ago    Up    
975b724b2814    registry.k8s.io/pause:3.10                         "/pause"                  About a minute ago    Up       

添加 kubectl 用到的配置文件

shell 复制代码
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

查看节点运行情况

shell 复制代码
root@kube-cp-01 ~ # kubectl get nodes
NAME         STATUS   ROLES           AGE     VERSION
kube-cp-01   Ready    control-plane   2m41s   v1.33.4

注:这里 control-plane node 处于 Ready 状态,如果用了 kube-proxy,在完成安装 CNI 网络插件之前会处于 NotReady 状态

查看 pod 运行情况

shell 复制代码
root@kube-cp-01 ~ # kubectl get pods -n kube-system                                                                                                                                                                1 ↵
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-674b8bbfcf-994fx             0/1     Pending   0          2m40s
coredns-674b8bbfcf-bsgdd             0/1     Pending   0          2m40s
etcd-kube-cp-01                      1/1     Running   0          2m46s
kube-apiserver-kube-cp-01            1/1     Running   0          2m45s
kube-controller-manager-kube-cp-01   1/1     Running   0          2m44s
kube-proxy-vlvt9                     1/1     Running   0          2m40s
kube-scheduler-kube-cp-01            1/1     Running   0          2m44s

coredns 处于 Pending 状态是因为还没安装 CNI 网络插件

安装 CNI 网络插件

选用 cilium 作为 CNI(容器网络接口) 插件

安装 cilium cli

shell 复制代码
wget -c https://github.com/cilium/cilium-cli/releases/download/v0.18.7/cilium-linux-amd64.tar.gz
tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin

安装 cilium

shell 复制代码
root@kube-cp-01 ~ # cilium install --version 1.18.1 \
  --namespace kube-system \
  --set bpf.masquerade=true \
  --set kubeProxyReplacement=true
ℹ️  Using Cilium version 1.18.1
🔮 Auto-detected cluster name: kubernetes
🔮 Auto-detected kube-proxy has not been installed
ℹ️  Cilium will fully replace all functionalities of kube-proxy

检查 cillium 的运行情况

shell 复制代码
root@kube-cp-01 ~ # cilium status --wait                
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       disabled
    \__/       ClusterMesh:        disabled

DaemonSet              cilium                   Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet              cilium-envoy             Desired: 1, Ready: 1/1, Available: 1/1
Deployment             cilium-operator          Desired: 1, Ready: 1/1, Available: 1/1
Containers:            cilium                   Running: 1
                       cilium-envoy             Running: 1
                       cilium-operator          Running: 1
                       clustermesh-apiserver    
                       hubble-relay             
Cluster Pods:          2/2 managed by Cilium
Helm chart version:    1.18.1

确认 cilium 已取代 kube-proxy

shell 复制代码
root@kube-cp-01 ~ # kubectl -n kube-system exec ds/cilium -- cilium-dbg status | grep KubeProxyReplacement
KubeProxyReplacement:    True   [eth0   172.21.49.56 fe80::216:3eff:fe0d:c8fe (Direct Routing)]

确认已启用 eBPF Host-Routing

shell 复制代码
root@kube-cp-01 ~ # kubectl -n kube-system exec ds/cilium -- cilium-dbg status | grep BPF                 
Routing:                 Network: Tunnel [vxlan]   Host: BPF
Masquerading:            BPF   [eth0]   10.0.0.0/24  [IPv4: Enabled, IPv6: Disabled]

Cillium 成功部署后,coredns pod 也随之正常运行

shell 复制代码
root@kube-cp-01 ~ # kubectl get pods -n kube-system
NAME                                 READY   STATUS    RESTARTS   AGE
coredns-674b8bbfcf-994fx             1/1     Running   0          8m46s
coredns-674b8bbfcf-bsgdd             1/1     Running   0          8m46s

添加更多 Control Plane 节点

一共部署 3 个 control plane 节点,准备 2 台与 kube-cp-01 同样配置的2核4G阿里云 ecs,加入 kube 安全组,主机名分别为 kube-cp-02 与 kube-cp-03,用 kube-cp-01 的镜像创建系统。

分别登录这2台服务器,修改主机名,重置已有的 k8s 配置

shell 复制代码
hostnamectl set-hostname kube-cp-02
kubeadm reset

在 /etc/hosts 中添加 kube-api 的解析,解析到 kube-cp-01 的 IP 地址

text 复制代码
172.21.49.56  kube-api

通过下面 kubeadm join 命令将服务器加入集群成为 control plane 节点

shell 复制代码
kubeadm join kube-api:6443 --token xxxxxx \
    --discovery-token-ca-cert-hash sha256:yyyyyy \
    --control-plane --certificate-key zzzzzz \
    -v=6

注:如果忘记之前 kubeadm init 创建集群时生成的 join 命令所需的 token + hash + key,可以通过下面的命令在 kube-cp-01 上生成

shell 复制代码
kubeadm init phase upload-certs --upload-certs
kubeadm token create --print-join-command

在 /etc/hosts 将 kube-api 解析到 127.0.0.1

text 复制代码
127.0.0.1  kube-api

这时通过 kubectl 命令就可以看到3个 control plane 节点

shell 复制代码
root@kube-cp-03 ~ # kubectl get nodes
NAME         STATUS   ROLES           AGE     VERSION
kube-cp-01   Ready    control-plane   2d6h    v1.33.4
kube-cp-02   Ready    control-plane   48m     v1.33.4
kube-cp-03   Ready    control-plane   6m18s   v1.33.4

指挥协调控制中心三人组就这样组建好了。

接下来添加真正干活的 worker 节点,添加之前要部署负载均衡,worker 节点通过负载均衡访问 control plane 的 api server,按照 control plane 的指令与目标干活。

部署负载均衡

选用了阿里云网络型负载均衡(NLB),创建一个名为 kube-api 的私网 NLB

接着,创建 NLB 服务器组,将 3 台 control-plane 节点服务器加入服务器组

接着,给 NLB 创建监听,监听协议是 TCP,端口是 6443,关联服务器组选择前一步创建的服务器组。

k8s 集群的 control-plane-endpoint 主机名是 kube-api,NLB 的 endpoint 主机名是下面这个很长的三级域名,需要部署内网 dns 服务器进行 CNAME 解析

text 复制代码
nlb-uaohnyerknl7eraukw2.ap-southeast-1.nlb.aliyuncsslbintl.com

选用了阿里云「云解析 PrivateZone」,在控制台添加一个域名,然后添加一个 CNAME 解析记录,将 kube-api 解析到阿里云负载均衡绑定的主机名

登录到 kube-cp-01 服务器测试一下解析

shell 复制代码
ping kube-api
PING nlb-uaohnyerknl7eraukw2.ap-southeast-1.com (172.21.49.53) 56(84) bytes of data.
64 bytes from 172.21.49.53: icmp_seq=1 ttl=102 time=0.378 ms

解析成功,负载均衡部署完成。

添加 Worker 节点

准备一台4核8G的阿里云 ecs 作为 worker 节点,加入 kube 安全组,主机名设置为 kube-worker-01,也是用之前的镜像创建系统。

登录 kube-worker-01 服务器,删除 /etc/hosts 中的 kube-api 解析,之前部署的内网 dns 服务器会自动进行解析。

用 kubeadm reset 命令重置 k8s 配置,通过 kubeadm join 命令将这台服务器作为 worker 节点加入集群

shell 复制代码
kubeadm join kube-api:6443 --token xxxxxx \
  --discovery-token-ca-cert-hash sha256:yyyyyy

出现下面的输出,说明成功加入

text 复制代码
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

登录到其中一台 control-plane 查看集群中的节点情况

shell 复制代码
root@kube-cp-01 ~ # kubectl get nodes                 
NAME             STATUS   ROLES           AGE     VERSION
kube-cp-01       Ready    control-plane   2d12h   v1.33.4
kube-cp-02       Ready    control-plane   6h45m   v1.33.4
kube-cp-03       Ready    control-plane   87m     v1.33.4
kube-worker-01   Ready    <none>          54m     v1.33.4

3 个 control-plane 节点,1 个 worker 节点都运行正常,k8s 集群部署完成,集装箱准备就绪,下一步就是往集装箱中装包裹(部署 pod),会在后续的博文中分享。

搭建中遇到的问题

开始安装的是最新版 kubernetes 1.34,在部署最新版 cilium 1.18.1 时发现 cilium 不兼容 k8s 1.34,只能换成 k8s 1.33.4。

本来想参考这篇博文试试 cilium 的高科技,用 k8s service 取代阿里云负载均衡作为 control plane 的负载均衡,但实验失败,等以后找时间再研究。

结语

让大家久等了,出海记第2篇博文姗姗来太迟,因为这段时间太忙了,有时搭建到中途,竟然连续几天抽不出时间继续搭建。

接下来会更忙,这段时间和华为达成了 HarmonyOS 的推广和专区建设合作,接下来要重点忙于 HarmonyOS 专区的搭建与运营,出海记的分享会更受影响,会考虑蚂蚁搬家式地一点一点分享,比如部署 redis 分享一篇,部署 dapr 分享一篇,直到找到负责 HarmonyOS 合作的运营人才加入团队,出海的步伐才能加快。

另外,园子办公室隔壁的「云栖开发者基地」装修好了,以后杭州的园友可以有固定的地方线下交流了,园子的出海也可以找个时间在线下交流了。

相关推荐
ShirleyWang0125 小时前
让headlamp控制台能访问
linux·服务器·python·k8s·k3s
spider_xcxc7 小时前
K8s 部署学习笔记
docker·容器·kubernetes·云计算·k8s
ShirleyWang0129 小时前
Day02 K3s NGF(Nginx Gateway Fabric)单 Worker 环境网关更新与故障处置 SOP
linux·服务器·python·k8s·k3s
ShirleyWang0129 小时前
DAY01 K3s 私有化部署排障复盘与 SOP
linux·服务器·k8s·k3s·企业部署
XUHUOJUN4 天前
AKS 不是安装在 Windows Server 上,而是运行在 Windows Server 之上的 Azure 平台能力
windows·架构·k8s·azure local·azure stack
Geek-Chow4 天前
Connecting kubectl to a Private EKS Cluster Over an Internal Domain
kubernetes·k8s·aws
spider_xcxc6 天前
Docker Compose 容器通信详解:同一个 Compose 文件才能互通吗?
docker·容器·k8s·容器化·容器网络
欢醉11 天前
k8s调用服务异常cannot allocate memory
kubernetes·k8s
万里侯14 天前
GitOps 漂移检测:集群里改了配置,Git 还以为一切正常
微服务·容器·k8s
spider_xcxc15 天前
云上网络基石(阿里云):深入解读阿里云VPC及其应用生态
网络·阿里云·云计算·k8s·运维开发·虚拟化