Istio 服务网格加载项插件 CA 证书故障排除

本文讨论 Istio 加载项插件证书颁发机构 (CA) 证书功能的常见故障排除问题,并提供解决这些问题的解决方案。 本文还回顾了为服务网格加载项设置插件 CA 证书的一般过程。

注意

本文假定 Istio 修订版 asm-1-21 部署在群集上。

先决条件

常规设置过程

  • 在启用 Istio 加载项以使用插件 CA 证书功能之前,必须在群集上为机密存储加载项启用 Azure 密钥库 提供程序。 确保 Azure 密钥库和群集位于同一 Azure 租户上。

  • 启用 Azure 密钥库机密提供程序加载项后,必须为加载项创建的用户分配的托管标识设置对 Azure 密钥库的访问权限。

  • 授予用户分配的托管标识访问 Azure 密钥库的权限后,可以将插件 CA 证书功能与 Istio 加载项一起使用。 有关详细信息,请参阅 “启用 Istio 加载项以使用插件 CA 证书 ”部分。

  • 若要使群集自动检测 Azure 密钥库 机密中的更改,必须为 Azure 密钥库 机密提供程序加载项启用自动轮换

  • 尽管自动应用对中间证书的更改,但在部署由加载项部署的 cronjob 重启部署后istiod,才会选取对根证书所做的更改,如“已部署的资源”部分所述。 此 cronjob 以 10 分钟的间隔运行。

启用 Istio 加载项以使用插件 CA 证书

Istio 加载项 插件 CA 证书 功能允许为网格配置插件根证书和中间证书。 若要在启用加载项时提供插件证书信息,请在 Azure CLI 中为 az aks mesh enable 命令指定以下参数。

参数 说明
--key-vault-id<resource-id> Azure 密钥库资源 ID。 此资源应与托管群集位于同一租户中。 此资源 ID 必须采用 Azure 资源管理器 模板(ARM 模板)资源 ID 格式
--root-cert-object-name<root-cert-obj-name> Azure 密钥库中的根证书对象名称。
--ca-cert-object-name<inter-cert-obj-name> Azure 密钥库中的中间证书对象名称。
--ca-key-object-name<inter-key-obj-name> Azure 密钥库中的中间证书私钥对象名称。
--cert-chain-object-name<cert-chain-obj-name> Azure 密钥库中的证书链对象名称。

如果要使用插件 CA 证书功能,则必须指定所有五个参数。 所有 Azure 密钥库 对象应属于机密类型

有关详细信息,请参阅基于 Istio 的服务网格加载项的插件 CA 证书Azure Kubernetes 服务

已部署资源

作为插件证书功能的加载项部署的一部分,以下资源将部署到群集:

  • cacerts在加载项部署时,aks-istio-system会在命名空间中创建 Kubernetes 机密。 此机密包含同步的 Azure 密钥库 机密:

    kubectl describe secret cacerts --namespace aks-istio-system
    
    Name:         cacerts
    Namespace:    aks-istio-system
    Labels:       secrets-store.csi.k8s.io/managed=true
    Annotations:  <none>
    
    Type:  opaque
    
    Data
    ====
    ca-cert.pem:     1968 bytes
    ca-key.pem:      3272 bytes
    cert-chain.pem:  3786 bytes
    root-cert.pem:   3636 bytes
    
  • istio-spc-asm-1-21 在加载项部署时,aks-istio-system在命名空间中创建 SecretProviderClass 对象。 此资源包含机密存储容器存储接口 (CSI) 驱动程序的特定于 Azure 的参数:

    kubectl get secretproviderclass --namespace aks-istio-system
    
    NAME                 AGE
    istio-spc-asm-1-21   14h
    
  • istio-ca-root-cert configmap 是在命名空间和所有用户管理的命名空间中创建aks-istio-system的。 此配置映射包含证书颁发机构使用的根证书,命名空间中的工作负荷使用它来验证工作负荷到工作负荷的通信,如下所示:

    kubectl describe configmap istio-ca-root-cert --namespace aks-istio-system
    
    Name:         istio-ca-root-cert
    Namespace:    aks-istio-system
    Labels:       istio.io/config=true
    Annotations:  <none>
    
    Data
    ====
    root-cert.pem:
    ----
    -----BEGIN CERTIFICATE-----
    <certificate data>
    -----END CERTIFICATE-----
    
  • cronjob istio-cert-validator-cronjob-asm-1-21 对象 是在命名空间中创建的 aks-istio-system 。 此 cronjob 计划每隔 10 分钟运行一次,以检查根证书上的更新。 如果 Kubernetes 机密中的cacerts根证书与命名空间中的 aks-istio-system configmap 不匹配istio-ca-root-cert,则会重启istiod-asm-1-21部署:

    kubectl get cronjob --namespace aks-istio-system
    
    NAME                                    SCHEDULE       SUSPEND   ACTIVE
    istio-cert-validator-cronjob-asm-1-21   */10 * * * *   False     0     
    

    可以运行以下命令来检查上次运行的 cronjob 日志:

    kubectl logs --namespace aks-istio-system $(kubectl get pods --namespace aks-istio-system | grep 'istio-cert-validator-cronjob-' | sort -k8 | tail -n 1 | awk '{print $1}')
    

    此命令生成以下输出消息之一,具体取决于是否检测到根证书更新:

    Root certificate update not detected.
    
    Root certificate update detected. Restarting deployment...
    deployment.apps/istiod-asm-1-21 restarted
    Deployment istiod-asm-1-21 restarted.
    

