跳转至

集群部署

这一章把「装集群」拆成可验证的四步:装包、初始化控制平面、安装 CNI、加入工作节点。仓库提供了 Ansible 版本,我们也给出等价的手工命令,方便你理解每一步到底改了什么。

难度 · 入门 预计 40 分钟 前置:环境与工具

你将学到

  • 仓库 ansible-k8s-install 的完整使用流程
  • kubeadm 初始化时每个关键参数的作用
  • Flannel / Calico / Cilium 三种 CNI 的安装差异
  • 初始化后必须完成的 8 项验收
  • 集群重置与常见初始化失败的排查

部署方式

方式 适合 优点 代价
Ansible playbook 重复搭建、多节点 一条命令完成 需要理解 inventory
手工 kubeadm 第一次学习、排错 每一步可见 命令较多
kind / minikube 本地体验 最快 无法模拟真实节点

本章先讲 Ansible,再给出手工对照。两种方式不要混用:Ansible 会执行 kubeadm reset -f,把已有集群清掉。

方式一:Ansible 一键部署

1. 准备控制机

在 master01 或一台能 SSH 到所有节点的机器上:

sudo apt-get update
sudo apt-get install -y git ansible
git clone https://github.com/iKubernetes/learning-k8s.git
cd learning-k8s/ansible-k8s-install

确认控制机能免密 SSH 到四台节点:

for ip in 192.168.10.6 192.168.10.11 192.168.10.12 192.168.10.13; do
  ssh -o BatchMode=yes "$ip" 'hostname' || echo "FAILED: $ip"
done

2. 修改节点地址

编辑 cluster-install.sh 顶部的四个变量:

MASTER_IP='192.168.10.6'
NODE_01_IP='192.168.10.11'
NODE_02_IP='192.168.10.12'
NODE_03_IP='192.168.10.13'

脚本会追加 inventory

cluster-install.sh 使用 cat >> /etc/ansible/hosts 追加主机记录。重复执行会产生重复条目。第二次执行前,先清理 /etc/ansible/hosts 中旧的 [master] / [nodes] 段。

3. 安装基础组件

chmod +x cluster-install.sh
./cluster-install.sh

这一步会:

  1. 安装 Ansible;
  2. 生成 /etc/ansible/hosts;
  3. 执行 install-kubeadm.yaml,在所有节点安装 containerd、kubeadm、kubelet、kubectl,并完成系统预配置。

执行完后先不要急着初始化,检查一遍:

ansible all -m shell -a 'kubeadm version -o short; systemctl is-active containerd'

预期每台节点都输出版本号与 active。

4. 初始化控制平面并安装 CNI

仓库为三种 CNI 各准备了一个 playbook,只选一个执行:

ansible-playbook install-k8s-flannel.yaml

默认使用 VXLAN 隧道;可在 playbook 的 vars 中调整:

k8s_version: "v1.31.0"
pod_cidr: "10.244.0.0/16"
service_cidr: "10.96.0.0/12"
mode: "tunneling"          # tunneling / routing
tunnel_protocol: "vxlan"
vxlan_directrouting: "false"
image_repo: "registry.aliyuncs.com/google_containers"
ansible-playbook install-k8s-calico.yaml

Calico 支持三种组合:

mode tunnel_protocol 效果
tunneling VXLAN VXLAN 隧道,通用性最好
tunneling IPIP IPIP 隧道,部分云网络更友好
routing IPIP BGP 路由 + 跨子网 IPIP

关键变量:

k8s_version: "v1.31.0"
pod_cidr: "10.244.0.0/16"
pod_cidr_block_size: "24"
service_cidr: "10.96.0.0/12"
mode: "tunneling"
tunnel_protocol: "IPIP"
image_repo: "registry.aliyuncs.com/google_containers"
ansible-playbook install-k8s-cilium.yaml

Cilium 默认使用 VXLAN,并可替换 kube-proxy。若使用 kube-proxy replacement,初始化时必须加:

--skip-phases=addon/kube-proxy

Cilium 的详细模式选择见 CNI 网络。

5. 重启并验收

ansible-playbook reboot-system.yaml

等待 1–2 分钟,然后在 master01 上:

kubectl get nodes -o wide
kubectl get pods -n kube-system

预期:

NAME                      STATUS   ROLES           AGE   VERSION
k8s-master01.magedu.com   Ready    control-plane   66s   v1.31.0
k8s-node01.magedu.com     Ready    <none>          52s   v1.31.0
k8s-node02.magedu.com     Ready    <none>          52s   v1.31.0
k8s-node03.magedu.com     Ready    <none>          52s   v1.31.0

方式二:手工 kubeadm 对照

如果你想理解 Ansible 做了什么,可以在 master01 上按下面顺序执行。

1. 初始化控制平面

