K8s 系列 | 第 2 天(重访):从单节点到生产级高可用集群:kubeadm 部署进阶与踩坑指南


title: “K8s 系列 | 第 2 天(重访):从单节点到生产级高可用集群:kubeadm 部署进阶与踩坑指南”
tags:
– Kubernetes
– K8s系列
– DevOps
– kubeadm
– 高可用集群
– 集群部署
– 生产运维


第 2/30 天(重访)

本文是 K8s 系列的第 2 天重访篇。原版第 2 天介绍了使用 kubeadm 搭建单节点集群的入门步骤,本文则聚焦于生产级高可用 Kubernetes 集群的部署实战,涵盖 HA 架构设计、etcd 集群化、Control Plane 负载均衡、Worker Node 加入以及常见踩坑解决方案。


一、引言

在入门阶段,我们使用 kubeadm init 快速启动了一个单节点集群,这对于学习和开发测试绰绰有余。然而,一旦要将 K8s 集群推向生产环境,单点故障就是最大的敌人——Control Plane 挂了,整个集群不可用;etcd 挂了,所有数据丢失。

生产级 Kubernetes 集群的核心要求:

要求 说明
Control Plane 高可用 至少 3 个 Master 节点,通过负载均衡器分发请求
etcd 集群化 奇数节点(3/5/7),Raft 共识保证数据一致性
Worker Node 弹性 可动态扩缩容,与 Control Plane 解耦
证书与安全 生产级证书管理,RBAC 权限控制

本文将手把手带你从零搭建一个3 节点 Control Plane + 3 节点 Worker + 负载均衡器的生产级 K8s 集群。


二、架构设计

2.1 节点规划

角色 主机名 IP 地址 配置
LB k8s-lb 192.168.1.100 2C4G
Master-1 k8s-m1 192.168.1.101 4C8G
Master-2 k8s-m2 192.168.1.102 4C8G
Master-3 k8s-m3 192.168.1.103 4C8G
Worker-1 k8s-w1 192.168.1.201 8C16G
Worker-2 k8s-w2 192.168.1.202 8C16G
Worker-3 k8s-w3 192.168.1.203 8C16G

2.2 架构拓扑

                        ┌─────────────┐
                        │   Nginx LB   │  ← 192.168.1.100:6443
                        │  (HAProxy)   │
                        └──────┬──────┘
                               │
          ┌────────────────────┼────────────────────┐
          ▼                    ▼                    ▼
   ┌───────────┐       ┌───────────┐       ┌───────────┐
   │  Master-1 │       │  Master-2 │       │  Master-3 │
   │  k8s-m1   │◄─────►│  k8s-m2   │◄─────►│  k8s-m3   │
   └─────┬─────┘       └─────┬─────┘       └─────┬─────┘
         │                   │                    │
         └───────────────────┼────────────────────┘
                             │
                    ┌────────┴────────┐
                    ▼                 ▼
              ┌──────────┐     ┌──────────┐
              │ Worker-1 │     │ Worker-2 │  ...更多 Worker
              └──────────┘     └──────────┘

三、前置准备

3.1 所有节点通用初始化

在所有 7 台机器上执行以下初始化操作:

# 1. 关闭交换分区(kubelet 强制要求)
swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab

# 2. 加载内核模块
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter

# 3. 设置内核参数
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sysctl --system

# 4. 安装 containerd
apt-get update && apt-get install -y containerd
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
# 关键:修改 SystemdCgroup 为 true
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd

# 5. 安装 kubeadm、kubelet、kubectl
apt-get update && apt-get install -y apt-transport-https curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/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.30/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
apt-get update && apt-get install -y kubelet=1.30.0-1.1 kubeadm=1.30.0-1.1 kubectl=1.30.0-1.1
apt-mark hold kubelet kubeadm kubectl

3.2 配置负载均衡器(LB 节点)

k8s-lb 节点上安装 HAProxy:

apt-get install -y haproxy

编辑 /etc/haproxy/haproxy.cfg

global
    log /dev/log local0
    maxconn 2000

defaults
    log global
    mode tcp
    option tcplog
    timeout connect 5000ms
    timeout client 50000ms
    timeout server 50000ms

frontend k8s-api
    bind *:6443
    default_backend k8s-masters

backend k8s-masters
    balance roundrobin
    server master1 192.168.1.101:6443 check fall 3 rise 2
    server master2 192.168.1.102:6443 check fall 3 rise 2
    server master3 192.168.1.103:6443 check fall 3 rise 2

启动 HAProxy:

systemctl restart haproxy
systemctl enable haproxy
# 验证
curl -k https://192.168.1.100:6443/healthz
# 应返回 "ok"

四、初始化 Control Plane 集群

4.1 在 Master-1 上初始化第一个 Control Plane

# 创建 kubeadm 配置文件
cat > kubeadm-config.yaml << 'EOF'
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.1.101
  bindPort: 6443
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: 1.30.0
controlPlaneEndpoint: 192.168.1.100:6443
apiServer:
  certSANs:
    - "192.168.1.100"
    - "192.168.1.101"
    - "192.168.1.102"
    - "192.168.1.103"
    - "127.0.0.1"
networking:
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd
EOF

# 初始化
kubeadm init --config kubeadm-config.yaml --upload-certs

