这篇文章整理自我早期的 Kubernetes v1.21 部署笔记,并根据当前 kubeadm 的通用流程重新校正。旧笔记中的 Docker 直连、固定旧版本仓库、关闭全部防火墙以及忽略所有预检错误等做法已经不适合直接照搬。
一、先理解单控制平面集群
单控制平面集群只有一台 control-plane 节点,API Server、Scheduler、Controller Manager 和本地 etcd 都运行在这台机器上。它适合学习、实验和小型测试环境,但不具备控制面的高可用能力。控制平面节点故障时,集群管理能力会中断,etcd 数据也存在丢失风险。
二、准备节点
建议至少准备一台控制平面节点和一台工作节点。控制平面节点至少需要 2 个 CPU、2 GiB 内存;所有节点应使用受支持的 Linux 系统,并保证节点之间网络互通。
每台节点都需要安装:
1. 符合 CRI 规范的容器运行时,例如 containerd 或 CRI-O。
2. kubelet,用于运行和管理节点上的 Pod。
3. kubeadm,用于初始化和加入集群。
4. kubectl,通常安装在管理集群的机器上。
kubeadm、kubelet 与控制平面的版本必须遵守 Kubernetes 的版本偏差策略。实际安装命令应以所选 Kubernetes 版本对应的官方文档为准,不要直接复制多年前的软件源和版本号。
三、配置容器运行时与系统参数
Kubernetes 从 v1.24 起已经移除内置 dockershim。新集群更适合直接使用 containerd 等 CRI 运行时;如果必须使用 Docker Engine,需要额外部署 cri-dockerd。
使用 Linux systemd 的节点,建议让容器运行时和 kubelet 使用一致的 cgroup 驱动。两者不一致时,kubelet 可能无法正常启动或节点会处于异常状态。
网络插件通常还要求开启 IPv4 转发:
sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.ipv4.ip_forward = 1
EOF
sudo sysctl --system
不要为了省事永久关闭所有防火墙,也不要直接使用 --ignore-preflight-errors=all 掩盖问题。应根据运行时、CNI 和 Kubernetes 官方端口清单按需放行。
四、初始化控制平面
在控制平面节点执行初始化。下面只展示通用形式,地址和 Pod 网段需要根据实际环境及所选 CNI 修改:
sudo kubeadm init \
--apiserver-advertise-address=<CONTROL_PLANE_IP> \
--pod-network-cidr=<POD_CIDR>
如果未来计划扩展为高可用集群,初始化时应考虑设置稳定的 --control-plane-endpoint,例如负载均衡器地址或稳定 DNS 名称。
初始化成功后,按输出提示为当前用户配置 kubectl:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
admin.conf 拥有很高的集群权限,不应公开、上传到代码仓库或随意分享。
五、安装 Pod 网络插件
kubeadm 不会替你安装 Pod 网络。必须选择并安装一个兼容的 CNI 插件,集群内的 Pod 才能相互通信。Pod 网段不能与节点所在网络重叠,并且必须与 CNI 的配置保持一致。
安装方式以所选 CNI 项目的官方文档为准。一个集群只应安装一个主 Pod 网络。安装后可以检查:
kubectl get pods -n kube-system
kubectl get nodes -o wide
当网络插件和 CoreDNS 正常运行后,节点通常会从 NotReady 变为 Ready。
六、加入工作节点
kubeadm init 完成时会输出 kubeadm join 命令。应在工作节点上执行该命令。加入令牌属于敏感信息,不要放进公开博客、聊天记录或代码仓库。
如果原命令已经遗失或令牌过期,可在控制平面节点重新生成:
kubeadm token create --print-join-command
七、验证集群
先检查节点和系统组件:
kubectl get nodes
kubectl get pods -A
再创建一个测试工作负载:
kubectl create deployment nginx --image=nginx
kubectl get deployment,pod
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get service nginx
测试完成后,记得删除实验资源:
kubectl delete service nginx
kubectl delete deployment nginx
八、常见问题与安全提醒
1. 节点一直 NotReady:先检查 CNI、CoreDNS、kubelet 日志和 Pod 网段是否冲突。
2. kubelet 启动失败:检查容器运行时是否正常、CRI socket 是否正确,以及 cgroup 驱动是否一致。
3. 镜像拉取失败:检查 DNS、代理、镜像仓库访问和运行时配置,不要盲目替换不可信镜像源。
4. 不要把 Dashboard 直接以公网 NodePort 暴露,更不要给公开账号绑定 cluster-admin。
5. 单控制平面不是生产高可用方案。重要环境至少应定期备份 etcd,并规划多控制平面架构。
总结
kubeadm 的价值是把复杂的控制面初始化流程标准化,但它不会替你完成主机安全、网络规划、运行时选择、CNI 安装、监控和备份。真正可靠的部署,关键不只是让节点显示 Ready,而是确保版本、网络、权限和恢复方案都经过验证。
参考资料:
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
https://kubernetes.io/docs/setup/production-environment/container-runtimes/
https://kubernetes.io/docs/concepts/cluster-administration/addons/