排查将映像从 Azure 容器注册表拉取到 Azure Kubernetes 服务群集时遇到的故障

注意

本文有帮助吗? 你的输入对我们很重要。 请使用此页上的 “反馈 ”按钮告诉我们本文为你工作得有多好,或者我们如何改进它。

将Microsoft Azure 容器注册表与 Azure Kubernetes 服务(AKS)一起使用时,必须建立身份验证机制。 可以使用几个简单的 Azure CLI 或 Azure PowerShell 命令设置 AKS 到容器注册表集成。 与 AKS 群集关联的 kubelet 标识被分配了 容器注册表读取者角色(适用于已启用属性访问控制(ABAC)的注册表)或 AcrPull 角色(适用于未启用 ABAC 的注册表),以便从容器注册表中提取映像。 请参阅 Microsoft Entra 基于属性的访问控制(ABAC)以获取有关存储库权限的更多信息,详细了解在 ACR 注册表是否启用 ABAC 的情况下分配所需的 ACR 角色。

在某些情况下,尝试将映像从容器注册表拉取到 AKS 群集失败。 本文提供有关将映像从容器注册表拉取到 AKS 群集时遇到的最常见错误的指南。

开始之前

本文假定你有现有的 AKS 群集和现有的容器注册表。 参阅以下快速入门:

还需要安装并配置 Azure CLI 2.0.59 或更高版本。 运行 az 版本 以确定版本。 如果必须安装或升级,请参阅 “安装 Azure CLI”。

症状和初始故障排除

Kubernetes Pod 的状态ImagePullBackOffErrImagePull。 若要获取详细的错误信息,请运行以下命令并检查 输出中的事件

kubectl describe pod <podname> -n <namespace>

建议通过检查 容器注册表的运行状况 并检查容器注册表是否可从 AKS 群集访问容器注册表来开始进行故障排除。

若要检查容器注册表的运行状况,请运行以下命令:

az acr check-health --name <myregistry> --ignore-errors --yes

如果检测到问题,它会提供错误代码和说明。 有关错误和可能的解决方案的详细信息,请参阅 运行状况检查错误参考

注意

如果您收到与 Helm 或 Notary 相关的错误,这并不意味着问题会影响容器注册表或 AKS。 它可以指示未安装 Helm 或 Notary,或者 Azure CLI 与 Helm 或 Notary 的当前安装版本不兼容。

若要验证容器注册表是否可从 AKS 群集访问,请运行以下 az aks check-acr 命令:

az aks check-acr --resource-group <MyResourceGroup> --name <MyManagedCluster> --acr <myacr>.azurecr.io

以下部分可帮助你排查命令输出中“事件kubectl describe pod最常见错误。

原因 1: 401 Unauthorized 错误

原因 1a: 401 Unauthorized 由于授权不正确而导致错误

AKS 群集需要标识。 此标识可以是托管标识或服务主体。 如果 AKS 群集使用托管标识,则 kubelet 标识用于使用 ACR 进行身份验证。 如果 AKS 群集用作服务主体的标识,则服务主体本身用于使用 ACR 进行身份验证。 无论标识是什么,都需要使用用于从容器注册表拉取映像的适当授权。 否则,可能会收到以下 401 Unauthorized 错误:

