CA 证书的手动轮换

此页面展示如何手动轮换证书颁发机构(CA)证书。

开始之前

你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。建议在至少有两个不充当控制平面主机的节点的集群上运行本教程。如果你还没有集群,可以使用 minikube 创建一个,或者可以使用以下 Kubernetes 游乐场之一

  • 有关 Kubernetes 中身份验证的更多信息,请参阅身份验证
  • 有关 CA 证书的最佳实践的更多信息,请参阅单根 CA

手动轮换 CA 证书

  1. 将新的 CA 证书和私钥(例如:ca.crtca.keyfront-proxy-ca.crtfront-proxy-ca.key)分发到 Kubernetes 证书目录中所有控制平面节点。

  2. 更新 kube-controller-manager--root-ca-file 标志,以同时包含旧的和新的 CA,然后重新启动 kube-controller-manager。

    在此之后创建的任何ServiceAccount 都将获得包含旧的和新的 CA 的 Secret。

  3. 等待控制器管理器更新服务帐户 Secret 中的 ca.crt,以包含旧的和新的 CA 证书。

    如果在 API 服务器使用新的 CA 之前启动任何 Pod,则新的 Pod 将获得此更新,并将信任旧的和新的 CA。

  4. 重新启动所有使用集群内部配置的 Pod(例如:kube-proxy、CoreDNS 等),以便它们可以使用链接到 ServiceAccount 的 Secret 中更新的证书颁发机构数据。

    • 确保 CoreDNS、kube-proxy 和其他使用集群内部配置的 Pod 按预期工作。
  5. 将旧的和新的 CA 追加到 kube-apiserver 配置中的 --client-ca-file--kubelet-certificate-authority 标志对应的文件中。

  6. 将旧的和新的 CA 追加到 kube-scheduler 配置中的 --client-ca-file 标志对应的文件中。

  7. 通过分别替换 client-certificate-dataclient-key-data 的内容来更新用户帐户的证书。

    有关为单个用户帐户创建证书的信息,请参阅 为用户帐户配置证书

    此外,分别使用 Base64 编码的旧的和新的证书颁发机构数据来更新 kubeconfig 文件中的 certificate-authority-data 部分

  8. 更新 Cloud Controller Manager--root-ca-file 标志,以同时包含旧的和新的 CA,然后重新启动 cloud-controller-manager。

  9. 按滚动方式执行以下步骤。

    1. 重新启动任何其他聚合的 API 服务器 或 webhook 处理程序,以信任新的 CA 证书。

    2. 通过更新 kubelet 配置中的 clientCAFilekubelet.conf 中的 certificate-authority-data 对应的文件来重新启动 kubelet,以在所有节点上使用旧的和新的 CA。

      如果你的 kubelet 没有使用客户端证书轮换,请更新所有节点上的 kubelet.conf 中的 client-certificate-dataclient-key-data 以及通常在 /var/lib/kubelet/pki 中找到的 kubelet 客户端证书文件。

    3. 使用新的 CA 签名的证书(apiserver.crtapiserver-kubelet-client.crtfront-proxy-client.crt)重新启动 API 服务器。 你可以使用现有的私钥或新的私钥。 如果你更改了私钥,那么也在 Kubernetes 证书目录中更新这些私钥。

      由于你集群中的 Pod 信任旧的和新的 CA,因此会发生短暂的断开连接,之后 Pod 的 Kubernetes 客户端会重新连接到新的 API 服务器。 新的 API 服务器使用由新的 CA 签名的证书。

      • 重新启动kube-scheduler以使用并信任新的 CA。
      • 确保控制平面组件的日志中没有 TLS 错误。
    4. 注释任何 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
    
     Depending on how you use StatefulSets you may also need to perform similar rolling replacement.
    
  10. 如果你的集群使用引导令牌来加入节点,请使用新的 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 -
    
  11. 验证集群功能。

    1. 检查来自控制平面组件、kubelet 和 kube-proxy 的日志。 确保这些组件没有报告任何 TLS 错误;有关更多详细信息,请参阅 查看日志

    2. 验证来自任何聚合的 api 服务器和使用集群内部配置的 Pod 的日志。

  12. 一旦成功验证了集群功能

    1. 更新所有服务帐户令牌,使其仅包含新的 CA 证书。

      • 所有使用集群内部 kubeconfig 的 Pod 最终都需要重新启动以获取新的 Secret,这样就没有 Pod 依赖于旧的集群 CA。
    2. 通过从 kubeconfig 文件和 --client-ca-file--root-ca-file 标志对应的文件中删除旧的 CA 来重新启动控制平面组件。

    3. 在每个节点上,通过从 clientCAFile 标志对应的文件和 kubelet kubeconfig 文件中删除旧的 CA 来重新启动 kubelet。 你应该以滚动更新的方式执行此操作。

      如果你的集群允许你进行此更改,你也可以通过替换节点而不是重新配置它们来推出更改。

上次修改时间为太平洋标准时间 2022 年 4 月 14 日下午 2:47:删除手动更新服务帐户 Secret 的不必要步骤 (b1a5f31dd5)