Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Migrate AKS pods from pod-managed identities to Microsoft Entra Workload ID (workload identity) using one of three approaches based on your current Azure Identity SDK version: latest SDK parallel deployment, migration sidecar proxy (Linux only), or SDK rewrite.
Prerequisites
- Azure CLI version 2.47.0 or later. Run the
az --versioncommand to find the version. If you need to install or upgrade, see Install Azure CLI.
Set environment variables
The following table lists the environment variables used in the commands throughout this article. Make sure to replace the placeholder values with your own values.
| Environment variable | Description | Example value |
|---|---|---|
SUBSCRIPTION_ID |
The ID of the Azure subscription where the AKS cluster and managed identity are created. | 00000000-0000-0000-0000-000000000000 |
RESOURCE_GROUP |
The name of the resource group where the AKS cluster and managed identity are created. | myResourceGroup |
LOCATION |
The Azure region where the AKS cluster and managed identity are created. | chinanorth3 |
CLUSTER_NAME |
The name of the AKS cluster. | myAKSCluster |
MANAGED_IDENTITY_NAME |
The name of the user-assigned managed identity. | myManagedIdentity |
SERVICE_ACCOUNT_NAME |
The name of the Kubernetes service account to create or associate with the managed identity. | workload-identity-sa |
SERVICE_ACCOUNT_NAMESPACE |
The namespace of the Kubernetes service account. | default |
FEDERATED_IDENTITY_NAME |
The name of the federated identity credential to create. | myFederatedIdentity |
Choose a migration path
Select the appropriate migration approach based on your current Azure Identity SDK version:
- Latest Azure Identity SDK: If your application already uses the latest version of Azure Identity SDK, you can migrate by deploying Microsoft Entra Workload ID in parallel with existing pod-managed identity.
- Older SDK with migration sidecar - If your application uses an older SDK version and runs on Linux containers, you can use a temporary migration sidecar to proxy Instance Metadata Service (IMDS) transactions while planning your SDK upgrade.
- Older SDK rewrite approach: If your application uses an older SDK version, you can update your application code to use the latest Azure Identity SDK, then migrate to workload identity.
Prepare for migration
For all migration paths, you need to have the federated trust set up before you update your application to use Microsoft Entra Workload ID. The following are the minimum steps required:
- Create a managed identity credential.
- Associate the user-assigned managed identity with the Kubernetes service account already used for the pod-managed identity or create a new Kubernetes service account and then associate it with the managed identity.
- Establish a federated trust relationship between the managed identity and Microsoft Entra ID using the OpenID Connect (OIDC) issuer URL and the service account.
Migrate from latest version of Azure Identity SDK
This migration path applies when your application already uses the latest version of the Azure Identity SDK and you want to migrate with minimal code changes.
Migration approach: Deploy Microsoft Entra Workload ID in parallel with pod-managed identity, verify functionality, then remove pod-managed identity.
Steps:
- Deploy Microsoft Entra Workload ID in parallel with existing pod-managed identity.
- Restart your application deployment to begin using Microsoft Entra Workload ID (OIDC annotations are injected automatically).
- Verify the application can authenticate successfully using workload identity.
- Remove the pod-managed identity annotations from your application.
- Remove the pod-managed identity add-on from your cluster.
Use a migration sidecar (Linux containers only)
This migration path applies when your application uses an older version of the Azure Identity SDK, runs on Linux containers, and you need a temporary solution while planning SDK updates.
Migration approach: Deploy a migration sidecar that proxies IMDS transactions to OIDC, allowing your existing application code to work without immediate changes.
Important limitations:
- Linux containers only. Windows containers aren't supported.
- Temporary solution that's not intended for long-term production use.
- Planning required to schedule SDK updates for long-term support.
Steps:
- Deploy the workload with migration sidecar to proxy IMDS transactions.
- Verify authentication transactions complete successfully.
- Schedule application SDK updates to supported Azure Identity versions.
- Once SDKs are updated, remove the proxy sidecar and redeploy applications.
Rewrite application for latest Azure Identity SDK
This migration path applies when your application uses an older version of the Azure Identity SDK and you want to update to the latest supported SDK before migrating.
Migration approach: Update your application code to use the latest Azure Identity SDK, then migrate to Microsoft Entra Workload ID with the updated code.
Technical outcomes:
- Uses current Azure Identity SDK versions (no deprecation timeline).
- Supports both Linux and Windows containers (unlike sidecar approach).
- Eliminates proxy components and IMDS translation overhead.
Steps:
- Update your application code to use the latest Azure Identity SDK.
- Test the updated application with pod-managed identity.
- Restart your application deployment to begin authenticating using Microsoft Entra Workload ID (OIDC annotations are injected automatically).
- Verify authentication transactions complete successfully.
- Remove the pod-managed identity annotations and add-on.
Set an active Azure subscription
Set a specific Azure subscription as the current active subscription using the
az account setcommand.az account set --subscription $SUBSCRIPTION_ID
Create a managed identity
Create a managed identity using the
az identity createcommand.az identity create --name $MANAGED_IDENTITY_NAME --resource-group $RESOURCE_GROUP --location $LOCATION --subscription $SUBSCRIPTION_ID
Get managed identity client ID
Get the client ID of the managed identity and save it to an environmental variable using the
az identity showcommand.export USER_ASSIGNED_CLIENT_ID="$(az identity show --resource-group $RESOURCE_GROUP --name $MANAGED_IDENTITY_NAME --query 'clientId' -otsv)"
Grant managed identity access to Azure resources
- Grant the managed identity the permissions needed to access the required Azure resources. Follow the steps in Assign a managed identity access to a resource to assign the appropriate role to the managed identity.
Get OIDC issuer URL
Get the OIDC issuer URL and save it to an environmental variable using the
az aks showcommand.export AKS_OIDC_ISSUER="$(az aks show --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --query "oidcIssuerProfile.issuerUrl" -o tsv)"The variable should contain an issuer URL similar to the following example:
https://eastus.oic.prod-aks.azure.com/00000000-0000-0000-0000-000000000000/00000000-0000-0000-0000-000000000000/By default, the issuer uses the base URL
https://{region}.oic.prod-aks.azure.com/{uuid}, where the value for{region}matches the location the AKS cluster is deployed in. The value{uuid}represents the OIDC key.
Get AKS cluster credentials
Get the AKS cluster credentials using the
az aks get-credentialscommand.az aks get-credentials --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP
Create Kubernetes service account
Create a Kubernetes service account and annotate it with the managed identity client ID using the
kubectl applycommand. Make sure to replace the placeholder values with your own values.cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID} name: ${SERVICE_ACCOUNT_NAME} namespace: ${SERVICE_ACCOUNT_NAMESPACE} EOFThe following output resembles successful creation of the identity:
Serviceaccount/workload-identity-sa created
Establish federated identity credential trust
Create the federated identity credential between the managed identity, service account issuer, and subject using the
az identity federated-credential createcommand.az identity federated-credential create --name $FEDERATED_IDENTITY_NAME --identity-name $MANAGED_IDENTITY_NAME --resource-group $RESOURCE_GROUP --issuer ${AKS_OIDC_ISSUER} --subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME} --audience api://AzureADTokenExchangeThe federated identity credential takes a few minutes to propagate after being added. If a token request is made immediately after adding the federated identity credential, the token request might fail because the Azure AD directory cache contains outdated information.
Deploy the workload with migration sidecar
If your application uses user-assigned managed identity and still relies on IMDS to get an access token you can use the migration sidecar to start migrating to Microsoft Entra Workload ID. In long-term applications, you should modify the code to use the latest Azure Identity SDKs that support client assertion.
To update or deploy the workload, add the following pod annotations to your pod specification (only if you want to use the migration sidecar):
| Pod annotation | Description | Value |
|---|---|---|
azure.workload.identity/inject-proxy-sidecar |
Indicates whether to inject the proxy sidecar into the pod. | true or false |
azure.workload.identity/proxy-sidecar-port |
Desired port for the proxy sidecar. | Default value: 8000 |
When you create a pod with these annotations, the Microsoft Entra Workload ID mutating webhook automatically injects the init-container and proxy sidecar to the pod spec. The following YAML shows an example of what the mutating webhook adds to the pod deployment:
apiVersion: v1
kind: Pod
metadata:
name: httpbin-pod
labels:
app: httpbin
azure.workload.identity/use: "true"
annotations:
azure.workload.identity/inject-proxy-sidecar: "true"
spec:
serviceAccountName: workload-identity-sa
initContainers:
- name: init-networking
image: mcr.azk8s.cn/oss/azure/workload-identity/proxy-init:v1.1.0
securityContext:
capabilities:
add:
- NET_ADMIN
drop:
- ALL
privileged: true
runAsUser: 0
env:
- name: PROXY_PORT
value: "8000"
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
- name: proxy
image: mcr.azk8s.cn/oss/azure/workload-identity/proxy:v1.1.0
ports:
- containerPort: 8000
Verify the workload with migration sidecar
Verify the pod is in a running state using the
kubectl describe podcommand. Replace<pod-name>with the name of your pod.kubectl describe pods <pod-name>Verify the pod is passing IMDS transactions using the
kubectl logscommand. Replace<pod-name>with the name of your pod.kubectl logs <pod-name>The following example log output resembles successful communication through the proxy sidecar. Verify the logs show a token is successfully acquired and the
GEToperation is successful.I0926 00:29:29.968723 1 proxy.go:97] proxy "msg"="starting the proxy server" "port"=8080 "userAgent"="azure-workload-identity/proxy/v0.13.0-12-gc8527f3 (linux/amd64) c8527f3/2022-09-26-00:19" I0926 00:29:29.972496 1 proxy.go:173] proxy "msg"="received readyz request" "method"="GET" "uri"="/readyz" I0926 00:29:30.936769 1 proxy.go:107] proxy "msg"="received token request" "method"="GET" "uri"="/metadata/identity/oauth2/token?resource=https://management.core.chinacloudapi.cn/api-version=2018-02-01&client_id=<client_id>" I0926 00:29:31.101998 1 proxy.go:129] proxy "msg"="successfully acquired token" "method"="GET" "uri"="/metadata/identity/oauth2/token?resource=https://management.core.chinacloudapi.cn/api-version=2018-02-01&client_id=<client_id>"
Remove pod-managed identity
After you complete your testing and the application can successfully get a token using the proxy sidecar, you can remove the identity and pod-managed identity mapping from your AKS cluster
Remove the pod-managed identity binding from your pod using the
az aks pod-identity deletecommand. Replace<pod-identity-name>and<pod-identity-namespace>with the name and namespace of your pod identity.az aks pod-identity delete --name <pod-identity-name> --namespace <pod-identity-namespace> --resource-group $RESOURCE_GROUP --cluster-name $CLUSTER_NAME
Related content
For more information about Microsoft Entra Workload ID, see the Overview article.