2、集群环境搭建:使用kubeadm搭建高可用集群、容器运行时(containerd)配置、网络插件(Calico)部署

好,咱们进入实战环节。这一章我带你亲手搭一套高可用的Kubernetes集群。说实话,搭建集群这事儿,网上教程一搜一大把,但真正在生产环境里踩过坑的人,才知道哪些地方容易翻车。我会把我在项目中遇到的那些“坑”都指出来,你跟着走,能省不少时间。

2.1 环境规划与准备工作

先说说我的习惯。我一般会准备三台或以上的机器,操作系统用Ubuntu 22.04 LTS或者CentOS 7.9都行。我个人偏爱Ubuntu,包管理更顺手。每台机器至少2核4G内存,磁盘50G以上。你想想看,如果资源不够,后面跑Pod的时候很容易OOM,那可就尴尬了。

节点角色分配如下:

主机名 IP地址 角色 配置
master-01 192.168.1.10 Control Plane 4C/8G/100G
master-02 192.168.1.11 Control Plane 4C/8G/100G
master-03 192.168.1.12 Control Plane 4C/8G/100G
node-01 192.168.1.20 Worker 4C/8G/100G
node-02 192.168.1.21 Worker 4C/8G/100G

嗯,这里要注意,所有节点的主机名不能重复,而且必须能互相解析。我建议你直接改/etc/hosts,别依赖DNS,省得后面出幺蛾子。

# 所有节点执行
cat >> /etc/hosts <

2.2 基础环境配置

在开始装Kubernetes之前,有几项基础工作必须做。我记得有一次,我忘了关swap,结果kubelet死活起不来,查了半天日志才发现。所以,咱们先把这些“雷”排掉。

2.2.1 关闭swap

# 临时关闭
swapoff -a
# 永久关闭,注释掉/etc/fstab中的swap行
sed -i '/swap/s/^/#/' /etc/fstab

2.2.2 配置内核参数

说白了,Kubernetes对网络和内核有一些特殊要求。我们需要加载br_netfilter模块,并设置net.bridge.bridge-nf-call-iptables等参数。

cat <

2.2.3 安装containerd

容器运行时我选containerd。Docker虽然经典,但Kubernetes从1.24开始就弃用Docker了。containerd更轻量,也更符合OCI标准。我在项目中一直用containerd,稳定性没得说。

# 安装依赖
apt-get update && apt-get install -y ca-certificates curl

# 配置Docker官方源(containerd也在这里)
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

apt-get update && apt-get install -y containerd.io

安装完成后,需要生成默认配置并修改。这里有个关键点:containerd默认使用systemd cgroup驱动,但Kubernetes也推荐用systemd。咱们得确保两者一致。

# 生成默认配置
containerd config default | tee /etc/containerd/config.toml

# 修改配置,启用SystemdCgroup
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

# 重启containerd
systemctl restart containerd
systemctl enable containerd
小提示: 你可以用 crictl info 检查containerd的运行状态。如果看到 runtimeType: io.containerd.runc.v2systemdCgroup: true,那就对了。

2.3 安装kubeadm、kubelet、kubectl

接下来安装Kubernetes的核心组件。版本选择上,我建议你选最新的稳定版。比如现在最新的是1.28,那就用1.28。别追新,也别用太老的版本,中间版本最稳。

# 添加Kubernetes源
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list

apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

为什么要apt-mark hold?你想想看,如果哪天不小心执行了apt upgrade,Kubernetes组件被自动升级了,那集群可能就挂了。所以,锁住版本是个好习惯。

2.4 使用kubeadm搭建高可用集群

高可用集群的核心是控制平面要有多个副本。kubeadm支持两种方式:堆叠式(Stacked)和外置式(External)。堆叠式是把etcd和控制平面放在一起,外置式是单独部署etcd集群。对于中小规模集群,堆叠式就够用了。我一般用堆叠式,省事。

2.4.1 初始化第一个控制平面节点

