Azure Kubernetes 服务 (AKS) 中的证书轮换

Azure Kubernetes 服务 (AKS) 使用证书对其许多组件进行身份验证。 2022 年 3 月之后创建的具有 Azure 基于角色的访问控制 (Azure RBAC) 的群集已启用证书自动轮换。 出于安全或策略原因,可能需要定期轮换这些证书。 例如,你可能有一个策略,用于每隔 90 天轮换所有证书。

备注

默认情况下,仅对已启用 RBAC 的 AKS 群集启用证书自动轮换。

本文介绍如何在 AKS 群集中使用证书轮换。

开始之前

本文需要 Azure CLI 2.0.77 或更高版本。 运行 az --version 即可查找版本。 如果需要进行安装或升级,请参阅安装 Azure CLI

AKS 证书、证书颁发机构和服务帐户

AKS 可生成和使用以下证书、证书颁发机构 (CA) 和服务帐户 (SA):

  • AKS API 服务器会创建一个称为“群集 CA”的 CA。
  • API 服务器具有一个群集 CA,该 CA 对证书进行签名,以用于从 API 服务器到 kubelet 的单向通信。
  • 每个 kubelet 会创建一个证书签名请求 (CSR),该 CSR 由群集 CA 签名,用于从 kubelet 到 API 服务器的通信。
  • API 聚合器使用群集 CA 颁发证书,以便与其他 API 进行通信。 API 聚合器也可以拥有自己的 CA 来颁发这些证书,但它目前使用群集 CA。
  • 每个节点都使用 SA 令牌,该令牌由群集 CA 签名。
  • kubectl 客户端具有用于与 AKS 群集通信的证书。

Azure 将维护本部分所述的所有证书,但群集证书除外。

备注

  • 对于 2019 年 5 月之前创建的 AKS 群集,其证书将在两年后到期。
  • 对于 2019 年 5 月之后创建的 AKS 群集,其群集 CA 证书将在 30 年后到期。

可以使用 kubectl get nodes 命令验证群集的创建时间,该命令会显示节点池的年龄

检查证书过期日期

检查群集证书到期日期

  • 使用 kubectl config view 命令检查群集证书的到期日期。

    kubectl config view --raw -o jsonpath="{.clusters[?(@.name == '')].cluster.certificate-authority-data}" | base64 -d | openssl x509 -text | grep -A2 Validity
    

检查 API 服务器证书过期日期

  • 使用以下 curl 命令检查 API 服务器证书的到期日期。

    curl https://{apiserver-fqdn} -k -v 2>&1 | grep expire
    

检查 VMAS 代理节点证书到期日期

  • 使用 az vm run-command invoke 命令检查 VMAS 代理节点证书的到期日期。

    az vm run-command invoke --resource-group MC_rg_myAKSCluster_region --name vm-name --command-id RunShellScript --query 'value[0].message' -otsv --scripts "openssl x509 -in /etc/kubernetes/certs/apiserver.crt -noout -enddate"
    

检查虚拟机规模集代理节点的证书过期日期

  • 使用 az vmss run-command invoke 命令检查虚拟机规模集代理节点证书的过期日期。

    az vmss run-command invoke --resource-group "MC_rg_myAKSCluster_region" --name "vmss-name" --command-id RunShellScript --instance-id 1 --scripts "openssl x509 -in  /var/lib/kubelet/pki/kubelet-client-current.pem -noout -enddate" --query "value[0].message"
    

证书自动轮换

为使 AKS 自动轮换非 CA 证书,群集必须具有在所有 Azure 区域中默认启用的 TLS 启动

备注

  • 如果有现有群集,则必须升级该群集以启用证书自动轮换。
  • 不要禁用启动以保持启用自动轮换。
  • 如果群集在自动证书轮换期间处于停止状态,则仅轮换控制平面证书。 在这种情况下,应在证书轮换后重新创建节点池,以启动节点池证书轮换。

对于在 2022 年 3 月之后创建或升级的任何 AKS 群集,Azure Kubernetes 服务会在客户端证书有效时间的 80% 内自动在控制平面和代理节点上轮换非 CA 证书,然后才能在群集未停机的情况下过期。

如何检查当前代理节点池是否已启用 TLS 启动?

  1. 通过浏览到以下路径中的一个来验证群集是否已启用 TLS 启动:

    • 在 Linux 节点上:/var/lib/kubelet/bootstrap-kubeconfig 或 /host/var/lib/kubelet/bootstrap-kubeconfig
    • 在 Windows 节点上:C:\k\bootstrap-config

    有关详细信息,请参阅连接到 Azure Kubernetes 服务群集节点以进行维护或故障排除

    备注

    随着 Kubernetes 版本的发展,文件路径可能会更改。

  2. 配置区域后,请创建新群集或升级现有群集以设置群集证书的自动轮换。 需要升级控制平面和节点池才能启用此功能。

手动轮换群集证书

警告

