1.4. 集群部署

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

层级:

L1 · 入门

难度:

入门

预计:

40 分钟

前置:

环境与工具

1.4.1. 你将学到

  • 仓库 ansible-k8s-install 的完整使用流程

  • kubeadm 初始化时每个关键参数的作用

  • Flannel / Calico / Cilium 三种 CNI 的安装差异

  • 初始化后必须完成的 8 项验收

  • 集群重置与常见初始化失败的排查

1.4.2. 部署方式

方式

适合

优点

代价

Ansible playbook

重复搭建、多节点

一条命令完成

需要理解 inventory

手工 kubeadm

第一次学习、排错

每一步可见

命令较多

kind / minikube

本地体验

最快

无法模拟真实节点

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

1.4.3. 方式一:Ansible 一键部署

1.4.3.1. 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

1.4.3.2. 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] 段。

1.4.3.3. 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。

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

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

1.4.3.4.1. Flannel

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"

1.4.3.4.2. Calico

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"

1.4.3.4.3. Cilium

ansible-playbook install-k8s-cilium.yaml

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

--skip-phases=addon/kube-proxy

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

1.4.3.5. 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

1.4.4. 方式二:手工 kubeadm 对照

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

1.4.4.1. 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 配置命令

1.4.4.2. 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,这是正常的。

1.4.4.3. 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。

1.4.4.4. 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

1.4.5. 初始化后的 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>

1.4.6. 部署后的必要附件

集群可用后,按需安装:

1.4.7. 重置集群

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

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 已备份,且节点已从负载均衡中摘除。

1.4.8. 常见问题

现象

原因

处理

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.4.9. 进阶挑战

  1. 用 kubeadm config print init-defaults 生成配置文件,改用配置文件方式初始化。

  2. 增加第二个 control-plane 节点,验证 --control-plane join 与证书上传。

  3. 把 CNI 从 Flannel 换成 Calico,记录需要清理哪些残留(CNI 配置、路由、iptables)。

  4. 用 kubeadm certs check-expiration 查看证书有效期,规划升级。

1.4.10. 小结

  • Ansible 负责重复性,kubeadm 负责控制平面;理解 kubeadm 参数比记住 playbook 更重要。

  • CNI 必须与 --pod-network-cidr 一致,这是最常见的「节点 NotReady」原因。

  • 部署完成不等于可用,8 项验收至少跑一遍。

1.4.11. 延伸阅读