手动轮换 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,然后重新启动 kube-controller-manager。在此之后创建的任何 ServiceAccount 都将获得包含旧的和新的 CA 的 Secret。
注意
kube-controller-manager 标志
--client-ca-file
和--cluster-signing-cert-file
指定的文件不能是 CA 捆绑包。如果这些标志和--root-ca-file
指向同一个ca.crt
文件,该文件现在是一个捆绑包(包含旧的和新的 CA),您将遇到错误。要解决此问题,您可以将新的 CA 复制到一个单独的文件中,并使标志--client-ca-file
和--cluster-signing-cert-file
指向该副本。一旦ca.crt
不再是捆绑包,您就可以恢复问题标志以指向ca.crt
并删除副本。问题 1350 为 kubeadm 跟踪 kube-controller-manager 无法接受 CA 捆绑包的错误。
等待控制器管理器更新服务帐户 Secret 中的
ca.crt
以包含旧的和新的 CA 证书。如果在 API 服务器使用新的 CA 之前启动了任何 Pod,新的 Pod 将获得此更新,并将信任旧的和新的 CA。
重新启动使用集群内配置的所有 Pod(例如:kube-proxy、CoreDNS 等),以便它们可以使用链接到 ServiceAccount 的 Secret 中更新的证书颁发机构数据。
- 确保 CoreDNS、kube-proxy 和其他使用集群内配置的 Pod 按预期工作。
将旧的和新的 CA 都追加到
kube-apiserver
配置中针对--client-ca-file
和--kubelet-certificate-authority
标志的文件。将旧的和新的 CA 都追加到
kube-scheduler
配置中针对--client-ca-file
标志的文件。通过分别替换
client-certificate-data
和client-key-data
的内容来更新用户帐户的证书。有关为单个用户帐户创建证书的信息,请参阅 为用户帐户配置证书。
此外,使用 Base64 编码的旧的和新的证书颁发机构数据分别更新 kubeconfig 文件中的
certificate-authority-data
部分。更新 云控制器管理器 的
--root-ca-file
标志以包含旧的和新的 CA,然后重新启动云控制器管理器。注意
如果您的集群没有云控制器管理器,您可以跳过此步骤。以滚动方式执行以下步骤。
重新启动任何其他 聚合的 API 服务器 或 webhook 处理程序以信任新的 CA 证书。
通过更新 kubelet 配置中针对
clientCAFile
的文件以及kubelet.conf
中的certificate-authority-data
来重新启动 kubelet,以在所有节点上使用旧的和新的 CA。如果您的 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,因此在 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.
如果您的集群使用引导令牌来加入节点,请在
kube-public
命名空间中使用新的 CA 更新 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。您应该将此作为滚动更新执行。如果您的集群允许您进行此更改,您也可以通过替换节点而不是重新配置节点来将其推出。