使用 az aks rotate-certs 轮换证书将重新创建所有节点、虚拟机规模集和磁盘,并可能导致 AKS 群集停机时间长达 30 分钟。

  1. 使用 az aks get-credentials 命令连接到群集。

    az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME
    
  2. 使用 az aks rotate-certs 命令轮换群集上的所有证书、CA 和 SA。

    az aks rotate-certs --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME
    

    重要

    az aks rotate-certs 最多可能需要 30 分钟才能完成。 如果该命令还未完成就已失败,请使用 az aks show 验证群集的状态是否为“正在轮换证书”。 如果群集处于失败状态,请重新运行 az aks rotate-certs 以再次轮换证书。

  3. 使用任何 kubectl 命令(例如 kubectl get nodes)验证旧证书是否不再有效。

    kubectl get nodes
    

    如果尚未更新 kubectl 使用的证书,则会看到类似于以下示例输出的错误:

    Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "ca")
    
  4. 使用带有 kubectl 标志的 az aks get-credentials 命令更新 --overwrite-existing 使用的证书。

    az aks get-credentials --resource-group $RESOURCE_GROUP_NAME --name $CLUSTER_NAME --overwrite-existing
    
  5. 使用 kubectl get 命令验证证书是否已更新。

    kubectl get nodes
    

    备注

    如果有任何服务在 AKS 之上运行,可能需要更新其证书。

Kubelet 服务证书轮换

借助 Kubelet 服务证书轮换,AKS 可以利用 kubelet 服务器 TLS 引导来引导和轮换群集 CA 签名的服务证书。

局限性

  • 在 Kubernetes 版本 1.27 及更高版本上受支持。
  • 当基于快照预配节点池时,不受支持。
  • 无法手动启用此功能。 当现有节点池第一次升级到任何 kubernetes 版本 1.27 或更高版本时,将默认启用 kubelet 服务证书轮换。 Kubernetes 版本 1.27 或更高版本上的新节点池将默认启用 kubelet 提供证书轮换。 若要查看是否已在你的区域中启用了 kubelet 服务证书轮换,请参阅 AKS 版本

验证 kubelet 服务证书轮换是否已启用

启用该功能的每个节点都将自动获得标签 kubernetes.azure.com/kubelet-serving-ca=cluster。 使用kubectl get nodes -L kubernetes.azure.com/kubelet-serving-ca命令验证是否已设置标签。

kubectl get nodes -L kubernetes.azure.com/kubelet-serving-ca

验证 kubelet 是否经历 TLS 引导过程

启用此功能后,运行节点的每个 kubelet 都应经历服务 TLS 引导过程

使用 kubectl get 命令获取群集中的当前 CSR 对象,验证启动过程是否正在进行。

kubectl get csr --field-selector=spec.signerName=kubernetes.io/kubelet-serving

所有服务 CSR 都应处于 Approved,Issued 状态,指示 CSR 已获得批准并被颁发签名证书。 服务 CSR 的签名者名称为 kubernetes.io/kubelet-serving

   NAME        AGE    SIGNERNAME                                    REQUESTOR                    REQUESTEDDURATION   CONDITION
csr-8mx4w   113s   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:uoxr9r      none              Approved,Issued
csr-bchlj   111s   kubernetes.io/kubelet-serving                 system:node:akswinp7000000   none              Approved,Issued
csr-sb4wz   46m    kubernetes.io/kubelet-serving                 system:node:akswinp6000000   none              Approved,Issued
csr-zc4wt   46m    kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:ho7zyu      none              Approved,Issued

验证 kubelet 是否使用从服务器 TLS 引导获取的证书

若要确认节点的 kubelet 是否使用由群集 CA 签名的服务证书,请使用 [kubectl debug][kubectl-debug] 检查 kubelet 的 PKI 目录的内容。

kubectl debug node/<node> -ti --image=mcr.azk8s.cn/azurelinux/base/core:3.0 -- ls -l /host/var/lib/kubelet/kubelet-server-current.pem

如果kubelet-server-current.pem符号链接存在,那么 kubelet 已通过 TLS 引导过程引导/更新自己的服务证书,并由集群证书授权中心 (CA) 签署。

禁用 kubelet 服务证书轮换

可以通过使用 az aks nodepool update 命令指定标记 aks-disable-kubelet-serving-certificate-rotation=true,然后重镜像节点来更新节点池,从而禁用 kubelet 服务证书轮换。 可以通过节点映像升级,或者通过将池缩减为 0 个实例,然后再恢复到所需的值,来完成节点重镜像。

az aks nodepool update --cluster-name myCluster --resource-group myResourceGroup --name mynodepool --tags aks-disable-kubelet-serving-certificate-rotation=true

后续步骤

本文介绍了如何手动和自动轮换群集的证书、CA 和 SA。 有关详细信息,请参阅 Azure Kubernetes 服务 (AKS) 中的群集安全性和升级的最佳做法