确定部署日志中的证书类型

可以查看 istiod 部署日志,以确定是拥有自签名 CA 证书还是插件 CA 证书。 若要查看日志,请运行以下命令:

kubectl logs deploy/istiod-asm-1-21 --container discovery --namespace aks-istio-system | grep -v validationController

在每个证书日志条目之前,紧接着是描述该类型的证书的另一个日志条目。 对于自签名的 CA 证书,条目指出“没有插入证书在 etc/cacerts/ca-key.pem;使用自签名证书。”对于插件证书,条目指出“在 etc/cacerts/ca-key.pem 中使用插入证书”。下表显示了与证书相关的示例日志条目。

  • 自签名 CA 证书的日志条目

    Timestamp 日志级别 消息
    2023-11-20T23:27:36.649019Z info 使用 istiod 文件格式对 ca 文件进行签名
    2023-11-20T23:27:36.649032Z info 在 etc/cacerts/ca-key.pem 上没有插入证书;使用自签名证书
    2023-11-20T23:27:36.649536Z info x509 证书 - <证书详细信息>
    2023-11-20T23:27:36.649552Z info 重新加载 Istiod 证书
    2023-11-20T23:27:36.649613Z info spiffe 在对等证书验证程序中添加了 1 个证书,用于信任域群集.local
  • 插件 CA 证书的日志条目

    Timestamp 日志级别 消息
    2023-11-21T00:20:25.808396Z info 使用 istiod 文件格式对 ca 文件进行签名
    2023-11-21T00:20:25.808412Z info 在 etc/cacerts/ca-key.pem 上使用插入证书
    2023-11-21T00:20:25.808731Z info x509 证书 - <证书详细信息>
    2023-11-21T00:20:25.808764Z info x509 证书 - <证书详细信息>
    2023-11-21T00:20:25.808799Z info x509 证书 - <证书详细信息>
    2023-11-21T00:20:25.808803Z info 重新加载 Istiod 证书
    2023-11-21T00:20:25.808873Z info spiffe 在对等证书验证程序中添加了 1 个证书,用于信任域群集.local

日志条目中的证书详细信息显示为颁发者、使用者、序列号(SN(长十六进制字符串)的逗号分隔值,以及定义证书有效时间的开始和结束时间戳值。

对于自签名 CA 证书,有一个详细信息条目。 下表显示了此证书的示例值。

颁发者 Subject SN NotBefore NotAfter
“O=cluster.local” "" <32 位十六进制值> “2023-11-20T23:25:36Z” “2033-11-17T23:27:36Z”

对于插件 CA 证书,有三个详细信息条目。 其他两个条目用于根证书更新和对中间证书的更改。 下表显示了这些条目的示例值。

颁发者 Subject SN NotBefore NotAfter
CN=中间 CA - A1,O=Istio,L=cluster-A1” "" <32 位十六进制值> “2023-11-21T00:18:25Z” “2033-11-18T00:20:25Z”
CN=Root A,O=Istio” “CN=中间 CA - A1,O=Istio,L=cluster-A1” <40 位十六进制值> “2023-11-04T01:40:22Z” “2033-11-01T01:40:22Z”
CN=Root A,O=Istio” “CN=Root A,O=Istio” <40 位十六进制值> “2023-11-04T01:38:27Z” “2033-11-01T01:38:27Z”

排查常见问题

问题 1:对 Azure 密钥库的访问设置不正确

启用 Azure 密钥库机密提供程序加载项后,必须向 Azure 密钥库授予加载项的用户分配托管标识的访问权限。 设置对 Azure 密钥库的访问不正确会导致加载项安装停止。

kubectl get pods --namespace aks-istio-system

在 Pod 列表中,可以看到 istiod-asm-1-21 Pod 停滞在 Init:0/2 某个状态。

名称 就绪 状态 RESTARTS 年龄
istiod-asm-1-21-6fcfd88478-2x95b 0/1 正在终止 0 5m55s
istiod-asm-1-21-6fcfd88478-6x5hh 0/1 正在终止 0 5m40s
istiod-asm-1-21-6fcfd88478-c48f9 0/1 Init:0/2 0 54s
istiod-asm-1-21-6fcfd88478-wl8mw 0/1 Init:0/2 0 39 秒

若要验证 Azure 密钥库访问问题,请kubectl get pods运行以下命令以查找命名空间中具有secrets-store-provider-azure标签的 kube-system Pod:

kubectl get pods --selector app=secrets-store-provider-azure --namespace kube-system --output name | xargs -I {} kubectl logs --namespace kube-system {}

以下示例输出显示发生“403 禁止访问”错误,因为你对密钥库的机密没有“get”权限:

“无法处理装载请求”err=“未能获取 objectType:secret, objectName:<secret-object-name>, objectVersion:: keyvault。BaseClient#GetSecret:响应请求失败:StatusCode=403 -- 原始错误:autorest/azure:服务返回错误。 Status=403 Code=\“Forbidden\” Message=\“User, group or application 'appid=<appid>;oid=<oid>;iss=<iss>“ 没有机密获取密钥保管库”MyAzureKeyVault“的权限;location=eastus'. 有关解决此问题的帮助,请参阅 https://go.microsoft.com/fwlink/?linkid=2125287\“ InnerError={\”code\“:\”AccessDenied\“}”

若要解决此问题,请通过获取对 Azure 密钥库 机密的 Get 和 List 权限并重新安装 Istio 加载项来设置对 Azure 密钥库 机密提供程序加载项的用户分配托管标识的访问权限。 首先,通过运行 az aks show 命令,获取 Azure 密钥库 机密提供程序加载项的用户分配托管标识的对象 ID:

OBJECT_ID=$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER --query 'addonProfiles.azureKeyvaultSecretsProvider.identity.objectId')