初始化成功后,会输出两条关键信息:
1. kubeadm join 命令(用于 Worker 节点加入)
2. kubeadm join 命令 + --control-plane --certificate-key(用于其他 Master 节点加入)

请务必保存这些输出! 如果丢失,可在 Master-1 上通过以下命令重新获取:

# 重新生成证书密钥
kubeadm init phase upload-certs --upload-certs
# 获取 token
kubeadm token create --print-join-command

4.2 配置 kubectl(Master-1 上执行)

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

# 验证
kubectl get nodes
kubectl get pods -n kube-system

4.3 安装 CNI 网络插件(Calico)

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28/manifests/tigera-operator.yaml

cat > custom-resources.yaml << 'EOF'
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  calicoNetwork:
    ipPools:
    - blockSize: 26
      cidr: 10.244.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()
---
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
  name: default
spec: {}
EOF

kubectl create -f custom-resources.yaml

4.4 加入其余 Control Plane 节点

Master-2Master-3 上分别执行:

kubeadm join 192.168.1.100:6443 
  --token <token> 
  --discovery-token-ca-cert-hash sha256:<hash> 
  --control-plane 
  --certificate-key <key>

⚠️ 关键踩坑点:如果 --control-plane 加入失败,最常见的原因是证书密钥过期(有效期 2 小时)。解决方案是回到 Master-1 重新生成:kubeadm init phase upload-certs --upload-certs

4.5 加入 Worker 节点

Worker-1、Worker-2、Worker-3 上分别执行:

kubeadm join 192.168.1.100:6443 
  --token <token> 
  --discovery-token-ca-cert-hash sha256:<hash>

五、验证集群

# 查看所有节点状态
kubectl get nodes -o wide

# 预期输出示例:
# NAME      STATUS   ROLES           AGE   VERSION   INTERNAL-IP
# k8s-m1    Ready    control-plane   10m   v1.30.0   192.168.1.101
# k8s-m2    Ready    control-plane   8m    v1.30.0   192.168.1.102
# k8s-m3    Ready    control-plane   7m    v1.30.0   192.168.1.103
# k8s-w1    Ready    <none>          5m    v1.30.0   192.168.1.201
# k8s-w2    Ready    <none>          4m    v1.30.0   192.168.1.202
# k8s-w3    Ready    <none>          3m    v1.30.0   192.168.1.203

# 验证 Control Plane HA
kubectl get endpoints -n kube-system kube-scheduler -o yaml | grep -A 10 subsets

# 部署测试应用验证功能
kubectl create deployment nginx --image=nginx:alpine --replicas=3
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get svc,deploy,pod -o wide

# 模拟 Master 节点故障测试
# 在 Master-1 上停止 kubelet:
# systemctl stop kubelet
# 此时 kubectl 应仍能正常使用(通过 LB 路由到其他 Master)

六、常见踩坑与解决方案

6.1 初始化卡在 [wait-control-plane]

现象kubeadm init 卡在 [wait-control-plane] 阶段很久

原因:API Server 的健康检查端口无法访问,通常是容器运行时配置问题

解决

# 检查 containerd 配置
cat /etc/containerd/config.toml | grep SystemdCgroup
# 必须为 true
# 检查 cgroup 驱动一致性
kubeadm config migrate

6.2 Pod 网络不通(CNI 问题)

现象:CoreDNS Pending 或 CrashLoopBackOff

原因:Pod CIDR 与 CNI 插件配置不匹配,或节点间网络不通

解决

# 检查 Pod CIDR 是否与 CNI 配置一致
kubectl cluster-info dump | grep -m 2 cluster-cidr
# 检查节点防火墙
iptables -L -n | grep FORWARD | grep DROP
# 确保 FORWARD 策略为 ACCEPT
iptables -P FORWARD ACCEPT

6.3 证书过期

现象kubectl 命令报证书相关错误

解决

# 检查证书有效期
kubeadm certs check-expiration
# 更新证书
kubeadm certs renew all
# 重启组件
systemctl restart kubelet

6.4 重启后 kubelet 无法启动

现象:节点重启后 kubectl get nodes 显示 NotReady

原因:kubelet 启动顺序早于 containerd

解决

# 设置依赖关系
cat > /etc/systemd/system/kubelet.service.d/20-depends.conf << 'EOF'
[Unit]
After=containerd.service
Requires=containerd.service
EOF
systemctl daemon-reload

七、总结

本文从零搭建了一个生产级 3+3 高可用 Kubernetes 集群,核心要点回顾:

要点 说明
HA 架构 至少 3 个 Control Plane 节点 + 负载均衡器
etcd 集群 kubeadm 自动管理,确保奇数节点
CNI 网络 Calico 提供 VXLAN 跨子网通信
证书管理 定期检查证书有效期,提前续期
故障切换 任意 Master 节点宕机不影响集群

生产环境 Checklist
– [ ] 是否配置了 HAProxy/Nginx 健康检查?
– [ ] 是否设置了证书自动续期(cronjob)?
– [ ] 是否启用了 etcd 定期快照备份?
– [ ] 是否配置了 Pod 资源限额?
– [ ] 是否安装了日志和监控组件?


下期预告

第 3 天(重访) 将深入探讨 Pod 进阶设计模式,包括 Init Container、Sidecar 模式、Security Context 与 Pod Security Standards,以及高级调度约束(NodeSelector / NodeName / Tolerations)。敬请期待!


系列目录

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容