---
title: Integrate Azure Container Registry with Azure Kubernetes Service (AKS)
description: Learn how to integrate Azure Kubernetes Service (AKS) with Azure Container Registry (ACR).
ms.topic: concept-article
ms.date: 05/08/2026
author: davidsmatlak
ms.author: davidsmatlak
ms.tool: azure-cli, azure-powershell
ms.devlang: azurecli
ms.custom: devx-track-azurepowershell, devx-track-azurecli
zone_pivot_groups: cli-powershell-terraform

# Customer intent: As a cloud administrator, I want to integrate Azure Container Registry with Azure Kubernetes Service, so that I can streamline the deployment of container images and manage access permissions efficiently.
---

# Authenticate with Azure Container Registry (ACR) from Azure Kubernetes Service (AKS)

When using [Azure Container Registry (ACR)][acr-intro] with Azure Kubernetes Service (AKS), you need to establish an authentication mechanism. You can configure the required permissions between ACR and AKS using the Azure CLI, Azure PowerShell, or Azure portal. This article provides examples to configure authentication between these Azure services using the Azure CLI or Azure PowerShell.

The AKS to ACR integration assigns the [AcrPull role][acr-pull] to the [Microsoft Entra ID managed identity][aad-identity] associated with the agent pool in your AKS cluster. For more information on AKS managed identities, see [Summary of managed identities][summary-msi].

> [!IMPORTANT]
> There's a latency issue with Microsoft Entra groups when attaching ACR. If the `AcrPull` role is granted to a Microsoft Entra group and the kubelet identity is added to the group to complete the Azure role-based access control (Azure RBAC) configuration, there might be a delay before the RBAC group takes effect. If you're running automation that requires the Azure RBAC configuration to be complete, we recommend you use [Bring your own kubelet identity][byo-kubelet-identity] as a workaround. You can precreate a user-assigned identity, add it to the Microsoft Entra group, then use the identity as the kubelet identity to create an AKS cluster. This method ensures the identity is added to the Microsoft Entra group before a token is generated by kubelet, which avoids the latency issue.

> [!NOTE]
> This article covers automatic authentication between AKS and ACR. If you need to pull an image from a private external registry, use an [image pull secret][image-pull-secret].

