本页面介绍如何手动轮换证书颁发机构(CA)证书。
你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个节点的集群上运行本教程,且这些节点不能作为控制平面主机。如果你还没有集群,可以通过 minikube 创建一个,或者使用以下 Kubernetes 演练场之一。
请务必备份您的证书目录以及配置文件和任何其他必要的文件。
此方法假设 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,然后重启 kube-controller-manager。
在此之后创建的任何 ServiceAccount 都将获得包含旧的和新的 CA 的 Secret。
由 kube-controller-manager 标志 --client-ca-file 和 --cluster-signing-cert-file 指定的文件不能是 CA 束(bundle)。如果这些标志和 --root-ca-file 指向同一个 ca.crt 文件(现在是一个包含旧的和新的 CA 的束),您将面临错误。为了解决这个问题,您可以将新的 CA 复制到一个单独的文件,并使 --client-ca-file 和 --cluster-signing-cert-file 标志指向该副本。一旦 ca.crt 不再是束文件,您就可以将这些标志还原为指向 ca.crt 并删除副本。
kubeadm 的 Issue 1350 跟踪了一个 kube-controller-manager 无法接受 CA 束的错误。
等待控制器管理器更新 ServiceAccount Secret 中的 ca.crt,以包含旧的和新的 CA 证书。
如果在 API 服务器使用新的 CA 之前启动了任何 Pod,新的 Pod 将获取此更新并信任旧的和新的 CA。
重启所有使用集群内(in-cluster)配置的 Pod(例如:kube-proxy、CoreDNS 等),以便它们可以使用来自链接到 ServiceAccount 的 Secret 的更新后的证书颁发机构数据。
将旧的和新的 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 编码的旧的和新的证书颁发机构数据。
更新 Cloud Controller Manager 的 --root-ca-file 标志,以包含旧的和新的 CA,然后重启 cloud-controller-manager。
以滚动方式执行以下步骤。
重启任何其他聚合 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 客户端证书文件。
重启 API 服务器,使用由新 CA 签名的证书(apiserver.crt、apiserver-kubelet-client.crt 和 front-proxy-client.crt)。您可以使用现有的私钥或新的私钥。如果您更改了私钥,也请在 Kubernetes 证书目录中进行相应更新。
由于集群中的 Pod 信任旧的和新的 CA,会出现短暂的断开连接,随后 Pod 的 Kubernetes 客户端会重新连接到新的 API 服务器。新的 API 服务器使用由新 CA 签名的证书。
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 命名空间中的 ConfigMap cluster-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 的日志。
一旦成功验证了集群功能
更新所有 ServiceAccount 令牌,使其仅包含新的 CA 证书。
通过从 kubeconfig 文件以及 --client-ca-file 和 --root-ca-file 标志所对应的文件中删除旧的 CA,来重启控制平面组件。
在每个节点上,通过从 clientCAFile 标志所对应的文件和 kubelet kubeconfig 文件中删除旧的 CA,来重启 kubelet。您应该以滚动更新的方式进行此操作。
如果您的集群允许进行此更改,您也可以通过替换节点而不是重新配置它们来进行滚动更新。