sudo kubeadm init \
  --control-plane-endpoint=k8s-master01.magedu.com \
  --apiserver-advertise-address=192.168.10.6 \
  --kubernetes-version=v1.31.0 \
  --pod-network-cidr=10.244.0.0/16 \
  --service-cidr=10.96.0.0/12 \
  --image-repository=registry.aliyuncs.com/google_containers \
  --upload-certs

参数说明:

参数 作用 注意
--control-plane-endpoint 控制平面统一入口 后续加 master 必须一致
--apiserver-advertise-address API Server 对外地址 多网卡时务必指定
--pod-network-cidr Pod 网段 必须与 CNI 配置一致
--service-cidr Service 网段 不要与节点网段重叠
--image-repository 镜像仓库 国内环境常用阿里云
--upload-certs 上传证书供其他 master 使用 单 master 可省略

成功后会输出三件事,务必保存:

  • kubeadm join ... --token ...(工作节点加入)
  • kubeadm join ... --control-plane ... --certificate-key ...(控制平面加入)
  • kubectl 配置命令

2. 配置 kubectl

mkdir -p "$HOME/.kube"
sudo cp /etc/kubernetes/admin.conf "$HOME/.kube/config"
sudo chown "$(id -u):$(id -g)" "$HOME/.kube/config"
kubectl get nodes

此时节点是 NotReady,因为还没有 CNI,这是正常的。

3. 安装 CNI

以 Calico 为例:

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.0/manifests/calico.yaml

如果 Pod CIDR 不是 192.168.0.0/16,先下载文件并修改 CALICO_IPV4POOL_CIDR,再 apply。

4. 加入工作节点

在每台 worker 上执行 init 输出的 join 命令:

sudo kubeadm join k8s-master01.magedu.com:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash>

Token 默认 24 小时过期。过期后重新生成:

kubeadm token create --print-join-command

初始化后的 8 项验收

不要只看 kubectl get nodes。逐项确认:

# 1. 节点状态
kubectl get nodes -o wide

# 2. 系统组件
kubectl get pods -n kube-system -o wide

# 3. CoreDNS 是否就绪
kubectl get deploy -n kube-system coredns

# 4. CNI Pod
kubectl get pods -n kube-system | grep -E 'calico|cilium|flannel'

# 5. 集群信息
kubectl cluster-info

# 6. 组件健康
kubectl get --raw='/readyz?verbose'

# 7. DNS 解析
kubectl run dnstest --image=busybox:1.36 --rm -it --restart=Never -- \
  nslookup kubernetes.default

# 8. 跨节点 Pod 网络
kubectl create deploy nettest --image=nginx:1.27 --replicas=4
kubectl get pods -o wide

跨节点验证:

# 在一个 Pod 里访问另一个节点上的 Pod IP
kubectl run client --image=busybox:1.36 --rm -it --restart=Never -- \
  wget -qO- --timeout=3 http://<另一个节点的PodIP>

部署后的必要附件

集群可用后,按需安装:

重置集群

实验环境建议保留重置脚本,随时推倒重来:

ansible-playbook reset-kubeadm.yaml

手工重置:

sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d /var/lib/cni /var/lib/kubelet /var/lib/etcd
sudo rm -rf "$HOME/.kube"
sudo reboot

reset 会删除数据

kubeadm reset 会移除本地 etcd 数据与 kubelet 状态。生产环境执行前必须确认 etcd 已备份,且节点已从负载均衡中摘除。

常见问题

现象 原因 处理
init 卡在 waiting for kubelet kubelet 起不来 / cgroup 配置错 journalctl -u kubelet -n 100
节点 NotReady CNI 未装或 Pod CIDR 不匹配 检查 CNI Pod 日志与 podCIDR
CoreDNS Pending CNI 未就绪 等 CNI Running,或检查污点
join 报 token 过期 token 默认 24h kubeadm token create --print-join-command
加入后节点名重复 主机名相同 修改 /etc/hostname 并重启 kubelet
kubectl 连不上 6443 API Server 未起 / 防火墙 crictl ps、ss -lntp、检查证书
Calico Pod CrashLoop Pod CIDR 与 calico 配置冲突 修改 CALICO_IPV4POOL_CIDR 后重装
多网卡选错地址 kubelet 用了错误 IP 指定 --node-ip 并重启 kubelet

进阶挑战

  1. 用 kubeadm config print init-defaults 生成配置文件,改用配置文件方式初始化。
  2. 增加第二个 control-plane 节点,验证 --control-plane join 与证书上传。
  3. 把 CNI 从 Flannel 换成 Calico,记录需要清理哪些残留(CNI 配置、路由、iptables)。
  4. 用 kubeadm certs check-expiration 查看证书有效期,规划升级。

小结

  • Ansible 负责重复性,kubeadm 负责控制平面;理解 kubeadm 参数比记住 playbook 更重要。
  • CNI 必须与 --pod-network-cidr 一致,这是最常见的「节点 NotReady」原因。
  • 部署完成不等于可用,8 项验收至少跑一遍。

延伸阅读