自动化 Kubernetes 证书轮换

本指南帮助您在 中安装、了解和操作 Kubernetes Certificate Rotator,以自动化集群内 Kubernetes 证书的轮换。

CAUTION

仅在需要证书轮换时使用此插件

Kubernetes 证书默认有效期为 10 年。启用此插件后,插件管理的证书将变为短期证书:kubelet 证书为 91 天,控制平面证书为 365 天。

自动续订会重启 API server 和 kubelet 等组件,这可能会影响集群可用性和业务工作负载。如果轮换耗时超过 30 秒,节点可能变为 NotReady,其 Pod 可能会被驱逐。

如果不需要证书轮换,请勿安装此插件。

安装

有关安装说明,请参阅集群插件。

注意:

  • 当前支持:

    • On-Premises 集群
    • DCS 集群

配置

以下是插件的默认证书设置。控制器使用为每种证书类型配置的续订阈值,并按照配置的间隔检查证书。

证书设置

证书有效期默认续订阈值大致轮换时间点
控制平面8760h(365 天)1752h(剩余 73 天)签发后约 292 天
Kubelet2184h(91 天)720h(剩余 30 天)签发后约 61 天

使用默认设置时,证书剩余有效期少于 20% 或 30 天时会续订,以先达到的阈值为准。这对应于控制平面证书签发后约 292 天,以及 kubelet 证书签发后约 61 天。实际时间可能因检查间隔而有所变化。如果覆盖部署值,则以配置的续订阈值为准。

操作设置

设置默认值描述
检查间隔24h两次证书检查之间的间隔。
续订 kubelet 客户端证书已禁用同时续订 kubelet.conf 引用的客户端证书。

覆盖证书设置

控制器接受以下插件参数。时长值使用 Go 的 time.Duration 格式;使用小时,例如 8760h 或 720h(该格式支持 ns、us、ms、s、m 和 h 等单位)。

参数默认值描述
controlPlaneCertificateDuration8760h为控制平面证书请求的有效期。
controlPlaneCertificateRenewBefore1752h触发控制平面证书续订的剩余有效期。
kubeletCertificateDuration2184h为 kubelet 证书请求的有效期。
kubeletCertificateRenewBefore720h触发 kubelet 证书续订的剩余有效期。
checkInterval24h两次证书检查之间的间隔。
enableRenewKubeletClientCertificatefalse是否续订 kubelet.conf 引用的客户端证书。

对于已安装的插件,请编辑 Global 集群中对应的 ModuleInfo。插件的 spec.config 是受支持的配置输入;cert-rotator 的 valuesTemplates 会将这些字段映射到控制器使用的 chart 值:

spec:
  config:
    controlPlaneCertificateDuration: "8760h"
    controlPlaneCertificateRenewBefore: "1752h"
    kubeletCertificateDuration: "2184h"
    kubeletCertificateRenewBefore: "720h"
    checkInterval: "24h"
    enableRenewKubeletClientCertificate: true

找到已安装的实例并使用以下命令进行编辑:

kubectl get moduleinfo \
  -l cpaas.io/cluster-name=<CLUSTER-NAME>,cpaas.io/module-name=cluster-cert-rotator
kubectl edit moduleinfo <MODULEINFO-NAME>

有关高级插件 YAML 安装和配置,请参阅集群插件。请确保每个续订阈值都短于其对应的证书有效期。更改有效期也会导致续订有效期不同的证书。

工作原理

此插件会自动轮换以下证书。

