生产级Kubernetes集群部署完全指南:从kubeadm到高可用架构落地

生产级高可用Kubernetes集群的部署,远不是几条kubeadm命令就能搞定的事情。深夜收到报警短信、API Server突然宕机、证书过期导致集群瘫痪,这些场景是每个运维人最不愿面对的噩梦,但往往源于部署时忽略的关键细节。

本文基于Kubernetes官方文档及多个生产环境的踩坑经验,从架构设计到部署实操,完整拆解一个真正可用的高可用集群该如何落地。文章聚焦于堆叠控制平面拓扑这一生产中最常用的方案,同时覆盖外部etcd、负载均衡配置、安全加固和灾备演练等生产级要素,帮助你从零搭建一套经得起考验的集群。

一、架构设计:先想清楚再动手

1.1 两种高可用拓扑的选择

在开始部署之前,需要先确定控制平面的架构方案。kubeadm支持两种高可用拓扑:

堆叠etcd拓扑是最常用的方案。etcd成员与控制平面节点部署在同一台机器上,每个控制平面节点同时运行kube-apiserver、kube-controller-manager、kube-scheduler和一个本地etcd成员。这种方式的优势是基础设施需求少、设置更简单、副本管理更容易。缺点是控制平面节点与etcd成员耦合,单个节点故障时两者同时丢失。

外部etcd拓扑将etcd集群独立部署在控制平面之外的节点上。每个控制平面节点仍然运行API Server、Controller Manager和Scheduler,但etcd成员分布在独立的主机上。这种方案解耦了控制平面和etcd,故障影响范围更小,但需要两倍于堆叠方案的主机数量。对于大多数生产环境,堆叠方案已足够满足需求,本文以此为主线。

1.2 节点规划的最低标准

对于生产级高可用集群,节点规划需要遵循以下原则:

控制平面节点至少3台。控制平面节点数量必须为奇数,这有助于在机器故障或分区故障时进行领导者选举。3台是堆叠方案的最低要求。如果只有2台控制平面节点,在选举时无法形成多数派,集群将无法正常工作。

工作节点至少2台。工作节点用于运行业务Pod,数量根据负载需求决定。生产环境建议至少2台以保证Pod调度的冗余性。

网络要求:所有节点之间必须实现全网络连接,包括控制平面节点之间、控制平面与工作节点之间。通信可以在公网或私网中进行,但所有节点需要能够通过端口6443访问API Server。

1.3 etcd的黄金法则

如果采用外部etcd方案,etcd集群同样需要奇数个节点,至少3台。有以下几条黄金法则需要牢记:

etcd节点必须使用独立磁盘,禁止与其他服务共享磁盘,避免I/O竞争导致心跳超时。

etcd对磁盘性能极为敏感,建议使用SSD。如果跨多个机房部署,考虑5节点配置,将节点分布在3个机房中,例如机房A部署2节点、机房B部署2节点、机房C部署1节点,以避免脑裂问题。

二、环境准备:所有节点的统一操作

以下步骤需要在集群中的每台机器上执行,包括控制平面节点和工作节点。

2.1 系统基础配置

关闭Swap分区是kubelet正常运行的前提条件。Swap会干扰kubelet的内存隔离能力,必须在所有节点上禁用:

bash 复制代码
swapoff -a
sed -i '/swap/d' /etc/fstab

配置主机名和/etc/hosts文件,确保节点之间能够通过主机名互相通信。设置内核参数开启桥接转发和IP转发,这是网络插件正常工作的基础:

bash 复制代码
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

时间同步同样不可忽视,集群中各节点时间差过大会导致证书验证失败。使用chrony或ntpdate确保系统时间一致。

2.2 容器运行时安装

Kubernetes需要容器运行时来运行Pod。containerd是目前最常用的选择,安装后需要配置systemd cgroup驱动:

bash 复制代码
apt install -y containerd   # Ubuntu/Debian
yum install -y containerd   # CentOS/RHEL

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl restart containerd

cgroup驱动配置为systemd,确保与kubelet使用的驱动一致,避免资源管理冲突。

2.3 安装kubeadm、kubelet、kubectl

在所有节点上安装这三个工具,并锁定版本以防止自动升级:

bash 复制代码
# Ubuntu/Debian示例
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/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.32/deb/ /" | tee /etc/apt/sources.list.d/kubernetes.list
apt update
apt install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

建议将kubeadm、kubelet、kubectl的版本与要部署的Kubernetes版本匹配,版本不一致可能导致意外行为。

三、配置API Server负载均衡器

高可用集群的核心是让API Server具备容错能力。所有对API Server的请求,包括kubectl命令和kubelet心跳,都需要通过负载均衡器分发到多个控制平面节点。

