CA 证书的手动轮换
本页面介绍如何手动轮换证书颁发机构(CA)证书。
准备工作
你需要有一个 Kubernetes 集群,并且 kubectl 命令行工具已配置为与你的集群通信。建议你在至少有两个非控制平面主机节点的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者使用这些 Kubernetes 教程环境之一。
手动轮换 CA 证书
注意
务必备份你的证书目录以及配置文件和任何其他必要文件。
此方法假定 Kubernetes 控制平面在具有多个 API 服务器的 HA 配置中运行。还假定 API 服务器正常终止,以便客户端可以干净地从一个 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 捆绑包。如果这些标志和--root-ca-file
都指向同一个ca.crt
文件,而该文件现在是一个捆绑包(包含旧 CA 和新 CA),你将会遇到错误。为了解决此问题,你可以将新 CA 复制到单独的文件中,并使标志--client-ca-file
和--cluster-signing-cert-file
指向该副本。一旦ca.crt
不再是捆绑包,你可以将问题标志恢复为指向ca.crt
并删除该副本。kubeadm 的问题 1350 跟踪了 kube-controller-manager 无法接受 CA 捆绑包的错误。
等待控制器管理器更新服务账号 Secret 中的
ca.crt
,使其包含旧 CA 证书和新 CA 证书。如果在 API 服务器使用新 CA 之前启动了任何 Pod,则这些新 Pod 将获得此更新并信任旧 CA 和新 CA。
重启所有使用集群内配置的 Pod(例如:kube-proxy、CoreDNS 等),以便它们可以使用链接到 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
的内容来更新用户账号的证书。有关为单个用户账号创建证书的信息,请参阅 为用户账号配置证书。
此外,更新 kubeconfig 文件中的
certificate-authority-data
部分,分别使用 Base64 编码的旧证书颁发机构数据和新证书颁发机构数据。更新 云控制器管理器 的
--root-ca-file
标志,以同时包含旧 CA 和新 CA,然后重启云控制器管理器。注意
如果你的集群没有云控制器管理器,可以跳过此步骤。按滚动方式执行以下步骤。
重启任何其他 聚合 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.
如果你的集群使用引导令牌加入节点,请使用新的 CA 更新
kube-public
命名空间中的 ConfigMapcluster-info
。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 的日志。
一旦集群功能成功验证
更新所有服务账号令牌,使其只包含新的 CA 证书。
- 所有使用集群内 kubeconfig 的 Pod 最终都需要重启以获取新的 Secret,这样就没有 Pod 依赖旧的集群 CA 了。
通过分别从 kubeconfig 文件以及
--client-ca-file
和--root-ca-file
标志所指向的文件中移除旧 CA 来重启控制平面组件。在每个节点上,通过从
clientCAFile
标志所指向的文件以及 kubelet kubeconfig 文件中移除旧 CA 来重启 kubelet。你应该以滚动更新的方式执行此操作。如果你的集群允许你进行此更改,你也可以通过替换节点而不是重新配置它们来推出。