You are viewing documentation for Kubernetes version: v1.23
Kubernetes v1.23 documentation is no longer actively maintained. The version you are currently viewing is a static snapshot. For up-to-date documentation, see the latest version.
手动轮换 CA 证书
本页展示如何手动轮换证书机构(CA)证书。
Before you begin
你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:
Your Kubernetes server must be at or later than version v1.13. To check the version, enterkubectl version
.手动轮换 CA 证书
确保备份你的证书目录、配置文件以及其他必要文件。
这里的方法假定 Kubernetes 的控制面通过运行多个 API 服务器以高可用配置模式运行。 另一假定是 API 服务器可体面地终止,因而客户端可以彻底地与一个 API 服务器断开 连接并连接到另一个 API 服务器。
如果集群中只有一个 API 服务器,则在 API 服务器重启期间会经历服务中断期。
- 将新的 CA 证书和私钥(例如:
ca.crt
、ca.key
、front-proxy-ca.crt
和front-proxy-client.key
)分发到所有控制面节点,放在其 Kubernetes 证书目录下。
更新 kube-controller-manager 的
--root-ca-file
标志,使之同时包含老的和新的 CA,之后重启组件。自此刻起,所创建的所有服务账号都会获得同时包含老的 CA 和新的 CA 的 Secret。
Note: 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
并删除该副本。
更新所有服务账号令牌,使之同时包含老的和新的 CA 证书。
如果在 API 服务器使用新的 CA 之前启动了新的 Pod,这些 Pod 也会获得此更新并且同时信任老的和新的 CA 证书。
base64_encoded_ca="$(base64 -w0 <path to file containing both old and new CAs>)" for namespace in $(kubectl get ns --no-headers | awk '{print $1}'); do for token in $(kubectl get secrets --namespace "$namespace" --field-selector type=kubernetes.io/service-account-token -o name); do kubectl get $token --namespace "$namespace" -o yaml | \ /bin/sed "s/\(ca.crt:\).*/\1 ${base64_encoded_ca}/" | \ kubectl apply -f - done done
重启所有使用集群内配置的 Pods(例如:
kube-proxy
、coredns
等),以便这些 Pod 能够使用 来自 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
中的内容,更新用户账号的证书。有关为独立用户账号创建证书的更多信息,可参阅 为用户帐号配置证书。
另外,还要更新 kubeconfig 文件中的
certificate-authority-data
节,使之包含 Base64 编码的老的和新的证书机构数据。
遵循下列步骤执行滚动更新
重新启动所有其他 被聚合的 API 服务器 或者 Webhook 处理程序,使之信任新的 CA 证书。
在所有节点上更新 kubelet 配置中的
clientCAFile
所指文件以及 kubelet.conf 中的certificate-authority-data
并重启 kubelet 以同时使用老的和新的 CA 证书。如果你的 kubelet 并未使用客户端证书轮换,则在所有节点上更新 kubelet.conf 中
client-certificate-data
和client-key-data
以及 kubelet 客户端证书文件(通常位于/var/lib/kubelet/pki
目录下)
- 使用用新的 CA 签名的证书
(
apiserver.crt
、apiserver-kubelet-client.crt
和front-proxy-client.crt
) 来重启 API 服务器。 你可以使用现有的私钥,也可以使用新的私钥。 如果你改变了私钥,则要将更新的私钥也放到 Kubernetes 证书目录下。
由于 Pod 既信任老的 CA 也信任新的 CA,Pod 中的客户端会经历短暂的连接断开状态, 之后再连接到使用新的 CA 所签名的证书的新的 API 服务器。
* 重启调度器以使用新的 CA 证书。
- 确保控制面组件的日志中没有 TLS 相关的错误信息。
- 为 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
Note: 要限制应用可能受到的并发干扰数量,可以参阅 配置 Pod 干扰预算.
如果你的集群使用启动引导令牌来添加节点,则需要更新
kube-public
名字空间下的 ConfigMapcluster-info
,使之包含新的 CA 证书。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 数据,进而不再信任老的 CA 证书。
从 kubeconfig 文件和
--client-ca-file
以及--root-ca-file
标志所指向的文件 中去除老的 CA 数据,之后重启控制面组件。重启 kubelet,移除
clientCAFile
标志所指向的文件以及 kubelet kubeconfig 文件中 的老的 CA 数据。