Azure Container Registry Azure Kubernetes Service 클러스터로 이미지를 끌어오지 못했습니다.

참고

이 문서가 도움이 되었나요? 귀하의 입력은 우리에게 중요합니다. 이 페이지의 피드백 단추를 사용하여 이 문서가 얼마나 잘 작동했는지 또는 어떻게 개선할 수 있는지 알려주세요.

MICROSOFT Azure Container Registry AKS(Azure Kubernetes Service)와 함께 사용하는 경우 인증 메커니즘을 설정해야 합니다. 몇 가지 간단한 Azure CLI 또는 Azure PowerShell 명령을 사용하여 AKS와 Container Registry 통합을 설정할 수 있습니다. 이 통합은 AKS 클러스터와 연결된 kubelet ID에 대한 AcrPull 역할을 할당하여 컨테이너 레지스트리에서 이미지를 가져옵니다.

경우에 따라 컨테이너 레지스트리에서 AKS 클러스터로 이미지를 끌어오려고 하면 실패합니다. 이 문서에서는 컨테이너 레지스트리에서 AKS 클러스터로 이미지를 끌어올 때 발생하는 가장 일반적인 오류 문제를 해결하기 위한 지침을 제공합니다.

시작하기 전에

이 문서에서는 기존 AKS 클러스터와 기존 컨테이너 레지스트리가 있다고 가정합니다. 다음 빠른 시작을 참조하세요.

또한 Azure CLI 버전 2.0.59 이상을 설치하고 구성해야 합니다. az version을 실행하여 버전을 확인합니다. 설치 또는 업그레이드해야 하는 경우 Azure CLI 설치를 참조하세요.

증상 및 초기 문제 해결

Kubernetes Pod의 상태는ImagePullBackOff 또는 ErrImagePull입니다. 자세한 오류 정보를 얻으려면 다음 명령을 실행하고 출력에서 이벤트를 검사.

kubectl describe pod <podname> -n <namespace>

컨테이너 레지스트리의 상태를 확인하고 AKS 클러스터에서 컨테이너 레지스트리에 액세스할 수 있는지 확인하여 문제 해결을 시작하는 것이 좋습니다.

컨테이너 레지스트리의 상태를 검사 다음 명령을 실행합니다.

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

문제가 감지되면 오류 코드와 설명을 제공합니다. 오류 및 가능한 해결 방법에 대한 자세한 내용은 상태 검사 오류 참조를 참조하세요.

참고

Helm 관련 또는 공증 관련 오류가 발생하는 경우 문제가 Container Registry 또는 AKS에 영향을 주는 것은 아닙니다. Helm 또는 공증이 설치되지 않았거나 Azure CLI가 현재 설치된 Helm 또는 공증 버전과 호환되지 않음을 나타냅니다.

AKS 클러스터에서 컨테이너 레지스트리에 액세스할 수 있는지 확인하려면 다음 az aks 검사-acr 명령을 실행합니다.

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

다음 섹션에서는 명령 출력의 kubectl describe pod이벤트에 표시되는 가장 일반적인 오류를 해결하는 데 도움이 됩니다.

원인 1: 401 권한 없음 오류

AKS 클러스터에는 ID가 필요합니다. 이 ID는 관리 ID 또는 서비스 주체일 수 있습니다. AKS 클러스터가 관리 ID를 사용하는 경우 kubelet ID는 ACR을 사용하여 인증하는 데 사용됩니다. AKS 클러스터가 서비스 주체를 ID로 사용하는 경우 서비스 주체 자체는 ACR을 사용하여 인증하는 데 사용됩니다. ID가 무엇이든 간에 컨테이너 레지스트리에서 이미지를 끌어오는 데 사용되는 적절한 권한 부여가 필요합니다. 그렇지 않으면 다음과 같은 "401 권한 없음" 오류가 발생할 수 있습니다.

