Kubernetes 证书体系与 OpenSSL 命令全解析
📁 一、Kubernetes 证书目录结构
1.1 核心证书目录(Master节点)
/etc/kubernetes/pki/
├── apiserver.crt # API Server 服务端证书
├── apiserver.key # API Server 私钥
├── apiserver-kubelet-client.crt # API Server 访问 kubelet 的客户端证书
├── apiserver-kubelet-client.key
├── ca.crt # 集群根证书(CA证书)
├── ca.key # CA私钥(最敏感)
├── etcd/ # etcd 相关证书
│ ├── ca.crt
│ ├── ca.key
│ ├── healthcheck-client.crt
│ ├── healthcheck-client.key
│ ├── peer.crt
│ ├── peer.key
│ ├── server.crt
│ └── server.key
├── front-proxy-ca.crt # 前端代理CA
├── front-proxy-ca.key
├── front-proxy-client.crt # 前端代理客户端证书
├── front-proxy-client.key
├── sa.key # Service Account 私钥
└── sa.pub # Service Account 公钥
1.2 组件证书位置
| 组件 | 证书位置 | 用途 |
|---|---|---|
| kube-apiserver | /etc/kubernetes/pki/ |
服务端认证 |
| kube-controller-manager | /etc/kubernetes/pki/ |
客户端证书 |
| kube-scheduler | /etc/kubernetes/pki/ |
客户端证书 |
| kubelet | /var/lib/kubelet/pki/ |
节点证书 |
| etcd | /etc/kubernetes/pki/etcd/ |
etcd集群通信 |
| kube-proxy | /var/lib/kube-proxy/ |
客户端证书 |
1.3 证书内嵌(Embedded Certs)机制
Kubernetes 支持将证书内容直接嵌入到 kubeconfig 文件中,避免文件路径依赖:
bash
# 生成内嵌证书的 kubeconfig
kubectl config set-credentials user \
--client-certificate=user.crt \
--client-key=user.key \
--embed-certs=true # 关键参数:内嵌证书内容
内嵌 vs 文件路径:
- 内嵌优点:配置文件自包含,便于分发和迁移
- 内嵌缺点:配置文件变大,证书更新需要重新生成
- 文件路径优点:证书更新时无需修改 kubeconfig
- 文件路径缺点:路径依赖,部署环境需保持一致
1.4 证书轮换目录机制
Kubernetes 支持自动证书轮换,相关目录:
/var/lib/kubelet/pki/
├── kubelet-client-current.pem -> kubelet-client-2025-01-21-12-34-56.pem # 符号链接
├── kubelet-client-2025-01-21-12-34-56.pem # 实际证书文件
├── kubelet.crt
└── kubelet.key
轮换过程:
- kubelet 定期检查证书过期时间
- 自动向 API Server 申请新证书
- 创建新证书文件,更新符号链接
- 重启相关服务(部分组件支持热重载)
📄 二、证书格式与内容解析
2.1 证书文件格式
Kubernetes 主要使用两种格式:
| 格式 | 扩展名 | 说明 | 查看命令 |
|---|---|---|---|
| PEM | .crt, .pem |
Base64编码的文本格式 | cat cert.crt |
| DER | .der |
二进制格式 | openssl x509 -in cert.der -inform der -text |
2.2 证书内容结构
一个标准的 X.509 证书包含:
bash
# 查看证书详细信息
openssl x509 -in cert.crt -text -noout
# 输出示例:
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1234567890 (0x499602d2)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = kubernetes-ca # 颁发者
Validity
Not Before: Jan 21 00:00:00 2026 GMT
Not After : Jan 20 23:59:59 2027 GMT # 有效期
Subject: CN = system:node:node1 # 主题(标识身份)
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Subject Alternative Name: # SAN扩展
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc...
2.3 关键字段说明
| 字段 | 说明 | Kubernetes 中的典型值 |
|---|---|---|
| Issuer | 证书颁发者 | CN=kubernetes-ca |
| Subject | 证书持有者 | CN=system:node:node1(节点) CN=system:kube-controller-manager(组件) CN=readonly-user(用户) |
| SAN | 主题备用名称 | 包含 API Server 的 DNS 名称和 IP |
| Key Usage | 密钥用途 | Digital Signature, Key Encipherment |
| Extended Key Usage | 扩展密钥用途 | TLS Web Server Authentication(服务端) TLS Web Client Authentication(客户端) |
2.4 私钥格式
私钥同样有 PEM 和 DER 格式,通常使用 RSA 或 ECDSA 算法:
bash
# 查看私钥信息
openssl rsa -in private.key -text -noout
# 输出示例:
Private-Key: (2048 bit)
modulus:
00:aa:bb:cc:...
publicExponent: 65537 (0x10001)
privateExponent:
00:dd:ee:ff:...
🔧 三、OpenSSL 常用命令大全
3.1 证书生成流程(完整示例)
步骤1:生成私钥
bash
# 生成 2048 位 RSA 私钥
openssl genrsa -out user.key 2048
# 生成 ECDSA 私钥(更安全,更小)
openssl ecparam -genkey -name prime256v1 -out user.key
步骤2:创建证书签名请求(CSR)
bash
# 创建 CSR,CN 字段标识用户身份
openssl req -new -key user.key -out user.csr \
-subj "/CN=readonly-user"
# 带 SAN 扩展的 CSR(用于服务端证书)
cat > csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kubernetes
[ req_ext ]
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 = 192.168.124.134
EOF
openssl req -new -key server.key -out server.csr -config csr.conf
步骤3:使用 CA 签署证书
bash
# 使用集群 CA 签署证书(有效期365天)
openssl x509 -req -in user.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out user.crt \
-days 365
# 带扩展的签署
openssl x509 -req -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 \
-extfile csr.conf -extensions req_ext
3.2 证书查看与验证命令
查看证书信息
bash
# 查看证书内容(文本格式)
openssl x509 -in cert.crt -text -noout
# 查看证书有效期
openssl x509 -in cert.crt -dates -noout
# 查看证书序列号
openssl x509 -in cert.crt -serial -noout
# 查看证书指纹
openssl x509 -in cert.crt -fingerprint -noout
# 查看证书主题和颁发者
openssl x509 -in cert.crt -subject -issuer -noout
验证证书链
bash
# 验证证书是否由指定 CA 签发
openssl verify -CAfile ca.crt user.crt
# 验证证书链(多级CA)
openssl verify -CAfile root-ca.crt -untrusted intermediate-ca.crt user.crt
检查私钥
bash
# 查看私钥信息
openssl rsa -in private.key -text -noout
# 检查私钥是否匹配证书
openssl x509 -in cert.crt -pubkey -noout > cert.pub
openssl rsa -in private.key -pubout > key.pub
diff cert.pub key.pub # 应该相同
3.3 证书转换命令
bash
# PEM 转 DER
openssl x509 -in cert.pem -outform der -out cert.der
# DER 转 PEM
openssl x509 -in cert.der -inform der -out cert.pem
# 从证书提取公钥
openssl x509 -in cert.crt -pubkey -noout > public.key
# 从私钥提取公钥
openssl rsa -in private.key -pubout -out public.key
3.4 证书格式检查
bash
# 检查文件是否为有效的 PEM 证书
openssl x509 -in file.crt -text -noout >/dev/null 2>&1 && echo "Valid" || echo "Invalid"
# 检查文件是否为有效的私钥
openssl rsa -in file.key -check -noout >/dev/null 2>&1 && echo "Valid" || echo "Invalid"
# 检查证书和私钥是否匹配
openssl x509 -noout -modulus -in cert.crt | openssl md5
openssl rsa -noout -modulus -in private.key | openssl md5
# 两个 MD5 值应该相同
🔄 四、证书轮换与更新
4.1 手动证书轮换流程
bash
# 1. 生成新证书(使用相同 CN)
openssl req -new -key user.key -out user-new.csr -subj "/CN=readonly-user"
openssl x509 -req -in user-new.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out user-new.crt -days 365
# 2. 验证新证书
openssl verify -CAfile ca.crt user-new.crt
# 3. 替换证书文件(注意权限)
cp user-new.crt user.crt
chmod 600 user.crt
# 4. 重启相关服务(部分组件支持热重载)
systemctl restart kube-apiserver # 或相关组件
4.2 自动证书轮换(kubelet)
kubelet 支持自动证书轮换,配置参数:
yaml
# /var/lib/kubelet/config.yaml
rotateCertificates: true
certificateRotationDuration: 8760h # 1年
4.3 检查证书过期时间
bash
# 检查单个证书过期时间
openssl x509 -in cert.crt -enddate -noout
# 批量检查目录下所有证书
find /etc/kubernetes/pki -name "*.crt" -exec sh -c 'echo "=== $1 ==="; openssl x509 -enddate -noout -in "$1"' sh {} \;
# 使用 kubeadm 检查集群证书
kubeadm certs check-expiration
🛡️ 五、安全最佳实践
5.1 文件权限设置
bash
# CA 私钥(最敏感)
chmod 600 /etc/kubernetes/pki/ca.key
# 其他私钥
chmod 600 /etc/kubernetes/pki/*.key
# 证书文件(只读)
chmod 644 /etc/kubernetes/pki/*.crt
# kubeconfig 文件
chmod 600 ~/.kube/config
5.2 证书有效期管理
- CA 证书:通常 10 年
- 组件证书:通常 1 年
- 用户证书:建议 90 天到 1 年
- kubelet 自动轮换:建议开启
5.3 证书撤销(CRL/OCSP)
Kubernetes 默认不启用证书撤销列表(CRL),如需撤销:
- 删除 RBAC 绑定
- 从信任链中移除证书
- 重新生成受影响的证书
📋 六、补充要点(您可能遗漏的)
6.1 Service Account 令牌
Service Account 使用 JWT 令牌而非证书:
bash
# 查看 Service Account 令牌
kubectl get secret default-token-xxxx -o jsonpath='{.data.token}' | base64 -d
# 令牌格式:eyJhbGciOiJSUzI1NiIsImtpZCI6...
6.2 证书签名请求(CSR)API
Kubernetes 提供了 CSR API 用于证书管理:
bash
# 查看所有 CSR
kubectl get csr
# 批准 CSR
kubectl certificate approve csr-name
# 拒绝 CSR
kubectl certificate deny csr-name
6.3 证书续期(kubeadm)
使用 kubeadm 管理集群时:
bash
# 检查证书过期时间
kubeadm certs check-expiration
# 续期所有证书
kubeadm certs renew all
# 续期指定证书
kubeadm certs renew apiserver
6.4 证书备份与恢复
bash
# 备份证书目录
tar -czf k8s-certs-backup-$(date +%Y%m%d).tar.gz /etc/kubernetes/pki/
# 恢复时注意权限
tar -xzf backup.tar.gz -C /
chmod 600 /etc/kubernetes/pki/*.key
6.5 证书调试技巧
bash
# 查看 API Server 日志(证书相关错误)
journalctl -u kube-apiserver -f
# 使用 curl 测试证书
curl --cacert ca.crt --cert user.crt --key user.key https://api-server:6443/api
# 使用 openssl s_client 测试 TLS 连接
openssl s_client -connect api-server:6443 -CAfile ca.crt -cert user.crt -key user.key
🎯 复习要点总结
| 主题 | 核心内容 | 关键命令 |
|---|---|---|
| 证书目录 | /etc/kubernetes/pki/ 结构 |
ls -la /etc/kubernetes/pki/ |
| 证书生成 | CSR → CA 签名流程 | openssl req, openssl x509 |
| 证书查看 | 查看证书信息 | openssl x509 -text -noout |
| 证书验证 | 验证证书链 | openssl verify |
| kubeconfig | 内嵌证书机制 | --embed-certs=true |
| 权限管理 | RBAC + 证书认证 | kubectl auth can-i |
| 轮换机制 | 自动/手动轮换 | kubeadm certs renew |
| 安全实践 | 文件权限、有效期 | chmod 600 |
建议按照目录结构→证书格式→OpenSSL命令→实践操作的顺序复习,重点掌握证书生成流程和权限验证方法。
🔐 核心概念:双向TLS认证
在Kubernetes集群中,组件间的通信普遍采用双向TLS(mTLS)认证 来确保安全。这意味着通信双方(客户端和服务端)都需要验证对方身份的真实性。整个过程依赖于证书颁发机构(CA) 作为信任的基石 。
📜 证书签发流程
证书的签发遵循一个标准流程,下图展示了从生成密钥对到最终签发证书的完整过程:
生成私钥
创建证书签名请求
(CSR)
CA审核并签署
(生成正式证书)
部署证书到组件
组件使用证书建立安全通信
具体到Kubernetes集群的CA签发组件证书,主要过程如下:
-
创建CA(证书颁发机构)
这是信任的起点。您需要生成一个自签名的根证书和私钥,集群中的所有组件都将信任由此CA签发的证书 [citation:2, citation:3]。
bash# 生成CA私钥 openssl genrsa -out ca.key 2048 # 生成自签名的CA证书 openssl req -x509 -new -nodes -key ca.key -subj "/CN=kubernetes-ca" -days 3650 -out ca.crt -
为组件签发证书
为每个需要认证的组件(如
kube-apiserver,etcd,kubelet等)生成证书。这个过程遵循上述流程图,关键在于证书签名请求(CSR)中的主题(Subject) ,尤其是CN字段,它常被用于标识组件身份 [citation:1, citation:4]。例如,为kube-apiserver签发证书:bash# 生成私钥 openssl genrsa -out apiserver.key 2048 # 生成证书签名请求,CN通常设置为组件名 openssl req -new -key apiserver.key -out apiserver.csr -subj "/CN=kube-apiserver" # 使用CA签署,生成正式证书 openssl x509 -req -in apiserver.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out apiserver.crt -days 365对于
kube-apiserver这类服务端证书,还需在配置文件中指定subjectAltName,包含服务的域名和IP地址,否则客户端会认为证书无效 。
🔌 组件认证关系详解
下表清晰地展示了集群中核心组件在相互通信时,谁充当客户端,谁充当服务端,以及分别使用哪些证书来证明自己的身份。
| 客户端 | 服务端 | 客户端使用的证书 | 服务端使用的证书 | 认证目的 |
|---|---|---|---|---|
kubectl / kube-controller-manager / kube-scheduler |
kube-apiserver |
各自的客户端证书(如admin.crt, controller-manager.crt) |
apiserver.crt |
控制平面组件和管理员通过API Server操作集群 |
kube-apiserver |
etcd |
apiserver-etcd-client.crt |
etcd/server.crt |
API Server作为客户端读写etcd中的数据 [citation:6, citation:7] |
kubelet |
kube-apiserver |
kubelet-client.crt |
apiserver.crt |
kubelet上报节点状态,接收Pod部署指令 |
kube-apiserver |
kubelet |
apiserver-kubelet-client.crt |
kubelet.crt |
API Server主动访问kubelet(如日志获取、exec功能) |
etcd集群成员 |
etcd集群成员 |
etcd/peer.crt |
etcd/peer.crt |
etcd节点间的 peer-to-peer 通信与数据同步 |
💡 关键总结与最佳实践
- 身份标识 :证书中的
CN字段是身份标识的关键,Kubernetes的RBAC系统常通过CN来识别用户或组件身份 。 - 服务端认证 :除了身份标识,服务端证书还必须正确配置
subjectAltName,包含其服务的所有域名和IP地址,否则客户端会验证失败 。 - 安全实践 :妥善保管CA私钥,定期轮换证书。生产环境可以考虑使用
cfssl等工具来简化证书管理流程 。
希望这份梳理能帮助您更清晰地理解Kubernetes的证书体系。如果您对某个具体的交互流程或签发细节有更多疑问,我很乐意继续探讨。