3.1 为什么不建议直接使用云厂商HTTP负载均衡器

API Server需要的是TCP层负载均衡,而非HTTP(S)负载均衡。云厂商的HTTP负载均衡器在TCP长连接场景下可能引入不必要的连接中断。健康检查必须配置为API Server的/readyz端点,而非简单的端口检测。

3.2 使用HAProxy + Keepalived搭建本地负载均衡

在控制平面节点上部署HAProxy提供四层TCP转发,Keepalived提供VIP漂移,确保单点故障时的自动切换。

HAProxy配置示例:

bash 复制代码
# /etc/haproxy/haproxy.cfg
frontend k8s-api
    bind *:6443
    mode tcp
    default_backend k8s-api-backend

backend k8s-api-backend
    mode tcp
    balance roundrobin
    option tcp-check
    tcp-check connect port 6443
    tcp-check send GET /readyz HTTP/1.0\r\nHost:\ k8s-api\r\n\r\n
    tcp-check expect string ok
    server master1 192.168.1.11:6443 check
    server master2 192.168.1.12:6443 check
    server master3 192.168.1.13:6443 check

Keepalived配置示例:

bash 复制代码
# /etc/keepalived/keepalived.conf
vrrp_instance VI_1 {
    interface eth0
    state MASTER
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.1.100
    }
}

3.3 验证负载均衡器连通性

在配置完成后,使用以下命令测试VIP是否能正常通信:

bash 复制代码
nc -zv -w 2 <VIP> 6443

连接拒绝是可以预期的,因为API Server尚未启动。但超时则意味着负载均衡器无法与控制平面节点通信,需要重新检查配置。

四、初始化第一个控制平面节点

4.1 kubeadm init命令详解

在第一个控制平面节点上执行初始化命令,关键参数说明如下:

bash 复制代码
sudo kubeadm init \
  --control-plane-endpoint "192.168.1.100:6443" \
  --upload-certs \
  --pod-network-cidr=10.244.0.0/16

control-plane-endpoint必须设置为负载均衡器的地址或DNS和端口,而非某个具体的控制平面节点IP。upload-certs标志将控制平面证书加密并上传到集群中的Secret,供其他控制平面节点加入时下载使用,这是多控制平面自动证书分发的关键。

注意:--config和--certificate-key不能同时使用,如果使用kubeadm配置文件,需要在InitConfiguration中添加certificateKey字段。

4.2 保存join命令输出

初始化成功后,kubeadm会输出两段关键信息:

控制平面节点加入命令,包含token、ca-cert-hash和certificate-key。工作节点加入命令,包含token和ca-cert-hash。

务必将这些命令保存下来,证书密钥可以访问集群敏感数据,需要妥善保管。同时注意,上传的证书在两小时后自动失效,如果超时需要使用kubeadm init phase upload-certs重新上传。

4.3 配置kubectl访问

在第一个控制平面节点上配置kubectl访问集群:

bash 复制代码
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

五、加入其余控制平面节点

每个额外的控制平面节点需要执行与init输出中完全相同的join命令:

bash 复制代码
sudo kubeadm join 192.168.1.100:6443 \
  --token <token> \
  --discovery-token-ca-cert-hash sha256:<hash> \
  --control-plane \
  --certificate-key <certificate-key>

control-plane标志告诉kubeadm要创建一个新的控制平面而非工作节点。certificate-key参数用于从集群的kubeadm-certs Secret中下载控制平面证书并解密。

多个控制平面节点可以并行加入,完成此步骤后,集群已具备3个API Server副本和3个etcd成员的容错能力。

六、安装CNI网络插件

在控制平面初始化后,工作节点加入前,必须部署网络插件,否则Pod无法跨节点通信。

6.1 网络插件选型

Calico是目前最常用的选择,功能全面,支持网络策略。适用于对安全策略和网络隔离要求较高的生产环境。

Flannel配置简单,适合对网络策略要求不高的场景。需确保Flannel的Pod CIDR与kubeadm init时指定的--pod-network-cidr一致。

Cilium是基于eBPF的新一代网络方案,在性能要求极高的场景中表现出色。某游戏公司从Calico迁移至Cilium后,网络延迟降低40%。但引入Cilium后建议关闭kube-proxy,并使用kubeProxyReplacement=strict。

6.2 部署Calico

bash 复制代码
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

6.3 验证控制平面组件状态

部署网络插件后,查看控制平面组件的Pod状态,确保所有组件正常启动:

bash 复制代码
kubectl get pod -n kube-system -w

七、加入工作节点

在工作节点上执行init输出中提供的工作节点join命令:

