1. ETCD集群证书体系深度解析
在Kubernetes集群中,ETCD作为分布式键值存储数据库,承担着整个集群状态存储的核心角色。而证书体系则是保障ETCD集群通信安全的关键机制。我们先来全面拆解ETCD的证书架构。
1.1 证书类型与作用详解
ETCD集群涉及四种核心证书,每种都有其特定的安全职责:
CA证书(ca.crt/ca.key):证书体系的信任锚点,所有其他证书的合法性都基于CA证书验证。私钥必须严格保护,一旦泄露将导致整个证书体系崩溃。
Peer证书(peer.crt/peer.key):用于节点间的相互认证。当ETCD节点之间进行数据同步、leader选举等内部通信时,双方会通过peer证书验证对方身份。
Server证书(server.crt/server.key):用于客户端到ETCD的服务认证。当kube-apiserver等客户端连接ETCD时,ETCD会出示此证书证明自己的合法身份。
Healthcheck证书(healthcheck-client.crt/.key):专门用于健康检查操作的客户端证书。etcdctl等工具使用此证书进行存活状态检查,权限通常仅限于健康检查API。
关键安全原则:不同用途的证书应该严格分离。peer证书不应被用于客户端认证,反之亦然。这种职责分离能有效限制凭证泄露的影响范围。
1.2 证书内容深度检查
CA证书验证实操
验证CA证书的自签名特性是确认证书完整性的第一步:
openssl verify -CAfile /etc/kubernetes/pki/etcd/ca.crt /etc/kubernetes/pki/etcd/ca.crt预期应返回"OK",表示证书能通过自身验证。如果失败,说明证书可能被篡改或损坏。
查看CA证书详细内容时,需要特别关注:
openssl x509 -in /etc/kubernetes/pki/etcd/ca.crt -noout -text重点关注:
- Validity时间段(Not Before/After):确保证书在有效期内
- X509v3扩展项:必须包含
CA:TRUE标记和Certificate Sign用途 - 公钥算法与长度:现代标准应使用RSA 2048位或ECDSA P-256
Peer/Server证书关键检查点
对于peer和server证书,除了常规的CA链验证外,必须检查Subject Alternative Name(SAN):
openssl x509 -in peer.crt -text -noout | grep -A1 "Subject Alternative Name"输出应包含该节点的:
- 所有合法DNS名称(如节点主机名、localhost等)
- 所有使用IP地址(包括IPv4和IPv6) 缺少必要的SAN会导致TLS握手失败,这是证书配置中最常见的错误之一。
2. 证书生成方案全攻略
2.1 手动生成证书流程
CA证书准备
CA证书必须在所有节点保持一致。建议从正常节点拷贝:
scp root@healthy-node:/etc/kubernetes/pki/etcd/{ca.crt,ca.key} /etc/kubernetes/pki/etcd/完成后务必验证文件一致性:
# 在各节点执行以下命令,输出的MD5应该相同 openssl x509 -noout -modulus -in /etc/kubernetes/pki/etcd/ca.crt | openssl md5 openssl rsa -noout -modulus -in /etc/kubernetes/pki/etcd/ca.key | openssl md5生成节点证书
- 创建证书签名请求(CSR)配置文件:
cat > /etc/kubernetes/csr.conf <<EOF [req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [v3_req] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth subjectAltName = @alt_names [alt_names] DNS.1 = ${HOSTNAME} DNS.2 = localhost IP.1 = ${NODE_IP} IP.2 = 127.0.0.1 IP.3 = ::1 EOF- 生成peer证书:
openssl genrsa -out /etc/kubernetes/pki/etcd/peer.key 2048 openssl req -new -key peer.key \ -out /etc/kubernetes/pki/etcd/peer.csr \ -subj "/CN=${HOSTNAME}" \ -config /etc/kubernetes/csr.conf openssl x509 -req -in peer.csr \ -CA /etc/kubernetes/pki/etcd/ca.crt \ -CAkey /etc/kubernetes/pki/etcd/ca.key \ -CAcreateserial \ -out /etc/kubernetes/pki/etcd/peer.crt \ -days 3650 \ -extensions v3_req \ -extfile /etc/kubernetes/csr.conf- 设置严格的文件权限:
chmod 600 /etc/kubernetes/pki/etcd/*.key chown root:root /etc/kubernetes/pki/etcd/*.{crt,key}2.2 kubeadm自动生成方案
kubeadm提供了更便捷的证书管理方式,适合标准Kubernetes部署:
- 准备kubeadm配置文件:
apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration etcd: local: serverCertSANs: - "${NODE_IP}" - "${HOSTNAME}" peerCertSANs: - "${NODE_IP}" - "${HOSTNAME}"- 一键生成所有证书:
kubeadm init phase certs etcd-server --config=/etc/kubernetes/kubeadm-config.yaml kubeadm init phase certs etcd-peer --config=/etc/kubernetes/kubeadm-config.yaml kubeadm init phase certs etcd-healthcheck-client --config=/etc/kubernetes/kubeadm-config.yaml经验之谈:生产环境中,建议将证书有效期设置为1年(365天),并建立定期轮换机制。虽然示例中使用3650天(10年)方便演示,但长期不更换证书会带来安全风险。
3. ETCD节点重建实战手册
3.1 安全移除故障节点
- 首先检查集群状态:
ETCDCTL_API=3 etcdctl \ --endpoints=https://${HEALTHY_NODE_IP}:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ endpoint health- 获取节点ID:
ETCDCTL_API=3 etcdctl \ --endpoints=https://${HEALTHY_NODE_IP}:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ member list -w simple- 移除故障节点(以节点ID 669b91f5ce3f1e81为例):
ETCDCTL_API=3 etcdctl \ --endpoints=https://${HEALTHY_NODE_IP}:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/peer.crt \ --key=/etc/kubernetes/pki/etcd/peer.key \ member remove 669b91f5ce3f1e81关键细节:移除成员操作必须在健康节点上执行,使用peer证书而非healthcheck证书,因为这是集群管理操作。
3.2 节点数据清理
在待重建节点上执行:
systemctl stop kubelet rm -rf /var/lib/etcd/member/注意:
- 必须停止kubelet,否则etcd容器可能自动重启
- 删除member目录而非整个etcd目录,保留wal日志等可能有助于故障诊断
3.3 重新加入集群
- 在健康节点上执行添加操作:
ETCDCTL_API=3 etcdctl \ --endpoints=https://${HEALTHY_NODE_IP}:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/peer.crt \ --key=/etc/kubernetes/pki/etcd/peer.key \ member add ${NEW_NODE_NAME} \ --peer-urls=https://${NEW_NODE_IP}:2380- 记录输出的初始集群配置,形如:
ETCD_INITIAL_CLUSTER="crust-m01=https://10.10.239.201:2380,crust-m02=https://10.10.239.202:2380,crust-m03=https://10.10.239.203:2380"- 在待加入节点上配置etcd启动参数(通常在/etc/kubernetes/manifests/etcd.yaml):
spec: containers: - command: - etcd - --initial-cluster=${ETCD_INITIAL_CLUSTER} - --initial-cluster-state=existing- 启动etcd服务:
systemctl start kubelet排错技巧:如果节点无法加入,检查防火墙是否放行了2380端口(peer通信)和2379端口(client通信)。使用tcpdump可以验证网络连通性:
tcpdump -i any port 2380 -nnvvv
4. 证书轮换最佳实践
4.1 安全更换证书流程
- 备份现有证书:
cp -a /etc/kubernetes/pki/etcd /etc/kubernetes/pki/etcd.bak.$(date +%Y%m%d)- 生成新证书(建议使用新文件名):
openssl genrsa -out /etc/kubernetes/pki/etcd/peer-new.key 2048 openssl req -new -key peer-new.key \ -out /etc/kubernetes/pki/etcd/peer-new.csr \ -subj "/CN=${HOSTNAME}" openssl x509 -req -in peer-new.csr \ -CA ca.crt -CAkey ca.key -CAcreateserial \ -out /etc/kubernetes/pki/etcd/peer-new.crt \ -days 365 -extensions v3_req \ -extfile <(printf "[v3_req]\nsubjectAltName=DNS:${HOSTNAME},IP:${NODE_IP}")- 原子替换证书:
mv -f /etc/kubernetes/pki/etcd/peer-new.crt /etc/kubernetes/pki/etcd/peer.crt mv -f /etc/kubernetes/pki/etcd/peer-new.key /etc/kubernetes/pki/etcd/peer.key- 触发etcd重新加载证书:
# 优雅重启etcd容器 mv /etc/kubernetes/manifests/etcd.yaml /tmp/ sleep 10 mv /tmp/etcd.yaml /etc/kubernetes/manifests/4.2 多节点证书轮换策略
对于生产环境,建议采用分阶段轮换:
- 先更换一个follower节点的证书,验证无误
- 间隔24小时后更换第二个节点
- 最后更换leader节点(可通过
etcdctl endpoint status确认leader)
重要提示:在证书轮换期间,确保至少(N/2)+1个节点保持健康(对于3节点集群至少2个),否则集群将无法达成共识。
5. 故障排查与应急方案
5.1 常见错误与解决方案
问题1:etcd日志报"transport: authentication handshake failed"
可能原因:
- 证书SAN不匹配节点实际信息
- 证书已过期
- CA证书不一致
解决方案:
# 检查证书有效期 openssl x509 -in /etc/kubernetes/pki/etcd/peer.crt -noout -dates # 验证证书链 openssl verify -CAfile /etc/kubernetes/pki/etcd/ca.crt /etc/kubernetes/pki/etcd/peer.crt # 检查SAN配置 openssl x509 -in /etc/kubernetes/pki/etcd/peer.crt -text | grep -A1 "Subject Alternative Name"问题2:etcd节点无法加入集群,报"cluster ID mismatch"
可能原因:
- 未清除旧的member数据
- 使用了错误的initial-cluster配置
解决方案:
# 彻底清除旧数据 rm -rf /var/lib/etcd/member/ # 获取最新的cluster配置 ETCDCTL_API=3 etcdctl \ --endpoints=https://${HEALTHY_NODE_IP}:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \ --key=/etc/kubernetes/pki/etcd/healthcheck-client.key \ member list -w simple5.2 灾难恢复预案
当大多数节点故障时,可采用以下步骤恢复:
- 选择数据最新的幸存节点
- 在该节点上执行:
etcd --force-new-cluster \ --data-dir=/var/lib/etcd \ --name=${NODE_NAME} \ --initial-advertise-peer-urls=https://${NODE_IP}:2380 \ --listen-peer-urls=https://${NODE_IP}:2380 \ --listen-client-urls=https://${NODE_IP}:2379,https://127.0.0.1:2379 \ --advertise-client-urls=https://${NODE_IP}:2379- 基于此节点重建集群
最后提醒:任何对etcd的操作都可能影响整个Kubernetes集群的稳定性。建议在维护窗口期进行操作,并确保有完整的备份方案。可以使用etcdctl snapshot save创建定期备份,这是保障数据安全的最重要措施。