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.v2 和 systemdCgroup: 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>
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控制平面需要
6443、2379-2380、10250-10252等端口,确保这些端口没有被占用。 - 证书过期: kubeadm生成的证书默认有效期是1年。我建议你部署一个证书自动续期工具,比如
cert-manager,或者定期手动更新。
好了,到这步,你的高可用Kubernetes集群就搭好了。下一章,咱们聊聊集群的日常运维和监控。有什么问题,欢迎随时交流。