证书文件功能节点类型
apiserver.crtkube-apiserver 的服务器证书控制平面节点
apiserver-etcd-client.crtkube-apiserver 访问 etcd 的客户端证书控制平面节点
apiserver-kubelet-client.crtkube-apiserver 访问 kubelet 的客户端证书控制平面节点
front-proxy-client.crtkube-apiserver 访问聚合 API 服务器的客户端证书控制平面节点
etcd/server.crtetcd 的服务器证书控制平面节点
etcd/peer.crtetcd 成员之间进行对等通信的证书控制平面节点
/root/.kube/config, admin.conf, super-admin.confkubeconfig 中用于集群管理的客户端证书控制平面节点
controller-manager.confkubeconfig 中用于 kube-controller-manager 的客户端证书控制平面节点
scheduler.confkubeconfig 中用于 kube-scheduler 的客户端证书控制平面节点
kubelet.crtkubelet 的服务器证书所有节点
kubelet-client-current.pemkubelet 的客户端证书(由 kubelet.conf 引用)所有节点

轮换流程

  1. 加载证书信息

    初始步骤包括收集所有目标证书的元数据。由于这些证书存储在主机上的不同路径中,因此必须从相应文件中读取其内容。为此,系统会在目标节点上创建一个临时 Pod,并挂载证书目录,使 Pod 能够读取相关信息。证书信息每天收集一次。证书详细信息(路径、过期时间)保存在 ConfigMap cpaas-system/node-local-certs-<node-name> 中。加密的 CA 证书存储在 Secret cpaas-system/kubernetes-ca 中。

  2. 轮换触发条件

    证书的 notBefore 和 notAfter 字段表示有效期。默认情况下,当剩余有效期少于 20% 或 30 天时(以先达到的阈值为准),会触发轮换。控制器会为每种证书类型应用配置的续订阈值,因此覆盖值优先。如果证书的有效期与预期时长不同,也会对其进行续订。

  3. 轮换队列

    需要轮换的证书会进入队列等待处理。轮换程序会评估近期的轮换活动和待处理任务的紧急程度,以决定是否立即处理这些任务。这可以防止同时轮换多个证书而导致潜在的集群运行状况问题。

  4. 生成新证书

    轮换程序会根据内部存储的 CA 信息生成新证书。轮换过程会在目标节点上创建一个临时 Pod,并挂载必要的证书目录,以便以受控方式修改文件。

  5. 重启组件

    需要重启:

    • kube-apiserver:需要重启以加载新证书。重启期间,它会重新生成其内部回环证书(有效期为一年,仅供内部使用,无法在外部轮换)。
    • kube-controller-manager:需要重启以重新加载 kubeconfig 文件。
    • kube-scheduler:需要重启以重新加载 kubeconfig 文件。
    • kubelet:需要重启以重新加载服务器证书。

    重启方法:向相应静态 Pod 的 YAML 文件添加注解,以触发 kubelet 重新创建 Pod。要重启 kubelet,请使用 hostPID is true 挂载主机文件系统,并在容器中运行 "systemctl restart kubelet"。

    自动重新加载:

    • Etcd 可以自动重新加载证书。

操作注意事项

如果 kubelet 在轮换窗口期间处于异常状态,无法自动轮换证书,则需要手动轮换:

操作员必须手动续订证书。

运行以下命令手动续订证书:

cert-renew --ca-cert <ca-cert-path> --ca-key <ca-key-path> --days <days> <certificate or kubeconfig 1> <certificate or kubeconfig 2> ...

例如,续订 kubelet.crt:

cert-renew --ca-cert /etc/kubernetes/pki/ca.crt --ca-key /etc/kubernetes/pki/ca.key --days 91 /etc/kubernetes/pki/kubelet.crt

要下载并准备 cert-renew 工具,请运行:

curl "$(kubectl get services -n cpaas-system frontend -o jsonpath='{.spec.clusterIP}'):8080/cluster-cert-rotator/download/cert-renew" -o ./cert-renew && chmod +x ./cert-renew

也可以下载 renew-all.sh,以续订节点上的所有证书:

curl "$(kubectl get services -n cpaas-system frontend -o jsonpath='{.spec.clusterIP}'):8080/cluster-cert-rotator/download/renew-all.sh" -o ./renew-all.sh