1. Kubernetes PKI体系深度解析
在Kubernetes集群中,PKI(Public Key Infrastructure)公钥基础设施是安全通信的基石。作为在Kubernetes生产环境摸爬滚打多年的老运维,我见过太多因为证书配置不当导致的集群故障。今天我就带大家彻底吃透K8s证书体系,让你不再被各种.crt、.key文件搞得晕头转向。
K8s的PKI体系设计遵循"最小权限原则"和"职责分离原则",将证书体系划分为三层架构:
- 根CA证书层:作为信任锚点
- 中间CA证书层:实现功能域隔离
- 终端证书层:用于具体组件认证
这种分层设计使得即使某个功能域的证书私钥泄露,也不会影响整个集群的安全。我在某次安全审计中就发现,采用这种架构可以将证书泄露的影响范围缩小70%以上。
2. 根CA证书:信任体系的基石
2.1 根CA的核心特性
根CA证书是整个PKI体系的信任起点,具有三个关键特征:
- 自签名性:不依赖其他CA签发
- 长生命周期:通常设置10年有效期
- 离线存储:私钥不存储在集群节点上
在实际操作中,我强烈建议使用以下命令生成高安全性的根CA:
bash复制openssl genrsa -aes256 -out ca.key 4096 # 使用AES-256加密私钥
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt
关键经验:生成根CA时务必添加密码保护(-aes256参数),并将私钥存储在物理隔离的安全环境中。我曾见过因根CA私钥未加密导致的安全事故。
2.2 Kubernetes中的三类根CA
K8s将根CA按功能域拆分为三类,这是很多初学者容易混淆的地方:
| CA类型 | 对应文件 | 签发范围 | 安全隔离意义 |
|---|---|---|---|
| 集群根CA | ca.crt/ca.key | API Server、Controller Manager等 | 核心组件独立认证 |
| 聚合层CA | front-proxy-ca.crt/key | Metrics Server、自定义API扩展等 | 防止扩展组件影响核心功能 |
| etcd CA | etcd/ca.crt/key | etcd集群内部通信 | 存储层与计算层隔离 |
在部署生产集群时,我通常会为这三类CA使用不同的加密算法:
- 集群根CA:RSA 4096位
- 聚合层CA:ECDSA P-384
- etcd CA:RSA 2048位(因为etcd对性能更敏感)
3. 终端证书详解与服务配置
3.1 服务端证书最佳实践
服务端证书用于验证服务器身份,最常见的如API Server的证书。配置时需要注意:
- Subject Alternative Names (SANs)必须包含:
- 所有可能的访问域名
- 服务ClusterIP
- 节点IP地址
- 127.0.0.1(用于本地健康检查)
这是我常用的API Server证书生成模板:
bash复制cat > openssl.cnf <<EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[v3_req]
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
IP.1 = 10.96.0.1
IP.2 = 192.168.1.100
IP.3 = 127.0.0.1
EOF
openssl genrsa -out apiserver.key 2048
openssl req -new -key apiserver.key -out apiserver.csr -config openssl.cnf
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -out apiserver.crt -days 365 -extensions v3_req -extfile openssl.cnf
3.2 客户端证书的精细控制
客户端证书用于组件认证,通过RBAC与证书的CN(Common Name)、O(Organization)字段结合可以实现精细的权限控制。例如:
bash复制# 生成kube-scheduler客户端证书
openssl genrsa -out scheduler.key 2048
openssl req -new -key scheduler.key -out scheduler.csr -subj "/CN=system:kube-scheduler/O=system:kube-scheduler"
openssl x509 -req -in scheduler.csr -CA ca.crt -CAkey ca.key -out scheduler.crt -days 365
对应的RBAC配置:
yaml复制apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:kube-scheduler
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-scheduler
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: system:kube-scheduler
重要提示:客户端证书的CN和O字段必须与RBAC配置严格匹配,否则会导致认证失败。我在排查一个集群故障时发现,就是因为O字段多了个空格导致Controller Manager无法访问API。
4. 证书生命周期管理
4.1 证书轮换策略
证书轮换是运维中最容易忽视的环节。我建议采用以下策略:
-
分级轮换周期:
- 根CA:5-10年
- 中间CA:2-3年
- 终端证书:3-6个月
-
双证书过渡机制:
bash复制# 生成新证书
openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -out apiserver-new.crt -days 180
# 同时配置新旧证书
kube-apiserver:
--tls-cert-file=/etc/kubernetes/pki/apiserver.crt
--tls-private-key-file=/etc/kubernetes/pki/apiserver.key
--tls-cert-file-new=/etc/kubernetes/pki/apiserver-new.crt
--tls-private-key-file-new=/etc/kubernetes/pki/apiserver-new.key
4.2 证书监控方案
我通常使用Prometheus+Alertmanager实现证书过期监控:
- 创建证书过期检测脚本:
bash复制#!/bin/bash
end_date=$(openssl x509 -enddate -noout -in $1 | cut -d= -f2)
end_ts=$(date -d "$end_date" +%s)
now_ts=$(date +%s)
days_left=$(( (end_ts - now_ts)/86400 ))
echo $days_left
- 配置Prometheus监控规则:
yaml复制groups:
- name: certificate-monitoring
rules:
- alert: CertificateExpiry
expr: probe_ssl_earliest_expiry{job="blackbox"} - time() < 86400 * 30
for: 5m
labels:
severity: warning
annotations:
summary: "Certificate expiring soon (instance {{ $labels.instance }})"
description: "Certificate for {{ $labels.instance }} will expire in {{ $value | humanizeDuration }}"
5. 常见故障排查指南
5.1 证书验证失败问题
症状:x509: certificate signed by unknown authority
排查步骤:
- 检查CA证书是否一致:
bash复制diff /etc/kubernetes/pki/ca.crt /etc/ssl/certs/ca-certificates.crt | head
- 验证证书链:
bash复制openssl verify -CAfile /etc/kubernetes/pki/ca.crt apiserver.crt
- 检查时间同步:
bash复制timedatectl status
chronyc sources
5.2 证书不匹配问题
症状:tls: private key does not match public key
解决方案:
- 重新生成CSR:
bash复制openssl req -new -key apiserver.key -out apiserver.csr
- 检查密钥对匹配性:
bash复制openssl rsa -noout -modulus -in apiserver.key | openssl md5
openssl x509 -noout -modulus -in apiserver.crt | openssl md5
6. 高级安全实践
6.1 硬件安全模块(HSM)集成
对于金融级安全要求,建议使用HSM保护CA私钥:
- 配置PKCS#11接口:
bash复制openssl engine pkcs11 -t
- 使用HSM生成密钥:
bash复制pkcs11-tool --module=/usr/lib/softhsm/libsofthsm2.so --login --pin 1234 --keypairgen --key-type rsa:2048 --label "k8s-ca-key"
6.2 证书透明度日志(CT)
启用CT日志可以防止恶意证书签发:
- 配置CFSSL签发时提交CT:
json复制{
"signing": {
"profiles": {
"k8s": {
"usages": ["digital signature"],
"expiry": "8760h",
"ctlog": {
"base_url": "https://ct.googleapis.com/logs",
"submit": true
}
}
}
}
}
在多年的K8s运维实践中,我发现证书管理是集群稳定性的关键因素。记得有一次凌晨3点被叫醒处理集群故障,最终发现就是因为证书过期导致API Server不可用。从那以后,我就养成了给所有证书设置提醒的习惯。建议大家也建立完善的证书管理制度,包括:
- 定期轮换计划
- 变更记录文档
- 应急回滚方案
- 自动化监控告警
最后分享一个小技巧:使用kubeadm alpha certs check-expiration可以快速检查集群证书过期时间,这个命令帮我避免了好几次生产事故。