4. 证书轮换失败常见原因:CA不可用、Secret权限不足、证书签名请求(CSR)被拒绝、节点时间偏差
Cilium Agent 的 mTLS 证书轮换依赖 Kubernetes 控制面与底层 PKI 基础设施的协同工作。任何一环出现故障,都会导致 Agent 无法获取新证书,进而引发连通性中断。以下是生产环境中最常见的四类根因及其诊断方法。
⚠️ 故障影响范围:证书轮换失败通常不会立即杀死 Agent 进程,但会导致现有 TLS 连接在证书过期后中断,影响范围从单个 Pod 到整个集群的节点间通信。修复优先级应为“高”。
4.1 CA 不可用
证书轮换的第一步是 Agent 向 CA(证书颁发机构)发起签名请求。如果 CA 服务不可达或响应超时,轮换流程将直接阻塞。
常见场景
- 内部 CA Pod 崩溃或重启:例如 cert-manager 或 cfssl 控制器处于 CrashLoopBackOff 状态。
- CA 服务网络策略阻断:Agent 所在节点无法通过 ClusterIP 或 NodePort 访问 CA 端点。
- CA 证书链失效:根证书或中间证书过期,导致新签发的证书无法被信任。
诊断命令
# 检查 CA 服务 Pod 状态
kubectl get pods -n cilium-system -l k8s-app=ca-service
# 测试 CA 端点连通性(从 Agent 节点执行)
curl -v --connect-timeout 5 https://ca-service.cilium-system.svc.cluster.local:443/healthz
# 查看 Agent 日志中的 CA 连接错误
kubectl logs -n cilium-system -l k8s-app=cilium-agent --tail=50 | grep -i "ca\|certificate\|tls"
🔍 关键指标:如果 curl 返回
Connection refused 或 Timeout,且 CA Pod 日志无异常,优先检查 NetworkPolicy 和 Service Endpoint 是否正常。
4.2 Secret 权限不足
Cilium Agent 在轮换证书时,需要将新证书写入 Kubernetes Secret 对象。如果 Agent 使用的 ServiceAccount 缺少对 Secret 的 get、update 或 patch 权限,轮换将失败。
权限模型对比
| 资源 | 所需操作 | 常见 RBAC 缺失 | 典型错误日志 |
|---|---|---|---|
secrets |
get, update, patch | 缺少 update 或 patch |
Forbidden: user "system:serviceaccount:cilium-system:cilium-agent" cannot update resource "secrets" |
secrets (跨命名空间) |
get, update | ClusterRole 未绑定到目标命名空间 | secrets "cilium-ca" is forbidden: User cannot get resource "secrets" in API group "" |
修复步骤
- 确认 Agent 使用的 ServiceAccount:
kubectl get pods -n cilium-system -l k8s-app=cilium-agent -o jsonpath='{.items[0].spec.serviceAccount}' - 检查当前 RBAC 绑定:
kubectl describe clusterrolebinding cilium-agent kubectl describe rolebinding -n cilium-system cilium-agent - 补充缺失权限(示例):
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cilium-agent-secret rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "watch", "update", "patch"]
💡 最佳实践:避免使用
* 通配权限。明确列出 get、update、patch 三个动词,并限制到 cilium-system 命名空间内的 Secret 资源。
4.3 证书签名请求(CSR)被拒绝
当 Agent 提交 CSR 到 Kubernetes 内置的 certificates.k8s.io API 时,集群的 CSR 审批控制器可能因策略原因拒绝请求。
拒绝原因分类
- 签名者名称不匹配:CSR 中
spec.signerName与集群配置的 signer 不一致(例如使用kubernetes.io/kubelet-serving而非cilium.io/agent)。 - 请求的密钥用途违规:CSR 中包含了
digital signature但缺少client auth或server auth。 - Subject 字段格式错误:Common Name (CN) 或 Organization (O) 不符合集群准入策略。
- 自动审批控制器未配置:集群缺少自动批准 Cilium CSR 的
ClusterRoleBinding或CertificateSigningRequest审批规则。
诊断与修复
# 查看所有 CSR 及其状态
kubectl get csr --all-namespaces
# 查看被拒绝的 CSR 详情
kubectl describe csr cilium-agent-xxxxx
# 手动批准(临时修复)
kubectl certificate approve cilium-agent-xxxxx
# 配置自动审批(推荐)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cilium-csr-approver
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["certificates.k8s.io"]
resources: ["certificatesigningrequests/approval"]
verbs: ["update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cilium-csr-approver
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cilium-csr-approver
subjects:
- kind: ServiceAccount
name: cilium-operator
namespace: cilium-system
🔍 关键检查点:CSR 被拒绝时,
kubectl describe csr 的 Status.Conditions 字段会显示 Reason: "Kubernetes API SignerName check" 或 Reason: "Requested key usages not allowed"。根据具体原因调整 CSR 模板。
4.4 节点时间偏差
证书轮换依赖时间戳验证:新证书的 notBefore 和 notAfter 字段基于 CA 的系统时间生成。如果 Agent 所在节点与 CA 之间的时间偏差超过证书有效期窗口(通常为 5 分钟),会导致以下问题:
- 证书立即过期:节点时间快于 CA 时间,新证书的
notBefore在未来,Agent 认为证书尚未生效。 - 验证失败:节点时间慢于 CA 时间,证书的
notAfter已过,Agent 拒绝加载。 - CSR 签名时间戳无效:CA 拒绝签名请求,因为请求中的时间戳与 CA 时间偏差过大。
时间偏差检测与修复
| 检测方法 | 命令/工具 | 正常阈值 | 修复措施 |
|---|---|---|---|
| 节点与 CA Pod 时间对比 | date vs kubectl exec ca-pod -- date |
< 30 秒 | 配置 NTP 服务(chrony/ntpd) |
| 证书时间戳验证 | openssl x509 -in cert.pem -noout -dates |
notBefore < now < notAfter | 同步节点时间后重新轮换 |
| Agent 日志时间戳异常 | kubectl logs ... | grep -i "certificate.*expired\|time.*skew" |
无此类日志 | 检查节点时区配置 |
4.5 综合排查流程
当证书轮换失败时,建议按以下顺序排查:
- 检查 Agent 日志:
kubectl logs -n cilium-system -l k8s-app=cilium-agent | grep -i "cert\|tls\|csr\|secret" - 验证 CA 可用性:从 Agent 节点 curl CA 健康端点。
- 检查 Secret 权限:使用
kubectl auth can-i模拟 Agent 的 ServiceAccount 操作。 - 查看 CSR 状态:
kubectl get csr | grep cilium,确认是否有 Pending 或 Denied 状态。 - 对比节点与 CA 时间:执行
date和kubectl exec ca-pod -- date,确保偏差 < 30 秒。
⚠️ 生产环境建议:在集群中部署 NTP 监控告警(如 Prometheus + node_time_seconds 指标),并配置自动 CSR 审批控制器,从源头减少时间偏差和权限问题导致的轮换失败。