이미지 "<acrname.azurecr.io/<> repository:tag>": [rpc error: code = Unknown desc = 이미지 "<acrname.azurecr.io/<> repository:tag>를 끌어오고 압축을 풀지 못했습니다. ": 참조 "<acrname.azurecr.io/<> repository:tag>"를 resolve 못했습니다. 권한을 부여하지 못했습니다. oauth 토큰을 가져오지 못했습니다. 예기치 않은 상태: 401 권한 없음

몇 가지 솔루션은 다음 제약 조건에 따라 이 오류를 resolve 데 도움이 될 수 있습니다.

해결 방법 1: ID에 대한 AcrPull 역할 할당이 생성되었는지 확인

AKS와 Container Registry 간의 통합은 AKS 클러스터의 kubelet ID에 대한 컨테이너 레지스트리 수준에서 AcrPull 역할 할당을 만듭니다. 역할 할당이 생성되었는지 확인합니다.

AcrPull 역할 할당이 생성되었는지 여부를 검사 하려면 다음 방법 중 하나를 사용합니다.

  • 다음 명령을 실행합니다.

    az role assignment list --scope /subscriptions/<subscriptionID>/resourceGroups/<resourcegroupname>/providers/Microsoft.ContainerRegistry/registries/<acrname> -o table
    
  • Azure Container Registry Access 컨트롤(IAM)>역할 할당을 선택하여 Azure Portal> 확인합니다. 자세한 내용은 Azure Portal 사용하여 Azure 역할 할당 나열을 참조하세요.

AcrPull 역할 외에도 일부 기본 제공 역할사용자 지정 역할에 는 "Microsoft.ContainerRegistry/registries/pull/read" 작업이 포함될 수도 있습니다. 해당 역할이 있는지 확인합니다.

AcrPull 역할 할당이 만들어지지 않은 경우 다음 명령을 사용하여 AKS 클러스터에 대한 Container Registry 통합을 구성 하여 만듭니다.

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

해결 방법 2: 서비스 주체가 만료되지 않았는지 확인

AKS 클러스터와 연결된 서비스 주체의 비밀이 만료되지 않았는지 확인합니다. 서비스 주체의 만료 날짜를 검사 다음 명령을 실행합니다.

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

az ad sp credential list --id "$SP_ID" --query "[].endDate" -o tsv

자세한 내용은 서비스 주체의 만료 날짜 확인을 참조하세요.

비밀이 만료된 경우 AKS 클러스터에 대한 자격 증명을 업데이트합니다.

해결 방법 3: 올바른 서비스 주체에 AcrPull 역할이 할당되었는지 확인

경우에 따라 컨테이너 레지스트리 역할 할당은 여전히 이전 서비스 주체를 참조합니다. 예를 들어 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: KUbelet ID가 AKS VMSS에서 참조되는지 확인합니다.

ACR을 사용한 인증에 관리 ID를 사용하는 경우 관리 ID를 kubelet ID라고 합니다. 기본적으로 kubelet ID는 AKS VMSS 수준에서 할당됩니다. kubelet ID가 AKS VMSS에서 제거된 경우 AKS 노드는 ACR에서 이미지를 끌어올 수 없습니다.

AKS 클러스터의 kubelet ID를 찾으려면 다음 명령을 실행합니다.

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

그런 다음 노드 리소스 그룹에서 VMSS를 열고 Azure Portal할당된 ID 사용자를 선택하거나 다음 명령을 실행하여 AKS VMSS의 ID>를 나열할 수 있습니다.

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

AKS 클러스터의 kubelet ID가 AKS VMSS에 할당되지 않은 경우 다시 할당합니다.

참고

IaaS API 또는 Azure Portal 사용하여 AKS VMSS를 수정하는 것은 지원되지 않으며 AKS 작업은 AKS VMSS에서 kubelet ID를 제거할 수 없습니다. 즉, 예기치 않은 항목이 제거되었습니다(예: 팀 구성원이 수동으로 제거). 이러한 제거 또는 수정을 방지하려면 NRGLockdown 기능을 사용하는 것이 좋습니다.

AKS VMSS에 대한 수정은 지원되지 않으므로 AKS 수준에서 전파되지 않습니다. kubelet ID를 AKS VMSS에 다시 할당하려면 조정 작업이 필요합니다. 이렇게 하려면 다음 명령을 실행합니다.

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 Portal컨테이너 레지스트리를 검색하여 선택합니다.

  3. 컨테이너 레지스트리 목록에서 컨테이너 레지스트리를 선택합니다.

  4. 컨테이너 레지스트리의 탐색 창에서 액세스 키를 선택합니다.

  5. 컨테이너 레지스트리의 액세스 키 페이지에서 컨테이너 레지스트리 값을 Kubernetes 비밀의 값과 비교합니다.

  6. 값이 일치하지 않으면 그에 따라 Kubernetes 비밀을 업데이트하거나 다시 만듭니다.

참고

암호 다시 생성 작업이 발생한 경우 "컨테이너 레지스트리 로그인 자격 증명 다시 생성"이라는 작업이 컨테이너 레지스트리의 활동 로그 페이지에 표시됩니다. 활동 로그보존 기간은 90일입니다.

원인 2: 이미지를 찾을 수 없음 오류

"acrname.azurecr.io/ repository:tag>" 이미지를< 끌어오지 못했습니다. [rpc error: code = NotFound desc = 이미지 "acrname.azurecr.io/ repository:tag>": 참조 "<<acrname.azurecr.io/<>> repository:tag>"<를 resolve 못했습니다. acrname.azurecr.io/>< repository:tag>: 찾을 수 없음<><

해결 방법: 이미지 이름이 올바른지 확인

이 오류가 표시되면 이미지 이름이 완전히 올바른지 확인합니다. 레지스트리 이름, 레지스트리 로그인 서버, 리포지토리 이름 및 태그를 검사 합니다. 일반적인 실수는 로그인 서버가 "azurecr.io" 대신 "azureacr.io"로 지정된다는 것입니다.

이미지 이름이 완전히 올바르지 않으면 컨테이너 레지스트리에서 익명 끌어오기 액세스 사용하도록 설정했는지 여부에 관계없이 AKS가 항상 익명 끌어오기를 시도하기 때문에 401 권한 없는 오류도 발생할 수 있습니다.

원인 3: 403 사용할 수 없음 오류

"<acrname.azurecr.io/< repository:tag>": rpc error: code = Unknown desc = 이미지 "<acrname.azurecr.io/>>< repository:tag>를 끌어오고 압축을 풀지 못했습니다. ": 참조 "<acrname.azurecr.io/<> repository:tag>"를 resolve 못했습니다. 권한을 부여하지 못했습니다. 익명 토큰을 가져오지 못했습니다. 예기치 않은 상태: 403 사용할 수 없음

컨테이너 레지스트리의 프라이빗 엔드포인트 및 AKS 클러스터의 네트워크 인터페이스가 서로 다른 가상 네트워크에 있는 경우 AKS 클러스터의 가상 네트워크에 대한 가상 네트워크 링크가 컨테이너 레지스트리의 프라이빗 DNS 영역에 설정되어 있는지 확인합니다. 이 링크의 이름은 기본적으로 "privatelink.azurecr.io"입니다. 가상 네트워크 링크가 컨테이너 레지스트리의 프라이빗 DNS 영역에 없는 경우 다음 방법 중 하나를 사용하여 추가합니다.

해결 방법 2: 컨테이너 레지스트리의 허용된 IP 주소 범위에 AKS Load Balancer 공용 IP 주소 추가

AKS 클러스터가 컨테이너 레지스트리에 공개적으로 연결되고(프라이빗 링크 또는 엔드포인트를 통하지 않음) 컨테이너 레지스트리의 공용 네트워크 액세스가 선택한 네트워크로 제한되는 경우 AKS Load Balancer 공용 IP 주소를 컨테이너 레지스트리의 허용된 IP 주소 범위에 추가합니다.

  1. 공용 네트워크 액세스가 선택한 네트워크로 제한되는지 확인합니다.

    Azure Portal 컨테이너 레지스트리로 이동합니다. 설정에서 네트워킹을 선택합니다. 공용 액세스 탭에서 공용 네트워크 액세스선택한 네트워크 또는 사용 안 함으로 설정됩니다.

  2. 다음 방법 중 하나를 사용하여 AKS Load Balancer 공용 IP 주소를 가져옵니다.

    • Azure Portal AKS 클러스터로 이동합니다. 설정에서 속성을 선택하고 인프라 리소스 그룹에서 가상 머신 확장 집합 중 하나를 선택하고 AKS Load Balancer 공용 IP 주소를 검사.

    • 다음 명령을 실행합니다.

      az network public-ip show --resource-group <infrastructure-resource-group> --name <public-IP-name> --query ipAddress -o tsv
      
  3. 다음 방법 중 하나를 사용하여 AKS Load Balancer 공용 IP 주소에서 액세스를 허용합니다.

    • 명령을 다음과 같이 실행 az acr network-rule add 합니다.

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

      자세한 내용은 레지스트리에 네트워크 규칙 추가를 참조하세요.

    • Azure Portal 컨테이너 레지스트리로 이동합니다. 설정에서 네트워킹을 선택합니다. 공용 액세스 탭의 방화벽에서 AKS Load Balancer 공용 IP 주소를 주소 범위에 추가한 다음 저장을 선택합니다. 자세한 내용은 선택한 공용 네트워크에서 액세스 - 포털을 참조하세요.

      참고

      공용 네트워크 액세스사용 안 함으로 설정된 경우 먼저 선택한 네트워크로 전환합니다.

      AKS Load Balancer 공용 IP 주소를 주소 범위에 추가하는 방법에 대한 스크린샷

원인 4: 443 시간 제한 오류

"acrname.azurecr.io/ repository:tag": rpc error: code = Unknown desc = "acrname.azurecr.io/<><> repository:tag>" 이미지를< 끌어오지 못했습니다. "acrna"를 참조<하지 resolve 못했습니다.me.azurecr.io/>< repository:tag>": 요청을 수행하지 못했습니다. 헤드 "https://< acrname.azurecr.io/v2/>< repository>/manifests/v1": dial tcp <acrprivateipaddress>:443: i/o>< 타임 아웃

참고

"443 시간 제한" 오류는 Azure Private Link 사용하여 컨테이너 레지스트리에 비공개로 연결하는 경우에만 발생합니다.

해결 방법 1: 가상 네트워크 피어링이 사용되는지 확인

컨테이너 레지스트리의 프라이빗 엔드포인트와 AKS 클러스터의 네트워크 인터페이스가 서로 다른 가상 네트워크에 있는 경우 가상 네트워크 피어링 이 두 가상 네트워크에 모두 사용되는지 확인합니다. Azure CLI 명령을 az network vnet peering list --resource-group <MyResourceGroup> --vnet-name <MyVirtualNetwork> --output table 실행하거나 설정 패널에서 VNET> 피어링을 선택하여 Azure Portal 가상 네트워크피어링을 검사 수 있습니다. 지정된 가상 네트워크의 모든 피어링을 나열하는 방법에 대한 자세한 내용은 az network vnet peering list를 참조하세요.

가상 네트워크 피어링이 두 가상 네트워크에 모두 사용되는 경우 상태 "연결됨"인지 확인합니다. 상태 연결이 끊어진 경우 두 가상 네트워크에서 피어링을 삭제한 다음 다시 만듭니다. 상태 "연결됨"인 경우 문제 해결 가이드: 피어링 상태 "연결됨"을 참조하세요.

추가 문제 해결을 위해 AKS 노드 또는 Pod 중 하나에 연결한 다음 텔넷 또는 Netcat 유틸리티를 사용하여 TCP 수준에서 컨테이너 레지스트리와의 연결을 테스트합니다. 명령을 사용하여 IP 주소를 nslookup <acrname>.azurecr.io 확인한 다음 명령을 실행합니다 telnet <ip-address-of-the-container-registry> 443 .

AKS 노드에 연결하는 방법에 대한 자세한 내용은 유지 관리 또는 문제 해결을 위해 SSH를 사용하여 AKS(Azure Kubernetes Service) 클러스터 노드에 연결을 참조하세요.

해결 방법 2: Azure Firewall 서비스 사용

컨테이너 레지스트리의 프라이빗 엔드포인트 및 AKS 클러스터의 네트워크 인터페이스가 가상 네트워크 피어링 외에도 다른 가상 네트워크에 있는 경우 Azure Firewall Service를 사용하여 Azure에서 허브 스포크 네트워크 토폴로지를 설정할 수 있습니다. 방화벽 규칙을 설정할 때 네트워크 규칙을 사용하여 컨테이너 레지스트리 프라이빗 엔드포인트 IP 주소에 대한 아웃바운드 연결을 명시적으로 허용해야 합니다.

원인 5: 매니페스트의 플랫폼과 일치하지 않음

호스트 운영 체제(노드 OS)는 Pod 또는 컨테이너에 사용되는 이미지와 호환되지 않습니다. 예를 들어 Windows 노드에서 Linux 컨테이너를 실행하도록 Pod를 예약하거나 Linux 노드의 Windows 컨테이너를 예약하면 다음 오류가 발생합니다.

"<acrname.azurecr.io/>< repository:tag>" 이미지를 끌어오지 못했습니다.
[
  rpc 오류:
  code = NotFound
  desc = "<acrname.azurecr.io/>< repository:tag>": 매니페스트의 플랫폼과 일치하지 않음: 찾을 수 없음,
]

이 오류는 이미지가 호스트 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

추가 정보

이 문서의 문제 해결 지침이 문제를 resolve 데 도움이 되지 않는 경우 고려해야 할 몇 가지 다른 사항은 다음과 같습니다.

  • 해당 항목이 있는 경우 서브넷과 연결된 네트워크 보안 그룹 및 경로 테이블을 확인합니다.

  • 방화벽과 같은 가상 어플라이언스 서브넷 간의 트래픽을 제어하는 경우 방화벽 및 방화벽 액세스 규칙을 검사.

타사 정보 고지 사항

이 문서에 나와 있는 다른 공급업체 제품은 Microsoft와 무관한 회사에서 제조한 것입니다. Microsoft는 이들 제품의 성능이나 안정성에 관하여 명시적이든 묵시적이든 어떠한 보증도 하지 않습니다.

도움을 요청하십시오.

질문이 있거나 도움이 필요한 경우 지원 요청을 생성하거나Azure 커뮤니티 지원에 문의하세요. Azure 피드백 커뮤니티에 제품 피드백을 제출할 수도 있습니다.