若要设置访问策略,请通过指定获取的对象 ID 来运行以下 az keyvault set-policy 命令:

az keyvault set-policy --name $AKV_NAME --object-id $OBJECT_ID --secret-permissions get list

注意

是否使用 Azure RBAC 授权为权限模型而不是保管库访问策略创建密钥库? 在这种情况下,请参阅使用 Azure 基于角色的访问控制提供对密钥库密钥、证书和机密的访问权限,以创建托管标识的权限。 为密钥库读取者添加 Azure 角色分配,以便为加载项的用户分配托管标识。

问题 2:未设置自动检测密钥库机密更改

若要使群集自动检测 Azure 密钥库 机密中的更改,必须为 Azure 密钥库 提供程序加载项启用自动轮换。 自动轮换可以自动检测中间证书和根证书中的更改。 对于启用 Azure 密钥库 提供程序加载项的群集,请az aks show运行以下命令来检查是否启用了自动轮换:

az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER | jq -r '.addonProfiles.azureKeyvaultSecretsProvider.config.enableSecretRotation'

如果群集启用了 Azure 密钥库 提供程序加载项,请az aks show运行以下命令来确定轮询间隔:

az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER | jq -r '.addonProfiles.azureKeyvaultSecretsProvider.config.rotationPollInterval'

Azure 密钥库在上一次同步后轮询间隔时间过后与群集同步。 默认间隔值为两分钟。

问题 3:证书值缺失或配置不正确

如果 Azure 密钥库中缺少机密对象,或者这些对象配置不正确,istiod-asm-1-21Pod 可能会停滞在Init:0/2状态中,从而延迟加载项的安装。 若要查找此问题的根本原因,请针对istiod部署运行以下命令kubectl describe并查看输出:

kubectl describe deploy/istiod-asm-1-21 --namespace aks-istio-system

该命令显示可能与以下输出表类似的事件。 在此示例中,缺少机密是问题的原因。

类型 原因 年龄 From 消息
正常 计划 3m9s default-scheduler 已成功将 aks-istio-system/istiod-asm-1-21-6fcfd88478-hqdjjj 分配到 aks-userpool-24672518-vmss000000
警告 FailedMount 66s kubelet 无法附加或装载卷:卸载的卷=[cacerts]、未附加的卷=[]、无法处理卷=[]:等待条件超时
警告 FailedMount 61s (x9 超过 3m9s) kubelet 卷“cacerts”的 MountVolume.SetUp 失败:rpc 错误:代码 = 未知 desc = 无法为 pod aks-istio-system/istiod-asm-1-21-6fcfd88478-hqdjj 装载机密存储对象, err: rpc error: code = Unknown desc = failed to mount objects, error: failed to get objectType:secret, objectName:test-cert-chain, objectVersion:: keyvault.BaseClient#GetSecret:响应请求失败:StatusCode=404 -- 原始错误:autorest/azure:服务返回错误。 Status=404 Code=“SecretNotFound” Message=“A secret with (name/id) test-cert-chain 的机密未在此密钥保管库中找到。 如果最近删除了此机密,则可以使用正确的恢复命令恢复它。 有关解决此问题的帮助,请参阅 https://go.microsoft.com/fwlink/?linkid=2125182

资源

第三方信息免责声明

本文中提到的第三方产品由 Microsoft 以外的其他公司提供。 Microsoft 对这些产品的性能和可靠性不作任何明示或默示担保。

第三方联系人免责声明

Microsoft 会提供第三方联系信息来帮助你查找有关本主题的其他信息。 此联系信息可能会更改,恕不另行通知。 Microsoft 不保证第三方联系信息的准确性。

联系我们寻求帮助

如果你有任何疑问或需要帮助,请创建支持请求联系 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区