bash 复制代码
kubeadm join 192.168.1.100:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

工作节点加入时不使用control-plane标志。token过期后可以通过kubeadm token create --print-join-command重新生成。

八、验证集群高可用性

8.1 集群状态检查

bash 复制代码
kubectl get nodes
# 应看到所有控制平面节点状态为Ready,所有工作节点状态为Ready

kubectl get pods -n kube-system
# 应看到控制平面组件和网络插件的Pod均为Running状态

8.2 控制平面故障演练

在VIP所在的控制平面节点上停止kubelet,观察VIP是否漂移到其他控制平面节点:

bash 复制代码
systemctl stop kubelet
# 检查VIP是否漂移
ip addr show | grep <VIP>

随后执行kubectl get nodes验证集群是否仍然可用。恢复kubelet后节点应重新加入集群。

九、生产环境的关键补充

9.1 证书生命周期管理

kubeadm默认签发的证书有效期为一年,过期将导致集群瘫痪。生产环境中必须关注证书续期:

bash 复制代码
# 检查证书过期时间
kubeadm certs check-expiration

# 手动续期所有证书
kubeadm certs renew all

使用cert-manager实现证书自动管理是更稳妥的长期方案。

9.2 安全加固要点

禁用匿名访问:在kube-apiserver启动参数中添加--anonymous-auth=false。

RBAC精细化控制:避免将cluster-admin角色授予普通开发人员,按照命名空间分配最小权限。使用Role和RoleBinding定义具体命名空间内的操作权限,ClusterRole和ClusterRoleBinding仅用于需要跨命名空间管理的场景。

审计日志:记录所有敏感操作,包括对Secret的delete和patch操作,便于事后追溯。

9.3 监控与灾备

部署Prometheus + Grafana监控集群状态,关键指标包括API Server请求延迟、etcd磁盘同步延迟、节点CPU和内存使用率等。同时制定etcd备份计划,定期备份etcd数据是灾难恢复的最后防线。

十、常见问题排查

证书过期:集群突然不可用,kubectl报错证书过期。解决方案:使用kubeadm certs renew all续期所有证书,或通过cert-manager自动管理。

API Server健康检查失败:负载均衡器无法识别API Server的存活状态。解决方案:检查负载均衡器的健康检查配置,确保使用/readyz端点而不是简单的端口检测。配置tcp-check命令发送GET /readyz请求并期望返回ok。

etcd性能问题:etcd节点磁盘I/O竞争导致心跳超时。解决方案:为etcd节点配置独立SSD磁盘,禁止与其他服务共享磁盘。etcd的磁盘性能直接决定集群的稳定性。

Pod跨节点通信失败:网络插件未正确部署。解决方案:确保网络插件已成功部署且Pod处于Running状态。检查CNI配置文件是否正确生成,确认Pod CIDR与kubeadm init时指定的值一致。

结语

生产级高可用Kubernetes集群的搭建,关键不在于命令本身,而在于部署前对架构的充分思考和对细节的极致把控。从节点规划到负载均衡,从证书管理到灾备演练,每一个环节都可能在业务高峰时成为引发故障的薄弱点。

本文覆盖了堆叠etcd拓扑的完整部署流程,但对于超大规模集群或特殊场景,外部etcd、二进制部署、跨可用区容灾等方案同样值得深入研究。记住,真正稳定的集群不是靠某个工具获得的,而是靠对细节的敬畏和持续的迭代优化沉淀下来的。

相关推荐
瞬间&永恒~2 小时前
【Docker】(三)联合文件系统UnionFS + Overlay2
docker·云原生·容器
Embedded-Xin2 小时前
Rust学习——Cargo工具
linux·学习·架构·rust·嵌入式
xcLeigh3 小时前
KingbaseES 的卢智能运维体架构深度拆解
运维·数据库·人工智能·ai·架构·ffmpeg·智能体
人生百态,人生如梦4 小时前
每日论文解读 (8.3) 1——DeepResearch Agent System:稀疏激活架构驱动的自主深度研究Agent
架构·llm·agent·deepresearch
逐光老顽童6 小时前
第 5 章:搞懂 K8s Service:从 ClusterIP 到负载均衡
docker·云原生·容器
anyup6 小时前
uni-app 没有根组件?仅需几行代码实现全局 Toast 和 Modal
前端·架构·uni-app
会博通·代码搬运工6 小时前
会博通API对接实战:工程企业文档分布式采集系统的技术实现与Python SDK详解
开发语言·分布式·python·线性代数·矩阵·架构·电子档案合规
运维大师7 小时前
【K8S 运维实战】34-多集群管理Karmada
java·运维·kubernetes