
在云原生时代,Kubernetes已成为容器编排的事实标准。对于生产环境,集群的高可用性(HA)是刚性需求——控制平面必须容忍节点故障,确保API服务连续性。本文不空谈理论,而是基于腾讯云CVM与CLB(云负载均衡器),使用kubeadm工具从零部署一套符合生产级标准的Kubernetes高可用集群。全文包含完整命令、配置文件、验证步骤及故障注入测试,技术深度直面一线运维场景。
本文选用堆叠etcd + 3个控制平面节点,兼顾可靠性与部署效率。控制平面通过腾讯云CLB实现四层(TCP)负载均衡,对外暴露一个VIP:6443,所有kubelet和kubectl均通过该VIP访问API Server。
角色 | 主机名 | 内网IP(示例) | 配置要求 |
|---|---|---|---|
控制平面节点1(etcd) | k8s-master-1 | 10.0.1.10 | 4C 8G SSD |
控制平面节点2(etcd) | k8s-master-2 | 10.0.1.11 | 4C 8G SSD |
控制平面节点3(etcd) | k8s-master-3 | 10.0.1.12 | 4C 8G SSD |
工作节点1 | k8s-worker-1 | 10.0.1.20 | 2C 4G |
工作节点2 | k8s-worker-2 | 10.0.1.21 | 2C 4G |
负载均衡器(CLB) | - | 10.0.1.100(VIP) | 腾讯云四层CLB |
操作系统:TencentOS Server 3.1(基于RHEL 8),内核 5.4.119。所有节点需配置SSH免密、主机名解析(/etc/hosts或内网DNS)。
# 关闭swap(kubelet强制要求)
swapoff -a && sed -i '/swap/d' /etc/fstab
# 关闭防火墙(或放行必要端口:6443,2379-2380,10250,10259,10257等)
systemctl stop firewalld && systemctl disable firewalld
# 设置内核参数
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
vm.swappiness = 0
EOF
sysctl --system
# 加载br_netfilter模块
modprobe br_netfilter && lsmod | grep br_netfilter
# 安装基础工具
yum install -y wget curl vim git conntrack-toolsKubernetes 1.26+ 官方推荐使用CRI兼容运行时,这里选用containerd,性能与稳定性优于Docker。
# 安装containerd
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y containerd.io
# 生成默认配置并修改cgroup驱动为systemd(与kubelet一致)
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
# 配置pause镜像加速(腾讯云内网镜像)
sed -i 's/sandbox_image = .*/sandbox_image = "ccr.ccs.tencentyun.com/k8s/pause:3.9"/' /etc/containerd/config.toml
# 启动containerd
systemctl daemon-reload && systemctl enable containerd --now使用腾讯云提供的Kubernetes YUM源(或阿里源),版本锁定为 v1.28.8(当前稳定版)。
cat <<EOF | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.tencent.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.tencent.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.tencent.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install -y kubeadm-1.28.8 kubelet-1.28.8 kubectl-1.28.8 --disableexcludes=kubernetes
systemctl enable kubelet --now注意:此时kubelet启动会报错(未加入集群),属正常现象,后续初始化后自动恢复。
登录腾讯云控制台,购买内网四层CLB(带宽按需,推荐500Mbps以上),监听器配置如下:
记录CLB的VIP(例如 10.0.1.100)和监听器ID(后续用于API Server的--advertise-address?实际我们使用--control-plane-endpoint)。
在/etc/hosts中添加:
10.0.1.100 apiserver.cluster.local后续kubeadm初始化使用apiserver.cluster.local:6443作为控制平面端点。
使用kubeadm config print init-defaults生成基础模板,按需修改。关键参数:
# init-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 10.0.1.10 # 本机内网IP
bindPort: 6443
nodeRegistration:
name: k8s-master-1
criSocket: unix:///var/run/containerd/containerd.sock
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: v1.28.8
controlPlaneEndpoint: "apiserver.cluster.local:6443" # CLB VIP域名
apiServer:
extraArgs:
bind-address: 0.0.0.0
# 启用etcd健康检查等
certSANs:
- apiserver.cluster.local
- 10.0.1.100 # CLB VIP
- 127.0.0.1
- 10.0.1.10
- 10.0.1.11
- 10.0.1.12
controllerManager:
extraArgs:
bind-address: 0.0.0.0
scheduler:
extraArgs:
bind-address: 0.0.0.0
etcd:
local:
dataDir: /var/lib/etcd
extraArgs:
listen-client-urls: https://0.0.0.0:2379
advertise-client-urls: https://10.0.1.10:2379
listen-peer-urls: https://0.0.0.0:2380
initial-advertise-peer-urls: https://10.0.1.10:2380
initial-cluster: k8s-master-1=https://10.0.1.10:2380,k8s-master-2=https://10.0.1.11:2380,k8s-master-3=https://10.0.1.12:2380
initial-cluster-state: new
initial-cluster-token: etcd-cluster-1
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd关键说明:
controlPlaneEndpoint指向CLB域名,所有kubelet和组件通过该地址访问API Server,实现负载均衡。certSANs必须包含CLB VIP和域名,否则API Server证书不认可该地址,导致连接拒绝。initial-cluster需列出全部3个控制平面节点,后续加入时自动发现。# 查看所需镜像
kubeadm config images list --config=init-config.yaml
# 使用腾讯云镜像仓库拉取(替换registry)
kubeadm config images pull --config=init-config.yaml --image-repository=ccr.ccs.tencentyun.com/k8skubeadm init --config=init-config.yaml --upload-certs初始化成功后,输出包含:
/etc/kubernetes/admin.conf)保存输出内容,尤其是--certificate-key,用于后续控制平面节点加入。
mkdir -p $HOME/.kube
cp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config验证集群状态:
kubectl get nodes # 仅master-1,状态NotReady(未安装CNI)
kubectl get pods -n kube-system # etcd、apiserver等均Running在master-2上执行(使用初始化输出的join命令):
kubeadm join apiserver.cluster.local:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <cert-key> \
--node-name k8s-master-2master-3同理,替换--node-name k8s-master-3。
注意:join时需保证etcd的
initial-cluster已包含新节点?实际上kubeadm会自动将新etcd成员加入现有集群,无需提前修改配置,但需确保节点间网络互通且/etc/hosts解析所有主机名。
# 在任一控制平面节点执行
kubectl exec -n kube-system etcd-k8s-master-1 -- etcdctl --endpoints=https://10.0.1.10:2379,https://10.0.1.11:2379,https://10.0.1.12:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint health预期所有端点返回 healthy。
查看kube-system pod分布:
kubectl get pods -n kube-system -o wide | grep -E 'apiserver|controller-manager|scheduler'每个组件应有3个副本,分别调度在不同控制平面节点上。
集群内部通信必须依赖CNI。选用Calico,支持网络策略,性能优秀。
# 安装Calico operator和资源
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
# 等待所有pod Running
kubectl wait --for=condition=Ready pods --all -n calico-system --timeout=300s检查节点状态:
kubectl get nodes # 全部Ready在worker-1、worker-2上执行工作节点join命令(初始化输出中的worker join命令,不含--control-plane):
kubeadm join apiserver.cluster.local:6443 --token <token> \
--discovery-token-ca-cert-hash sha256:<hash> \
--node-name k8s-worker-1验证:
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP
k8s-master-1 Ready control-plane ... v1.28.8 10.0.1.10
k8s-master-2 Ready control-plane ... v1.28.8 10.0.1.11
k8s-master-3 Ready control-plane ... v1.28.8 10.0.1.12
k8s-worker-1 Ready <none> ... v1.28.8 10.0.1.20
k8s-worker-2 Ready <none> ... v1.28.8 10.0.1.21在master-1执行shutdown -h now(或直接kill apiserver进程)。然后从任意机器通过kubectl访问集群(使用CLB VIP):
kubectl get nodes --kubeconfig=/etc/kubernetes/admin.conf # 依然正常返回停止master-1上的etcd容器(或直接关机),然后检查etcd集群成员:
kubectl exec -n kube-system etcd-k8s-master-2 -- etcdctl member list可以看到故障节点状态为unstarted,但集群仍保持多数(2/3存活),读写正常。
删除当前leader的controller-manager pod,观察是否快速切换到其他节点:
kubectl delete pod -n kube-system kube-controller-manager-k8s-master-1
kubectl get lease -n kube-system kube-controller-manager -o yaml # 查看holderIdentity变化所有测试应显示业务无感知,API服务持续可用。
启用API Server审计日志,配置审计策略,将日志输出到腾讯云CLS(日志服务):
apiServer:
extraArgs:
audit-policy-file: /etc/kubernetes/audit-policy.yaml
audit-log-path: /var/log/audit/kube-apiserver-audit.log
audit-log-maxage: "30"
audit-log-maxbackup: "10"
audit-log-maxsize: "100"为命名空间设置ResourceQuota,防止资源争抢。
结合腾讯云CVM伸缩组,部署Cluster Autoscaler,根据Pod pending状态自动增减节点。
通过Helm部署kube-prometheus-stack,采集控制平面组件指标,设置告警规则(如etcd leader变更频繁、apiserver请求延迟超过阈值)。
解决:检查etcd的initial-cluster配置是否包含所有节点,且节点间2380端口互通;查看etcd日志 kubectl logs -n kube-system etcd-xxx。
解决:在初始化时certSANs漏掉了CLB IP或域名,需要重新生成证书(使用kubeadm certs renew并修改--cert-san)或重新初始化。
解决:检查calico是否依赖/etc/cni/net.d配置,或Pod CIDR是否与VPC路由冲突。可调整Calico的IP池为10.244.0.0/16或其他不重叠段。
本文详细演示了基于kubeadm + 腾讯云CLB构建Kubernetes高可用集群的完整流程,涵盖了从系统初始化、组件配置、负载均衡集成、集群扩容到故障验证的全链路实践。该方案已在多家企业的腾讯云生产环境中稳定运行,经受住了节点宕机、网络分区等故障考验。希望这篇文章能为你的云原生基础设施落地提供可靠参考。后续可继续探索服务网格(Istio)、GitOps(ArgoCD)等高级主题,构建完整的应用交付体系。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。