手动轮换 CA 证书
本页面展示了如何手动轮换证书颁发机构(CA)证书。
开始之前
你需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具已被配置为与你的集群通信。建议你在一个至少包含两个不作为控制平面主机的节点的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用以下 Kubernetes 演练场之一
手动轮换 CA 证书
注意
请务必备份证书目录以及配置文件和任何其他必需的文件。
此方法假设 Kubernetes 控制平面在具有多个 API 服务器的高可用性 (HA) 配置中运行。还假设 API 服务器能够优雅终止,以便客户端可以干净地断开与一个 API 服务器的连接并重新连接到另一个。
具有单个 API 服务器的配置在 API 服务器重启期间将出现不可用。
将新的 CA 证书和私钥(例如:
ca.crt
、ca.key
、front-proxy-ca.crt
和front-proxy-ca.key
)分发到 Kubernetes 证书目录中的所有控制平面节点。更新kube-controller-manager 的
--root-ca-file
标志,使其包含旧 CA 和新 CA,然后重启 kube-controller-manager。此后创建的任何ServiceAccount 都将获得包含旧 CA 和新 CA 的 Secret。
注意
kube-controller-manager 标志
--client-ca-file
和--cluster-signing-cert-file
指定的文件不能是 CA 捆绑包(bundle)。如果这些标志和--root-ca-file
都指向同一个现在是捆绑包(包含旧 CA 和新 CA)的ca.crt
文件,你将会遇到错误。要解决这个问题,你可以将新的 CA 复制到单独的文件中,并让--client-ca-file
和--cluster-signing-cert-file
标志指向该复制文件。一旦ca.crt
不再是捆绑包,你就可以恢复这些问题标志指向ca.crt
并删除复制文件。kubeadm 的 Issue 1350 跟踪了 kube-controller-manager 无法接受 CA 捆绑包的错误。
等待控制器管理器更新 ServiceAccount Secret 中的
ca.crt
,使其包含旧 CA 证书和新 CA 证书。如果在 API 服务器使用新 CA 之前启动任何 Pod,这些新的 Pod 将获得此更新,并信任旧 CA 和新 CA。
重启所有使用集群内配置(例如:kube-proxy、CoreDNS 等)的 Pod,以便它们可以使用链接到 ServiceAccount 的 Secret 中更新后的证书颁发机构数据。
- 确保 CoreDNS、kube-proxy 和其他使用集群内配置的 Pod 按预期工作。
将旧 CA 和新 CA 都追加到
kube-apiserver
配置中--client-ca-file
和--kubelet-certificate-authority
标志指定的文件中。将旧 CA 和新 CA 都追加到
kube-scheduler
配置中--client-ca-file
标志指定的文件中。通过分别替换
client-certificate-data
和client-key-data
的内容来更新用户账户的证书。有关为单个用户账户创建证书的信息,请参阅为用户账户配置证书。
此外,分别用 Base64 编码的旧 CA 和新 CA 数据更新 kubeconfig 文件中的
certificate-authority-data
部分。更新Cloud Controller Manager 的
--root-ca-file
标志,使其包含旧 CA 和新 CA,然后重启 cloud-controller-manager。注意
如果你的集群没有 cloud-controller-manager,可以跳过此步骤。按滚动方式执行以下步骤。
重启任何其他聚合的 API 服务器或 Webhook 处理程序,使其信任新的 CA 证书。
通过更新所有节点上 kubelet 配置中
clientCAFile
标志指定的文件以及kubelet.conf
中的certificate-authority-data
,使其使用旧 CA 和新 CA,从而重启 kubelet。如果你的 kubelet 未使用客户端证书轮换,请更新所有节点上
kubelet.conf
中的client-certificate-data
和client-key-data
,以及通常位于/var/lib/kubelet/pki
中的 kubelet 客户端证书文件。使用由新 CA 签发的证书(
apiserver.crt
、apiserver-kubelet-client.crt
和front-proxy-client.crt
)重启 API 服务器。你可以使用现有的私钥或新的私钥。如果你更改了私钥,请同时在 Kubernetes 证书目录中更新它们。由于集群中的 Pod 信任旧 CA 和新 CA,因此会有一个短暂的断开连接,随后 Pod 的 Kubernetes 客户端将重新连接到新的 API 服务器。新的 API 服务器使用由新 CA 签发的证书。
- 重启kube-scheduler,使其使用并信任新的 CA。
- 确保控制平面组件的日志中没有 TLS 错误。
注意
To generate certificates and private keys for your cluster using the `openssl` command line tool, see [Certificates (`openssl`)](/docs/tasks/administer-cluster/certificates/#openssl). You can also use [`cfssl`](/docs/tasks/administer-cluster/certificates/#cfssl).
标注任何 DaemonSet 和 Deployment,以更安全的滚动方式触发 Pod 替换。
for namespace in $(kubectl get namespace -o jsonpath='{.items[*].metadata.name}'); do for name in $(kubectl get deployments -n $namespace -o jsonpath='{.items[*].metadata.name}'); do kubectl patch deployment -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}'; done for name in $(kubectl get daemonset -n $namespace -o jsonpath='{.items[*].metadata.name}'); do kubectl patch daemonset -n ${namespace} ${name} -p '{"spec":{"template":{"metadata":{"annotations":{"ca-rotation": "1"}}}}}'; done done
注意
To limit the number of concurrent disruptions that your application experiences, see [configure pod disruption budget](/docs/tasks/run-application/configure-pdb/).
Depending on how you use StatefulSets you may also need to perform similar rolling replacement.
如果你的集群使用引导令牌(bootstrap tokens)加入节点,请使用新的 CA 更新
kube-public
命名空间中的cluster-info
ConfigMap。base64_encoded_ca="$(base64 -w0 /etc/kubernetes/pki/ca.crt)" kubectl get cm/cluster-info --namespace kube-public -o yaml | \ /bin/sed "s/\(certificate-authority-data:\).*/\1 ${base64_encoded_ca}/" | \ kubectl apply -f -
验证集群功能。
检查控制平面组件以及 kubelet 和 kube-proxy 的日志。确保这些组件没有报告任何 TLS 错误;有关更多详细信息,请参阅查看日志。
验证任何聚合的 API 服务器和使用集群内配置的 Pod 的日志。
集群功能成功验证后
更新所有 ServiceAccount Token,使其仅包含新的 CA 证书。
- 所有使用集群内 kubeconfig 的 Pod 最终都需要重启以获取新的 Secret,从而确保没有 Pod 依赖于旧的集群 CA。
通过分别从 kubeconfig 文件以及
--client-ca-file
、--root-ca-file
标志指定的文件中移除旧 CA 来重启控制平面组件。在每个节点上,通过从
clientCAFile
标志指定的文件和 kubelet kubeconfig 文件中移除旧 CA 来重启 kubelet。应以滚动更新方式进行此操作。如果你的集群允许进行此更改,你也可以通过替换节点而不是重新配置节点来推广此更改。