Failed to pull image "\<acrname>.azurecr.io/\<repository\:tag>": [rpc error: code = Unknown desc = failed to pull and unpack image "\<acrname>.azurecr.io/\<repository\:tag>": failed to resolve reference "\<acrname>.azurecr.io/\<repository\:tag>": failed to authorize: failed to fetch oauth token: unexpected status: 401 Unauthorized

多个解决方案可帮助你解决此错误,但受以下约束的约束:

解决方案 1:确保为身份创建正确的 ACR 角色分配

AKS 与容器注册表的集成在容器注册表层面为 AKS 集群的 kubelet 身份分配了正确的角色。

注意

请确保已创建正确的角色分配(Container Registry Repository Reader 用于已启用 ABAC 的注册表,以及 AcrPull 用于未启用 ABAC 的注册表)。 请参阅 Microsoft Entra 基于属性的访问控制 (ABAC) 的存储库权限 ,以详细了解根据注册中心是否启用了 ABAC 所需的正确 ACR 角色。

若要检查是否存在正确的 ACR 角色分配,请使用以下方法之一:

  • 运行下面的命令:

    az role assignment list --scope /subscriptions/<subscriptionID>/resourceGroups/<resourcegroupname>/providers/Microsoft.ContainerRegistry/registries/<acrname> -o table
    
  • 通过选择Azure 容器注册表Access 控件(IAM)>来签入Azure 门户。> 有关详细信息,请参阅使用Azure 门户列出 Azure 角色分配。

Container Registry Repository Reader角色(用于已启用 ABAC 的注册表)或AcrPull角色(用于未启用 ABAC 的注册表)之外,一些内置角色自定义角色还可以包含拉取映像所需的 Microsoft Entra 权限。 根据需要检查这些角色。

Container Registry Repository Reader如果在已启用 ABAC 的注册表中不存在该角色,或AcrPull在未启用 ABAC 的注册表中该角色不存在,那么您可以创建该角色的分配。

对于未启用 ABAC 的注册表,可以使用以下命令分配 AcrPull 角色:

az aks update -n <myAKSCluster> -g <myResourceGroup> --attach-acr <acr-resource-id>

对于已启用 ABAC 的注册表, az aks --attach-acr 该命令不支持添加 Container Registry Repository Reader 角色。 必须使用 Azure 管理门户或 az role assignment CLI 命令手动将此角色分配给 AKS kubelet 身份。

解决方案 2:确保服务主体未过期

确保与 AKS 群集关联的服务主体的机密未过期。 若要检查服务主体的到期日期,请运行以下命令:

SP_ID=$(az aks show --resource-group <myResourceGroup> --name <myAKSCluster> \
    --query servicePrincipalProfile.clientId -o tsv)

az ad app credential list --id "SP_ID" --query "[].endDateTime" --output tsv

有关详细信息,请参阅 检查服务主体的到期日期。

如果机密已过期, 请更新 AKS 群集的凭据。

解决方案 3:确保为正确的服务主体分配正确的 ACR 角色

在某些情况下,容器注册表角色分配仍指旧的服务主体。 例如,当 AKS 群集的服务主体替换为新群集时。 若要确保容器注册表角色分配引用正确的服务主体,请执行以下步骤:

  1. 若要检查 AKS 群集使用的服务主体,请运行以下命令:

    az aks show --resource-group <myResourceGroup> \
        --name <myAKSCluster> \
        --query servicePrincipalProfile.clientId \
        --output tsv
    
  2. 若要检查容器注册表角色分配引用的服务主体,请运行以下命令:

    az role assignment list --scope /subscriptions/<subscriptionID>/resourceGroups/<resourcegroupname>/providers/Microsoft.ContainerRegistry/registries/<acrname> -o table
    
  3. 比较两个服务主体。 如果它们不匹配,请再次将 AKS 群集与容器注册表集成。

解决方案 4:确保在 AKS 虚拟机规模集中引用 kubelet 标识

当托管标识用于使用 ACR 进行身份验证时,托管标识称为 kubelet 标识。 默认情况下,kubelet 标识在 AKS 虚拟机规模集层分配。 如果 kubelet 标识从 AKS 虚拟机规模集中删除,AKS 节点无法从 ACR 拉取映像。

若要查找 AKS 群集的 kubelet 标识,请运行以下命令:

az aks show --resource-group <MyResourceGroup> --name <MyManagedCluster> --query identityProfile.kubeletidentity

然后,可以通过从节点资源组打开虚拟机规模集,并在 Azure 门户中选择标识>用户分配,或者运行以下命令,列出 AKS 虚拟机规模集的标识:

az vmss identity show --resource-group <NodeResourceGroup> --name <AksVmssName>

如果未将 AKS 群集的 kubelet 身份分配给 AKS 虚拟机规模集,请将其重新分配回去。

注意

不支持使用基础设施即服务(IaaS)API 或 Azure 门户修改 AKS 虚拟机规模集,并且任何 AKS 操作都无法从 AKS 虚拟机规模集中删除 kubelet 标识。 这意味着某些内容或某人删除了它,例如团队成员执行的手动删除。 若要防止此类删除或修改,请考虑使用 NRGLockdown 功能

由于不支持对 AKS 虚拟机规模集的修改,因此它们不会在 AKS 级别传播。 若要将 kubelet 身份重新分配给 AKS 虚拟机规模集,需要执行协调操作。 为此,请运行以下命令:

az aks update --resource-group <MyResourceGroup> --name <MyManagedCluster>

解决方案 5:确保服务主体正确且机密有效

如果使用映像拉取机密拉取映像 ,并且 Kubernetes 机密是使用服务主体的值创建的,请确保关联的服务主体正确且机密仍然有效。 执行以下步骤:

  1. 运行以下 kubectl getbase64 命令以查看 Kubernetes 机密的值:

    kubectl get secret <secret-name> --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
    
  2. 通过运行以下 az ad sp credential list 命令来检查到期日期。 用户名是服务主体值。

    az ad sp credential list --id "<username>" --query "[].endDate" --output tsv
    
  3. 如有必要,请运行以下 az ad sp credential reset 命令来重置该服务主体的机密:

    az ad sp credential reset --name "$SP_ID" --query password --output tsv
    
  4. 相应地更新或重新创建 Kubernetes 机密。

解决方案 6:确保 Kubernetes 机密具有容器注册表管理员帐户的正确值

如果使用映像拉取机密拉取映像,并且 Kubernetes 机密是使用容器注册表管理员帐户的值创建的,请确保 Kubernetes 机密中的值与容器注册表管理员帐户的值相同。 执行以下步骤:

  1. 运行以下 kubectl getbase64 命令以查看 Kubernetes 机密的值:

    kubectl get secret <secret-name> --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
    
  2. Azure 门户中,搜索并选择“容器注册表”。

  3. 在容器注册表列表中,选择容器注册表。

  4. 在容器注册表的导航窗格中,选择 “访问”键

  5. 在容器注册表的 “访问密钥 ”页中,将容器注册表值与 Kubernetes 机密中的值进行比较。

  6. 如果值不匹配,请相应地更新或重新创建 Kubernetes 密钥。

注意

如果发生 重新生成 密码操作,在容器注册表的Regenerate Container Registry Login Credentials页面中将显示一个名为的操作。 活动日志的保留期90 天。

原因 1b: 401 Unauthorized 由于体系结构不兼容而导致错误

即使 AKS 群集标识获得授权(如原因 1a 部分所述:由于授权不正确401 Unauthorized 错误401 Unauthorized),也可能会遇到错误。 如果 ACR 中的容器映像与运行容器的节点的体系结构(如 ARM64 与 AMD64)不匹配,则可能会出现此问题。 例如,在 AMD64 节点上部署 ARM64 映像,反之亦然可能会导致此错误。

错误消息如下所示:

Failed to pull image "\<acrname>.azurecr.io/\<repository:\tag>": [rpc error: code = NotFound desc = failed to pull and unpack image "\<acrname>.azurecr.io/\<repository:\tag>": no match for platform in manifest: not found, failed to pull and unpack image "\<acrname>.azurecr.io/\<repository\:tag>": failed to resolve reference "\<acrname>.azurecr.io/\<repository\:tag>": failed to authorize: failed to fetch anonymous token: unexpected status from GET request to https://\<acrname>.azurecr.io/oauth2/token?scope=repository%3A\<repository>%3Apull&service=\<acrname>.azurecr.io: 401 Unauthorized]

使用 Azure CLI 诊断此问题时,如果系统节点池运行的体系结构与 ACR 中的映像不同,可能会出现意外 exec format 错误:

az aks check-acr --resource-group <MyResourceGroup> --name <MyManagedCluster> --acr <myacr>.azurecr.io

exec /canipull: exec format error

解决方案:使用正确的体系结构推送映像或推送多体系结构映像

若要解决此问题,请使用以下方法之一:

  • 确保推送到 ACR 的容器映像与 AKS 节点的体系结构(例如 ARM64 或 AMD64)匹配。
  • 创建和推送支持 ARM64 和 AMD64 体系结构的多体系结构映像。

原因 2:找不到图像错误

未找到图像错误如下所示:

Failed to pull image "\<acrname>.azurecr.io/\<repository\:tag>": [rpc error: code = NotFound desc = failed to pull and unpack image "\<acrname>.azurecr.io/\<repository\:tag>": failed to resolve reference "\<acrname>.azurecr.io/\<repository\:tag>": \<acrname>.azurecr.io/\<repository\:tag>: not found

解决方案:确保法师名称正确

如果看到此错误,请确保映像名称正确。 检查注册表名称、注册表登录服务器、存储库名称和标记。

注意

常见的错误是,登录服务器被指定为 azureacr.io 而不是 azurecr.io

如果映像名称未完全正确,则 401 未授权错误 也可能发生,因为 AKS 始终尝试匿名拉取,而不管容器注册表是否启用了匿名拉取访问。

原因 3: 403 forbidden 错误

错误消息 403 Forbidden 如下所示:

Failed to pull image "\<acrname>.azurecr.io/\<repository\:tag>": rpc error: code = Unknown desc = failed to pull and unpack image "\<acrname>.azurecr.io/\<repository\:tag>": failed to resolve reference "\<acrname>.azurecr.io/\<repository\:tag>": failed to authorize: failed to fetch anonymous token: unexpected status: 403 Forbidden

如果容器注册表的专用终结点和 AKS 群集的网络接口位于不同的虚拟网络中,请确保在容器注册表的专用 DNS 区域中设置 AKS 群集虚拟网络的 虚拟网络链接 。 (默认情况下,该链接被命名为 privatelink.azurecr.io)。如果虚拟网络链接不在容器注册表的专用 DNS 区域中,请使用以下任一方法添加它:

  • 使用 Azure 门户:
  1. 在 Azure 门户中,选择专用 DNS 区域 privatelink.azurecr.io
  2. “设置”中,选择“添加虚拟网络链接>”。
  3. 选择 AKS 群集的名称和虚拟网络,然后选择“ 确定”。

注意

可以选择 “启用自动注册 ”功能。

解决方案 2:将 AKS 负载均衡器的公共 IP 地址添加到容器注册表的允许 IP 地址范围

如果 AKS 群集公开连接到容器注册表(不是 通过专用链接或终结点),并且容器注册表的公共网络访问仅限于所选网络,请使用以下步骤将 AKS 负载均衡器的公共 IP 地址添加到容器注册表的允许 IP 地址范围:

  1. 验证公共网络访问是否仅限于所选网络。

    1. 在Azure 门户中,导航到容器注册表。
    2. 在“设置”中,选择“网络”。
    3. 在“ 公共访问 ”选项卡上,将 公用网络访问权限 设置为 “所选网络 ”或 “已禁用”。
  2. 使用以下方法之一获取 AKS 负载均衡器的公共 IP 地址:

    • 使用 Azure 门户;

      1. 在Azure 门户中,导航到 AKS 群集。
      2. 在“设置”中,选择“属性”
      3. 选择基础结构资源组中的虚拟机规模集之一,并检查 AKS 负载均衡器的公共 IP 地址。
    • 运行下面的命令:

      az network public-ip show --resource-group <infrastructure-resource-group> --name <public-IP-name> --query ipAddress -o tsv
      
  3. 使用以下方法之一允许从 AKS 负载均衡器的公共 IP 地址进行访问:

    • 按如下所示运行az acr network-rule add命令:

      az acr network-rule add --name acrname --ip-address <AKS-load-balancer-public-IP-address>
      

      有关详细信息,请参阅 将网络规则添加到注册表

    • 使用 Azure 门户:

      1. 在Azure 门户中,导航到容器注册表。
      2. 在“设置”中,选择“网络”。
      3. 在“ 公共访问 ”选项卡上的 “防火墙”中,将 AKS 负载均衡器的公共 IP 地址添加到 地址范围 ,然后选择“ 保存”。

      有关详细信息,请参阅 从所选公用网络访问 - 门户

      注意

      如果 公用网络访问 设置为 “已禁用”,请先将其切换到 “所选网络 ”。

      有关如何将 AKS 负载均衡器的公共 IP 地址添加到地址范围的屏幕截图

原因 4: i/o timeout 错误

错误消息 i/o timeout 如下所示:

Failed to pull image "\<acrname>.azurecr.io/\<repository\:tag>": rpc error: code = Unknown desc = failed to pull and unpack image "\<acrname>.azurecr.io/\<repository\:tag>": failed to resolve reference "\<acrname>.azurecr.io/<repository\:tag>": failed to do request: Head "https://\<acrname>.azurecr.io/v2/\<repository>/manifests/v1": dial tcp \<acrprivateipaddress>:443: i/o timeout

注意

i/o timeout仅当使用 Azure 专用链接以私密方式连接到容器注册表时,才会发生此错误。

解决方案 1:确保使用虚拟网络对等互连

如果容器注册表的专用终结点和 AKS 群集的网络接口位于不同的虚拟网络中,请确保 将虚拟网络对等互连 用于这两个虚拟网络。 可以通过运行 Azure CLI 命令az network vnet peering list --resource-group <MyResourceGroup> --vnet-name <MyVirtualNetwork> --output table或在 Azure 门户中选择 VNET>对等互连设置 面板来检查虚拟网络对等互连。 有关列出指定虚拟网络的所有对等互连的详细信息,请参阅 az network vnet 对等互连列表

如果两个虚拟网络都使用虚拟网络对等互连,请确保状态为 “已连接”。 如果状态为 “断开连接”,请从两个虚拟网络中删除对等互连,然后重新创建它。 如果状态为“已连接”,请参阅故障排除指南:对等互连状态为“已连接”。

若要进一步进行故障排除,请连接到其中一个 AKS 节点或 Pod ,然后使用 telnet 或 netcat 实用工具在 TCP 级别测试与容器注册表的连接。 使用 nslookup <acrname>.azurecr.io 命令检查 IP 地址,然后运行 telnet <ip-address-of-the-container-registry> 443 该命令。

有关连接到 AKS 节点的详细信息,请参阅使用 SSH 连接到 Azure Kubernetes 服务 (AKS) 群集节点进行维护或故障排除

解决方案 2:使用 Azure 防火墙

如果容器注册表的专用终结点和 AKS 群集的网络接口位于不同的虚拟网络中(除了虚拟网络对等互连),则可以使用 Azure 防火墙 在 Azure 中设置中心辐射型网络拓扑。 设置防火墙规则时,需要使用网络规则显式允许 到容器注册表专用终结点 IP 地址的出站连接

原因 5:清单中的平台不匹配

主机操作系统(节点 OS)与用于 Pod 或容器的映像不兼容。 例如,如果计划 Pod 在 Windows 节点上运行 Linux 容器,或 Linux 节点上的 Windows 容器,则会发生以下错误:

Failed to pull image "\<acrname>.azurecr.io/\<repository:tag>"\:\ [\ &nbsp; rpc error:\ &nbsp; code = NotFound\ &nbsp; desc = failed to pull and unpack image "\<acrname>.azurecr.io/\<repository:tag>": **no match for platform in manifest**: not found,\ ]

如果映像与主机 OS 不兼容,则从任何源拉取的映像会出现此错误。 错误不限于从容器注册表拉取的映像。

解决方案:在 Pod 或部署中正确配置 nodeSelector 字段

在 Pod 或部署的配置设置中指定正确的 nodeSelector 字段。 此字段设置的正确 kubernetes.io/os 值可确保 Pod 按正确的节点类型进行计划。 下表显示了如何在 YAML 中设置 kubernetes.io/os 设置:

容器类型 YAML 设置
Linux 容器 "kubernetes.io/os": linux
Windows 容器 "kubernetes.io/os": windows

例如,以下 YAML 代码描述了需要在 Linux 节点上计划的 Pod:

apiVersion: v1
kind: Pod
metadata:
  name: aspnetapp
  labels:
    app: aspnetapp
spec:
  containers:
  - image: "mcr.microsoft.com/dotnet/core/samples:aspnetapp"
    name: aspnetapp-image
    ports:
    - containerPort: 80
      protocol: TCP
  nodeSelector:
    "kubernetes.io/os": linux

原因 6:Kubelet 超出默认映像拉取速率限制

当多个作业拉取相同的映像时,可以超出 kubelet 默认拉取速率限制。 在这种情况下,将显示如下所示的错误消息:

Failed to pull image "acrname.azurecr.io/repo/nginx:latest": pull QPS exceeded. This occurred for pod \<podname\> at 4/22/2025, 12:48:32.000 PM UTC.

有关限制的详细信息,请参阅 registryPullQPS 配置

解决方案:将 imagePullPolicy 的值更改为 IfNotPresent

若要解决此问题,请将 imagePullPolicy 的值从 Always 部署 YAML 文件中更改为 IfNotPresent 防止不必要的拉取。 IfNotPresent 确保仅当映像尚未存在于节点上时才从注册表拉取。

下面是部署 YAML 文件的示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: myacr.azurecr.io/my-image:latest
        imagePullPolicy: IfNotPresent

其他注意事项

如果本文中的故障排除指南无助于解决问题,请考虑以下一些其他事项:

  • 检查与子网关联的网络安全组和路由表(如果有这些项)。

  • 如果虚拟设备(如防火墙)控制子网之间的流量,请检查防火墙和 防火墙访问规则

第三方信息免责声明

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

联系我们寻求帮助

如果有疑问,可以询问 Azure 社区支持。 你还可以将产品反馈提交到 Azure 反馈社区