Migrate from Pod Identity to Workload Identity on AKS

I’ve been using AAD Pod Identity and managed identity for some of my workloads. Since AAD Workload Identity now supports user assigned managed identity, it’s time to migrate my workloads from Pod Identity to Workload Identity. So here is how I did it.

Enable Workload Identity on an existing AKS cluster

To use Workload Identity, the AKS version needs to be 1.24 or higher. The Workload Identity is still a preview feature. It needs to be enabled on the cluster. To do so, the latest version of aks-preview cli extension is needed. We can either add or update it with az extension add --name aks-preview or az extension update --name aks-preview.

We need to register the EnableWorkloadIdentityPreview and EnableOIDCIssuerPreview feature flags first.

az feature register --namespace "Microsoft.ContainerService" --name "EnableWorkloadIdentityPreview"
az feature register --namespace "Microsoft.ContainerService" --name "EnableOIDCIssuerPreview"

It will take some time for these feature flags to be registered. The following command can be used to monitor the status.

az feature list -o table --query "[?contains(name, 'Microsoft.ContainerService/EnableOIDCIssuerPreview') || contains(name, 'Microsoft.ContainerService/EnableWorkloadIdentityPreview')].{Name:name,State:properties.state}"

When the feature flags are registered, refresh the registration of the resource provider.

az provider register --namespace Microsoft.ContainerService

Now we can enable these two features on the cluster.

az aks update -g <resource-group> -n <cluster-name> --enable-workload-identity --enable-oidc-issuer

When the features are registered successfully, we need to get the URL of the OIDC issuer from the cluster. We can save it in an environment variable.

export AKS_OIDC_ISSUER="$(az aks show -n myAKSCluster -g myResourceGroup --query "oidcIssuerProfile.issuerUrl" -otsv)"

Create Kubernetes service account

We can use the following yaml to create a Kubernetes service account.

apiVersion: v1
kind: ServiceAccount
    azure.workload.identity/client-id: <USER_ASSIGNED_CLIENT_ID>
    azure.workload.identity/use: "true"

The USER_ASSIGNED_CLIENT_ID is the client id of the user assigned managed identity that we will use. We can reuse the one that was used with the Pod Identity. But since we need to enable the federated identity credential on this managed identity later, and some regions don’t support federated identity credential on user assigned managed identity yet, if our managed identity happens to be in those region, we will have to create a new one in the supported regions.

Enable federated identity credential on the managed identity

We can use the following command.

az identity federated-credential create --name <fid-name> --identity-name <user-assigned-mi-name> --resource-group <rg-name> --issuer ${AKS_OIDC_ISSUER} --subject system:serviceaccount:<service-account-namespace>:<service-account-name>

Update our workloads to use Workload Identity

To use the Workload Identity with our workloads, it is very simple. We just need to add serviceAccountName: <service-account-name> in our pod spec. If the code of the workloads has already been leveraging the Azure Identity SDK, for example, for .NET code if it has been using either DefaultAzureCredential or ManagedIdentityCredential to get the credential, we almost don’t need to make any change to the code. It should work straightly with the workload identity. However, if the code is using other ways to get the credential, it will have to be updated to work with the workload identity. There are some examples in the workload identity repo which shows how it works for different languages.

AKS team provide us a sidecar image that can be used as a temporary migration workaround. But updating the code is the long term solution.

Remove the Pod Identity

When we migrate the workloads to Workload Identity, we can remove the Pod Identity and the CDRs like AzureIdentity and AzureIdentityBinding etc. Depending on how Pod Identity is deployed on the cluster, there are different ways to remove it. For example, on my cluster I installed it with Helm. So I can simply uninstall it with helm uninstall.

That’s all about the migration.