在master-01上执行初始化。这里要指定API Server的负载均衡地址。如果没有现成的负载均衡器,可以用keepalived + haproxy搭一个。或者,你也可以用kube-vip,这个更轻量。

# 在master-01上执行
kubeadm init --control-plane-endpoint "192.168.1.10:6443" \
  --upload-certs \
  --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=192.168.1.10

这里--pod-network-cidr我用了10.244.0.0/16,这是Calico的默认网段。如果你用其他网络插件,记得改成对应的网段。

初始化成功后,会输出一段提示,包括加入集群的命令。一定要保存好!

# 配置kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

2.4.2 加入其他控制平面节点

在master-02和master-03上执行加入命令。注意,这里要用--control-plane参数。

# 在master-02和master-03上执行
kubeadm join 192.168.1.10:6443 --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash> \
  --control-plane \
  --certificate-key <cert-key>
注意: 如果token过期了,可以在master-01上重新生成:kubeadm token create --print-join-command。certificate-key也可以用kubeadm init phase upload-certs --upload-certs重新生成。

2.4.3 加入Worker节点

Worker节点加入就简单多了,不需要--control-plane参数。

# 在node-01和node-02上执行
kubeadm join 192.168.1.10:6443 --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash>

加入完成后,在master-01上执行kubectl get nodes,应该能看到所有节点,但状态都是NotReady。别急,这是因为还没装网络插件。

2.5 部署Calico网络插件

网络插件是Kubernetes集群的“血管”。没有它,Pod之间没法通信。Calico是我最常用的网络插件,性能好,策略灵活。我曾经在生产环境里用Calico支撑过上千个节点,没出过问题。

2.5.1 下载并部署Calico

# 下载Calico manifest
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O

# 如果需要自定义网段,修改calico.yaml中的CALICO_IPV4POOL_CIDR
# 默认是192.168.0.0/16,我们改成10.244.0.0/16
sed -i 's/192.168.0.0\/16/10.244.0.0\/16/' calico.yaml

# 部署
kubectl apply -f calico.yaml

部署完成后,Calico的Pod会运行在kube-system命名空间下。可以用kubectl get pods -n kube-system -w观察状态。等所有Pod都变成Running,节点状态就会变成Ready

2.5.2 验证网络

部署完成后,咱们验证一下网络是否正常。

# 查看节点状态
kubectl get nodes

# 创建一个测试Pod
kubectl run test-pod --image=busybox -- sleep 3600

# 查看Pod的IP
kubectl get pods -o wide

# 进入Pod,ping其他Pod或Service
kubectl exec -it test-pod -- ping 10.244.1.2

如果能ping通,说明网络没问题。如果ping不通,检查一下Calico的日志:kubectl logs -n kube-system -l k8s-app=calico-node

核心要点:
  • 高可用集群至少需要3个控制平面节点,etcd才能形成多数派。
  • containerd的cgroup驱动必须和kubelet一致,都用systemd
  • Calico的Pod网段要和kubeadm初始化时指定的--pod-network-cidr一致。
  • 加入集群的token和certificate-key要妥善保管,过期了可以重新生成。

2.6 避坑指南

最后,分享几个我踩过的坑,你遇到了可以少走弯路。

  • swap没关: 我曾经在一台测试机上忘了关swap,结果kubelet启动后一直报错failed to run kubelet: running with swap on is not supported。解决办法就是swapoff -a,然后注释掉/etc/fstab中的swap行。
  • 端口冲突: 有一次我在一台机器上同时跑了Kubernetes和另一个服务,结果端口被占用了。Kubernetes控制平面需要64432379-238010250-10252等端口,确保这些端口没有被占用。
  • 证书过期: kubeadm生成的证书默认有效期是1年。我建议你部署一个证书自动续期工具,比如cert-manager,或者定期手动更新。

好了,到这步,你的高可用Kubernetes集群就搭好了。下一章,咱们聊聊集群的日常运维和监控。有什么问题,欢迎随时交流。

专注资料整理