> [!CAUTION]
> The AKS-ACR integration through `az aks --attach-acr` isn't supported for ABAC-enabled ACR registries where the role assignment permissions mode is set to "RBAC Registry + ABAC Repository Permissions." ABAC-enabled ACR registries require the [`Container Registry Repository Reader` role](/azure/role-based-access-control/built-in-roles#container-registry-repository-reader) instead of the `AcrPull` role for granting image pull permissions. For ABAC-enabled ACR registries, you shouldn't use `az aks --attach-acr` but instead manually assign the `Container Registry Repository Reader` role assignment using either the Azure portal, `az role assignment` CLI, or Azure Resource Manager. For more information on ABAC-enabled ACR registries, see [Azure attribute-based access control](https://aka.ms/acr/auth/abac).

In this walkthrough, you configure an Azure Kubernetes Service (AKS) cluster to securely pull images from an Azure Container Registry (ACR). In Azure CLI, use `--attach-acr`. In Terraform, assign the `AcrPull` role to the AKS kubelet managed identity. This guide follows the same flow as the Azure CLI workflow while using Terraform for infrastructure provisioning.

## Before you begin

- You need the [**Owner**][rbac-owner], [**Azure account administrator**][rbac-classic], or [**Azure co-administrator**][rbac-classic] role on your Azure subscription.
  - To avoid the need for these roles, you can instead use an existing managed identity to authenticate ACR from AKS. For more information, see [Use an Azure managed identity to authenticate to an ACR](/azure/container-registry/container-registry-authentication-managed-identity).

:::zone pivot="azure-cli, terraform"

- If you're using Azure CLI, this article requires that you're running Azure CLI version 2.7.0 or later. to find the version, run the `az --version` command. If you need to install or upgrade, see [Install Azure CLI][azure-cli-install].

:::zone-end

:::zone pivot="azure-powershell"

- If you're using Azure PowerShell, this article requires that you're running Azure PowerShell version 5.9.0 or later. To find the version, run the `Get-InstalledModule -Name Az` command. If you need to install or upgrade, see [Install Azure PowerShell][azure-powershell-install].
- Examples and syntax to use Terraform for configuring ACR can be found in the [Terraform reference][terraform-reference].

:::zone-end

:::zone pivot="terraform"

- Terraform installed (`>= 1.6`).
- Azure CLI installed and signed in to your subscription.
- Permissions to assign roles (Owner or User Access Administrator).

In this article, you configure an Azure Kubernetes Service (AKS) cluster to securely pull images from an Azure Container Registry (ACR). In Azure CLI, use `--attach-acr`. In Terraform, assign the `AcrPull` role to the AKS kubelet managed identity.

This article follows the same flow as the Azure CLI workflow while using Terraform for infrastructure provisioning. To verify you're signed in to the correct subscription, use the following Azure CLI commands:

```azurecli-interactive
az login
az account show
```

:::zone-end

## Create a new ACR

:::zone pivot="azure-cli"

If you don't already have an ACR, create one using the [`az acr create`][az-acr-create] command.

The registry name must be globally unique within Azure, and contain 5-50 alphanumeric characters, excluding dash (`-`) characters. This name is part of the fully qualified DNS name of the registry.

```azurecli-interactive
export RANDOM_STRING=$(printf '%05d%05d' "$RANDOM" "$RANDOM")
export MYACR="mycontainerregistry$RANDOM_STRING"
export ACR_RESOURCE_GROUP="myContainerRegistryResourceGroup"
export LOCATION="westcentralus"

az group create \
  --name $ACR_RESOURCE_GROUP \
  --location $LOCATION

az acr create \
  --name $MYACR \
  --resource-group $ACR_RESOURCE_GROUP \
  --sku basic
```

The `RANDOM_STRING` variable stores a random 10-digit string. The `MYACR` value is concatenated with the `RANDOM_STRING` value to create a unique name.

:::zone-end

:::zone pivot="azure-powershell"

If you don't already have an ACR, create one using the [`New-AzContainerRegistry`][new-azcontainerregistry] cmdlet.

The registry name must be globally unique within Azure, and contain 5-50 alphanumeric characters, excluding dash (`-`) characters. This name is part of the fully qualified DNS name of the registry.

```azurepowershell-interactive
$RandomString = (Get-Random -Minimum 1000000000 -Maximum 10000000000).ToString()
$MyAcr = "mycontainerregistry$RandomString"
$AcrResourceGroup = "myContainerRegistryResourceGroup"
$Location = "westcentralus"

New-AzResourceGroup -Name $AcrResourceGroup -Location $Location

$NewAcr = @{
 Name = $MyAcr
 ResourceGroupName = $AcrResourceGroup
 Location = $Location
 Sku = "Basic"
}

New-AzContainerRegistry @NewAcr
```

The `$RandomString` variable stores a random 10-digit string. The `$MyAcr` value is concatenated with the `$RandomString` value to create a unique name.


:::zone-end

:::zone pivot="terraform"

Create a _main.tf_ file for the configuration, and begin by defining the Terraform providers and generating a unique suffix for globally unique resource names. A globally unique name ensures your Azure Container Registry name doesn't conflict with existing registries.

```terraform
terraform {
 required_version = ">= 1.6.0"
 required_providers {
   azurerm = {
     source  = "hashicorp/azurerm"
     version = "~> 4.0"
   }
   random = {
     source  = "hashicorp/random"
     version = "~> 3.6"
   }
 }
}
provider "azurerm" {
 features {}
}
resource "random_string" "suffix" {
 length  = 6
 upper   = false
 special = false
}
```

:::zone-end

## Create a new AKS cluster and integrate with an existing ACR

:::zone pivot="azure-cli"

Create a new AKS cluster and integrate with an existing ACR using the [`az aks create`][az-aks-create] command with the [`--attach-acr`][cli-param] parameter. This command allows you to authorize an existing ACR in your subscription and configures the appropriate `AcrPull` role for the managed identity.

```azurecli-interactive
export CLUSTER_NAME="myAKSCluster"
export CLUSTER_RESOURCE_GROUP="myClusterResourceGroup"

az group create \
  --name $CLUSTER_RESOURCE_GROUP \
  --location $LOCATION

az aks create \
  --name $CLUSTER_NAME \
  --resource-group $CLUSTER_RESOURCE_GROUP \
  --generate-ssh-keys \
  --attach-acr $MYACR
```

### Use an ACR in a different subscription or attach using resource ID

If you're using an ACR located in a different subscription from your AKS cluster or would prefer to use the ACR _resource ID_ instead of the ACR name, use the following syntax. This example creates the `ACR_RESOURCE_ID` variable using the container registry created in the previous section.

```azurecli
ACR_RESOURCE_ID=$(az acr show \
  --name $MYACR \
  --resource-group $ACR_RESOURCE_GROUP \
  --query id --output tsv)

az aks create \
  --name $CLUSTER_NAME \
  --resource-group $CLUSTER_RESOURCE_GROUP \
  --generate-ssh-keys \
  --attach-acr $ACR_RESOURCE_ID
```

:::zone-end

:::zone pivot="azure-powershell"

Create a new AKS cluster and integrate with an existing ACR using the [`New-AzAksCluster`][new-azakscluster] cmdlet with the [`-AcrNameToAttach`][ps-attach] parameter. This command allows you to authorize an existing ACR in your subscription and configures the appropriate `AcrPull` role for the managed identity.

```azurepowershell-interactive
$ClusterName = "myAKSCluster"
$ClusterResourceGroup = "myClusterResourceGroup"

New-AzResourceGroup -Name $ClusterResourceGroup -Location $Location

$NewCluster = @{
 Name = $ClusterName
 ResourceGroupName = $ClusterResourceGroup
 GenerateSshKey = $true
 AcrNameToAttach = $MyAcr
}

New-AzAksCluster @NewCluster
```

### Use an ACR in a different subscription or attach using resource ID

Azure PowerShell only supports attaching ACR to AKS using the `-AcrNameToAttach` parameter and doesn't support attaching to an ACR by _resource ID_.

:::zone-end


:::zone pivot="terraform"

Next, create a resource group and an Azure Container Registry. This registry stores the container images that your AKS cluster pulls later.

```terraform
locals {
 location           = "westcentralus"
 acr_name           = "myacr${random_string.suffix.result}"
 acr_resource_group = "myContainerRegistryResourceGroup"
}
resource "azurerm_resource_group" "acr_rg" {
 name     = local.acr_resource_group
 location = local.location
}
resource "azurerm_container_registry" "acr" {
 name                = local.acr_name
 resource_group_name = azurerm_resource_group.acr_rg.name
 location            = azurerm_resource_group.acr_rg.location
 sku                 = "Basic"
 admin_enabled       = false
}
```

Now create the AKS cluster that consumes images from the registry. This cluster uses a **system-assigned managed identity**, which will be granted permission to pull images.

```terraform
locals {
 aks_name           = "myAKSCluster"
 aks_resource_group = "myClusterResourceGroup"
}
resource "azurerm_resource_group" "aks_rg" {
 name     = local.aks_resource_group
 location = local.location
}
resource "azurerm_kubernetes_cluster" "aks" {
 name                = local.aks_name
 location            = azurerm_resource_group.aks_rg.location
 resource_group_name = azurerm_resource_group.aks_rg.name
 dns_prefix          = local.aks_name
 identity {
   type = "SystemAssigned"
 }
 default_node_pool {
   name       = "systempool"
   node_count = 2
   vm_size    = "Standard_DS2_v2"
 }
}
```

At this stage, the AKS cluster exists, but it doesn't yet have access to the container registry. In Azure CLI, use the `--attach-acr` parameter. In Terraform, you explicitly assign the `AcrPull` role.

```terraform
resource "azurerm_role_assignment" "aks_acr_pull" {
 scope                = azurerm_container_registry.acr.id
 role_definition_name = "AcrPull"
 principal_id         = azurerm_kubernetes_cluster.aks.kubelet_identity[0].object_id
}
```

:::zone-end

## Configure ACR integration for an existing AKS cluster

You can attach an ACR to an existing AKS cluster, or detach an ACR from an AKS cluster if you no longer want the cluster to have access to the registry.

The previous examples in the article created an Azure Container Registry and an Azure Kubernetes Service cluster attached to the ACR. The following are examples of how to attach or detach a container registry from a cluster and use the ACR and AKS cluster created in this article. You can replace the variable values with your own ACR and AKS cluster values.

### Attach an ACR to an existing AKS cluster

:::zone pivot="azure-cli"

Integrate an existing ACR with an existing AKS cluster using the [`az aks update`][az-aks-update] command with the [`--attach-acr`][cli-param] parameter.

```azurecli-interactive
# Attach using acr-name
az aks update \
  --name $CLUSTER_NAME \
  --resource-group $CLUSTER_RESOURCE_GROUP \
  --attach-acr $MYACR


# Attach using acr-resource-id
az aks update \
  --name $CLUSTER_NAME \
  --resource-group $CLUSTER_RESOURCE_GROUP \
  --attach-acr $ACR_RESOURCE_ID
```

The `az aks update --attach-acr` command uses the permissions of the user running the command to create the ACR role assignment. This role is assigned to the [kubelet][kubelet] managed identity. For more information on AKS managed identities, see [Summary of managed identities][summary-msi].

:::zone-end

:::zone pivot="azure-powershell"

Integrate an existing ACR with an existing AKS cluster using the [`Set-AzAksCluster`][set-azakscluster] command with the [`-AcrNameToAttach`][ps-attach] parameter.

```azurepowershell-interactive
$AttachCluster = @{
 Name = $ClusterName
 ResourceGroupName = $ClusterResourceGroup
 AcrNameToAttach = $MyAcr
}

Set-AzAksCluster @AttachCluster
```

The `Set-AzAksCluster -AcrNameToAttach` cmdlet uses the permissions of the user running the command to create the role ACR assignment. This role is assigned to the [kubelet][kubelet] managed identity. For more information on AKS managed identities, see [Summary of managed identities][summary-msi].

:::zone-end


:::zone pivot="terraform"

If your AKS cluster already exists, you can attach an ACR by referencing both resources and creating the same role assignment.

```terraform
data "azurerm_kubernetes_cluster" "existing_aks" {
 name                = "myAKSCluster"
 resource_group_name = "myClusterResourceGroup"
}
data "azurerm_container_registry" "existing_acr" {
 name                = "mycontainerregistry"
 resource_group_name = "myContainerRegistryResourceGroup"
}
resource "azurerm_role_assignment" "existing_aks_acr_pull" {
 scope                = data.azurerm_container_registry.existing_acr.id
 role_definition_name = "AcrPull"
 principal_id         = data.azurerm_kubernetes_cluster.existing_aks.kubelet_identity[0].object_id
}
```

:::zone-end

### Detach an ACR from an AKS cluster

:::zone pivot="azure-cli"

Remove the integration between an ACR and an AKS cluster using the [`az aks update`][az-aks-update] command with the [`--detach-acr`][cli-param] parameter.

```azurecli-interactive
# Detach using acr-name
az aks update \
  --name $CLUSTER_NAME \
  --resource-group $CLUSTER_RESOURCE_GROUP \
  --detach-acr $MYACR

# Detach using acr-resource-id
az aks update \
  --name $CLUSTER_NAME \
  --resource-group $CLUSTER_RESOURCE_GROUP \
  --detach-acr $ACR_RESOURCE_ID
```

:::zone-end

:::zone pivot="azure-powershell"

Remove the integration between an ACR and an AKS cluster using the [`Set-AzAksCluster`][set-azakscluster] command with the [`-AcrNameToDetach`][ps-detach] parameter.

```azurepowershell-interactive
$DetachCluster = @{
 Name = $ClusterName
 ResourceGroupName = $ClusterResourceGroup
 AcrNameToDetach = $MyAcr
}

Set-AzAksCluster @DetachCluster
```

:::zone-end


:::zone pivot="terraform"

To remove access, delete the role assignment that grants the cluster permission to pull images.

```terraform
# Remove this resource to revoke access
# resource "azurerm_role_assignment" "existing_aks_acr_pull" {
#   scope                = data.azurerm_container_registry.existing_acr.id
#   role_definition_name = "AcrPull"
#   principal_id         = data.azurerm_kubernetes_cluster.existing_aks.kubelet_identity[0].object_id
# }
```

:::zone-end

:::zone pivot="terraform"

## Initialize and deploy the configuration

After your configuration is complete, initialize Terraform and review the execution plan before applying.

```bash
terraform fmt
terraform init
terraform validate
terraform plan
terraform apply
```

At this point, your AKS cluster is configured to pull images from ACR.

You can now:
- Import images into ACR.
- Deploy workloads to AKS.
- Verify pod deployment.

:::zone-end

## Working with ACR and AKS

Import an image into your ACR, then deploy that image to your AKS cluster.

### Import an image into your ACR

:::zone pivot="azure-cli, terraform"

Import an image from Docker Hub into your ACR using the [`az acr import`][az-acr-import] command.

```azurecli-interactive
az acr import \
  --name $MYACR \
  --source docker.io/library/nginx:latest \
  --image nginx:v1
```

Run the following commands to verify the image was imported.

```azurecli-interactive
az acr repository show --name $MYACR --repository nginx
az acr repository show-tags --name $MYACR --repository nginx
```

:::zone-end

:::zone pivot="azure-powershell"

Import an image from Docker Hub into your ACR using the [`Import-AzContainerRegistryImage`][import-azcontainerregistryimage] cmdlet.

```azurepowershell-interactive
$ImportImage = @{
 RegistryName = $MyAcr
 ResourceGroupName = $AcrResourceGroup
 SourceRegistryUri = 'docker.io'
 SourceImage = 'library/nginx:latest'
 TargetTag = 'nginx:v1'
}

Import-AzContainerRegistryImage @ImportImage
```

Run the following commands to verify the image was imported.

```azurepowershell-interactive
Get-AzContainerRegistryRepository -RegistryName $MyAcr

Get-AzContainerRegistryTag -RegistryName $MyAcr -Repository nginx
```

:::zone-end

### Create deployment file

Create a Kubernetes deployment that references the image you imported into ACR. If the deployment is successful and the image is pulled correctly, your AKS cluster is properly integrated with ACR.

Create a file named _acr-nginx.yaml_ using the following sample YAML. In the `image` property, replace _acr-name_ with the name of your ACR. In Azure CLI, run `echo $MYACR` to display the ACR name. In Azure PowerShell, run `$MyAcr` to display the ACR name.

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx0-deployment
  labels:
    app: nginx0-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx0
  template:
    metadata:
      labels:
        app: nginx0
    spec:
      containers:
      - name: nginx
        image: <acr-name>.azurecr.io/nginx:v1
        ports:
        - containerPort: 80
```


### Get credentials and run deployment

:::zone pivot="azure-cli, terraform"

1. Ensure you have the proper AKS credentials using the [`az aks get-credentials`][az-aks-get-credentials] command.

    ```azurecli-interactive
    az aks get-credentials \
      --resource-group $CLUSTER_RESOURCE_GROUP \
      --name $CLUSTER_NAME
    ```

1. Run the deployment in your AKS cluster using the `kubectl apply` command.

    ```shell
    kubectl apply -f acr-nginx.yaml
    ```

1. Monitor the deployment using the `kubectl get pods` command.

    ```shell
    kubectl get pods
    ```

    The output should show two running pods, as shown in the following example output:

    ```output
    NAME                                 READY   STATUS    RESTARTS   AGE
    nginx0-deployment-669dfc4d4b-x74kr   1/1     Running   0          20s
    nginx0-deployment-669dfc4d4b-xdpd6   1/1     Running   0          20s
    ```

:::zone-end

:::zone pivot="azure-powershell"

1. Ensure you have the proper AKS credentials using the [`Import-AzAksCredential`][import-azakscredential] cmdlet.

    ```azurepowershell-interactive
    Import-AzAksCredential -ResourceGroupName $ClusterResourceGroup -Name $ClusterName
    ```

1. Run the deployment in your AKS cluster using the `kubectl apply` command.

    ```shell
    kubectl apply -f acr-nginx.yaml
    ```

1. Monitor the deployment using the `kubectl get pods` command.

    ```shell
    kubectl get pods
    ```

    The output should show two running pods, as shown in the following example output:

    ```output
    NAME                                 READY   STATUS    RESTARTS   AGE
    nginx0-deployment-669dfc4d4b-x74kr   1/1     Running   0          20s
    nginx0-deployment-669dfc4d4b-xdpd6   1/1     Running   0          20s
    ```
:::zone-end

### Troubleshooting

- Validate the registry is accessible from the AKS cluster using the [`az aks check-acr`](/cli/azure/aks#az-aks-check-acr) command.
- If your AKS cluster uses an HTTP proxy and your ACR uses Private Link, add both ACR endpoints (REST and data) to the cluster `noProxy` list. For more information, see [HTTP proxy support in Azure Kubernetes Service (AKS)](/azure/aks/http-proxy).
- Learn more about [ACR monitoring](/azure/container-registry/monitor-service).
- Learn more about [ACR health](/azure/container-registry/container-registry-check-health).


## Clean up resources

When you no longer need the resources created in this article, you can delete the resource groups to remove all associated resources. These commands delete the ACR and AKS cluster and the clusters node resource group that begins with `MC_`.

:::zone pivot="azure-cli, terraform"

```azurecli-interactive
az group delete --name $ACR_RESOURCE_GROUP --yes --no-wait
az group delete --name $CLUSTER_RESOURCE_GROUP --yes --no-wait
```

:::zone-end

:::zone pivot="azure-powershell"

```azurepowershell-interactive
Remove-AzResourceGroup -Name $AcrResourceGroup -Force
Remove-AzResourceGroup -Name $ClusterResourceGroup -Force
```

:::zone-end

## Related content

- [Use a managed identity to authenticate to an Azure container registry](/azure/container-registry/container-registry-authentication-managed-identity)
- [HTTP proxy support in Azure Kubernetes Service (AKS)](/azure/aks/http-proxy)


<!-- LINKS EXTERNAL -->
[image-pull-secret]: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
[kubelet]: https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
[terraform-reference]: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/container_registry


<!-- LINKS INTERNAL -->

[byo-kubelet-identity]: use-managed-identity.md#create-a-kubelet-managed-identity
[summary-msi]: managed-identity-overview.md#summary-of-managed-identities-used-by-aks
[acr-pull]: /azure/role-based-access-control/built-in-roles#acrpull
[azure-cli-install]: /cli/azure/install-azure-cli
[azure-powershell-install]: /powershell/azure/install-az-ps
[acr-intro]: /azure/container-registry/container-registry-intro
[aad-identity]: /azure/active-directory/managed-identities-azure-resources/overview
[rbac-owner]: /azure/role-based-access-control/built-in-roles#owner
[rbac-classic]: /azure/role-based-access-control/rbac-and-directory-admin-roles#classic-subscription-administrator-roles
[ps-detach]: /powershell/module/az.aks/set-azakscluster#-acrnametodetach
[cli-param]: /cli/azure/aks#az-aks-update-optional-parameters
[ps-attach]: /powershell/module/az.aks/set-azakscluster#-acrnametoattach
[az-acr-import]: /cli/azure/acr#az-acr-import
[az-aks-get-credentials]: /cli/azure/aks#az-aks-get-credentials
[import-azakscredential]: /powershell/module/az.aks/import-azakscredential
[import-azcontainerregistryimage]: /powershell/module/az.containerregistry/import-azcontainerregistryimage
[set-azakscluster]: /powershell/module/az.aks/set-azakscluster
[az-aks-update]: /cli/azure/aks#az-aks-update
[new-azakscluster]: /powershell/module/az.aks/new-azakscluster
[az-aks-create]: /cli/azure/aks#az-aks-create
[az-acr-create]: /cli/azure/acr#az-acr-create
[new-azcontainerregistry]: /powershell/module/az.containerregistry/new-azcontainerregistry
