1. 为什么需要高可用K8s集群?
三年前我负责的一个电商项目在双十一大促时遭遇了惨痛教训。当时我们使用的是单Master节点的K8s集群,结果Master节点所在物理机硬盘故障,导致整个集群控制平面瘫痪超过4小时。正是这次事故让我深刻认识到生产环境必须部署高可用集群的重要性。
高可用K8s集群的核心价值在于消除单点故障(SPOF)。当采用3Master架构时:
- 任何一个Master节点宕机时,剩余两个节点仍能维持集群的正常运转
- etcd采用Raft共识算法,可以容忍(N-1)/2个节点故障(3节点集群允许1个节点故障)
- 控制平面组件(API Server、Controller Manager、Scheduler)采用Leader选举机制,故障时自动切换
重要提示:生产环境强烈建议Master节点数量为奇数(3/5/7),这是由分布式共识算法特性决定的。偶数节点(如2/4)反而可能降低可用性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与系统配置
2.1 硬件资源规划
我这次实验使用的是三台Ubuntu 22.04 LTS服务器,具体配置如下:
| 节点类型 | vCPU | 内存 | 磁盘 | 数量 | 备注 |
|---|---|---|---|---|---|
| Master | 4核 | 8GB | 100GB | 3 | 需要稳定网络 |
| Worker | 8核 | 16GB | 200GB | 2 | 可动态扩展 |
实际生产环境中,建议Master节点:
- 至少2核4GB内存(资源不足会导致控制平面不稳定)
- 使用SSD存储(etcd对磁盘IOPS要求较高)
- 部署在独立的物理机或专用虚拟机(避免资源争抢)
2.2 系统基础配置
在所有节点上执行以下初始化操作:
bash复制# 关闭swap(K8s 1.8+要求)
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
# 设置时区同步
sudo timedatectl set-timezone Asia/Shanghai
sudo apt install -y chrony
sudo systemctl enable --now chronyd
# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置内核参数
cat <<EOF | sudo 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
sudo sysctl --system
3. 证书体系全链路解析
3.1 K8s证书架构全景图
K8s的证书体系犹如一座精密的瑞士钟表,每个齿轮都严丝合缝。主要包含以下几类证书:
-
CA根证书:整个集群信任的锚点
- 通常由集群管理员自签
- 用于签发其他所有证书
-
API Server证书:
- 包含所有Master节点IP、Service网段第一个IP
- 必须包含常用别名(如kubernetes.default.svc)
-
客户端证书:
- kube-controller-manager
- kube-scheduler
- kube-proxy
- 各Node节点kubelet
-
Peer证书:用于etcd节点间通信
3.2 双向认证工作原理
双向TLS认证(mTLS)过程就像两个陌生人在秘密接头:
-
客户端出示自己的证书(证明"我是我")
-
服务端验证:
- 证书是否由可信CA签发
- 证书是否在有效期内
- CN(Common Name)和O(Organization)是否符合预期
-
服务端出示自己的证书
-
客户端进行同样验证
在K8s中,以下通信默认启用mTLS:
- etcd集群成员间
- API Server与etcd
- API Server与kubelet
- Controller Manager/Scheduler与API Server
3.3 证书生成实战
使用cfssl工具链生成证书(比openssl更友好):
bash复制# 安装cfssl
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl_1.6.3_linux_amd64 -O /usr/local/bin/cfssl
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssljson_1.6.3_linux_amd64 -O /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl*
# CA配置
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "87600h"
}
}
}
}
EOF
# 生成CA证书
cat > ca-csr.json <<EOF
{
"CN": "Kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "Beijing",
"O": "Kubernetes",
"OU": "CA",
"ST": "Beijing"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
经验之谈:证书有效期不宜过短(建议1年),否则轮换会很痛苦。但也不建议超过2年,安全风险会增加。
4. 高可用集群部署实战
4.1 负载均衡配置
高可用架构的关键是为API Server提供负载均衡。我使用HAProxy+Keepalived方案:
bash复制# 在所有Master节点安装
sudo apt install -y haproxy keepalived
# HAProxy配置示例(/etc/haproxy/haproxy.cfg)
frontend k8s-api
bind *:6443
mode tcp
option tcplog
default_backend k8s-api
backend k8s-api
mode tcp
option tcp-check
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
# Keepalived配置(/etc/keepalived/keepalived.conf)
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
vrrp_instance VI_1 {
interface ens160
state MASTER # 其他节点设为BACKUP
virtual_router_id 51
priority 100 # BACKUP节点设为90,80
virtual_ipaddress {
192.168.1.100/24
}
track_script {
chk_haproxy
}
}
4.2 使用kubeadm初始化集群
在第一个Master节点执行:
bash复制sudo kubeadm init \
--control-plane-endpoint "192.168.1.100:6443" \
--upload-certs \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12 \
--image-repository registry.aliyuncs.com/google_containers
# 记录输出的join命令,类似:
kubeadm join 192.168.1.100:6443 --token xxx \
--discovery-token-ca-cert-hash sha256:xxx \
--control-plane --certificate-key xxx
4.3 加入其他控制平面节点
在其他两个Master节点执行前面记录的join命令。关键点:
- 必须包含
--control-plane参数 --certificate-key有效期2小时,超时需要重新生成- 加入过程会自动部署etcd成员和control plane组件
验证集群状态:
bash复制kubectl get nodes -o wide
kubectl get pods -n kube-system -o wide
5. 关键问题排查指南
5.1 证书相关错误
现象:API Server日志报"x509: certificate signed by unknown authority"
排查步骤:
- 检查所有组件使用的CA证书是否一致
bash复制
diff /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/apiserver.crt - 验证证书有效期
bash复制openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -dates - 检查证书包含的IP/DNS是否齐全
5.2 网络连通性问题
现象:Node状态为NotReady,kubelet日志报"node not found"
排查步骤:
- 检查Node与API Server VIP的网络连通性
bash复制
curl -k https://192.168.1.100:6443/version - 验证kubelet证书是否有效
bash复制
openssl verify -CAfile /etc/kubernetes/pki/ca.crt /var/lib/kubelet/pki/kubelet-client-current.pem - 检查防火墙规则
bash复制
iptables -L -n | grep 6443
5.3 etcd集群健康检查
bash复制# 在任一Master节点执行
ETCDCTL_API=3 etcdctl \
--endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint health
预期输出应显示所有etcd节点均为healthy状态。
6. 生产环境优化建议
经过多次生产部署,我总结出以下优化经验:
-
证书管理:
- 使用cert-manager自动管理证书轮换
- 为不同组件创建独立的Intermediate CA
-
etcd调优:
yaml复制# /etc/kubernetes/manifests/etcd.yaml - --heartbeat-interval=500 - --election-timeout=2500 - --snapshot-count=10000 - --max-request-bytes=157286400 -
API Server参数:
yaml复制# /etc/kubernetes/manifests/kube-apiserver.yaml - --max-mutating-requests-inflight=600 - --max-requests-inflight=1200 - --target-ram-mb=4096 -
监控方案:
- 使用Prometheus Operator监控集群
- 关键指标告警:
- etcd leader变更次数
- API Server延迟百分位
- 证书到期时间
-
备份策略:
bash复制# 每日etcd快照 ETCDCTL_API=3 etcdctl snapshot save snapshot.db \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key
最后提醒:高可用集群不是一劳永逸的,需要定期:
- 检查证书有效期(建议设置日历提醒)
- 测试故障转移(随机停止Master节点观察恢复情况)
- 更新K8s版本(每季度评估一次)
