Secure Azure Access with AKS Pod Identity
Secure Azure Access with AKS Pod Identity
Managing secrets and credentials in Kubernetes can be challenging. AKS Pod Identity allows your pods to use Azure Active Directory identities to access Azure resources securely, without embedding credentials in your code or configuration.
Understanding Pod Identity
Pod Identity assigns Azure managed identities to pods, enabling:
- Secretless authentication to Azure services
- Fine-grained access control per workload
- Automatic credential rotation
- Audit trail in Azure AD
Installing AAD Pod Identity
Using Helm
# Add the AAD Pod Identity Helm repo
helm repo add aad-pod-identity https://raw.githubusercontent.com/Azure/aad-pod-identity/master/charts
helm repo update
# Install in managed mode (recommended for managed AKS)
helm install aad-pod-identity aad-pod-identity/aad-pod-identity \
--namespace kube-system \
--set operationMode=managed \
--set forceNamespaced=true
Verify Installation
kubectl get pods -n kube-system | grep aad-pod-identity
# Should see:
# aad-pod-identity-mic-xxx Running
# aad-pod-identity-nmi-xxx Running
Creating an Azure Identity
# Create a user-assigned managed identity
az identity create \
--resource-group myResourceGroup \
--name myPodIdentity
# Get the identity resource ID and client ID
IDENTITY_RESOURCE_ID=$(az identity show \
--resource-group myResourceGroup \
--name myPodIdentity \
--query id -o tsv)
IDENTITY_CLIENT_ID=$(az identity show \
--resource-group myResourceGroup \
--name myPodIdentity \
--query clientId -o tsv)
Assigning Permissions
Grant the identity access to Azure resources:
# Example: Grant access to Key Vault
az keyvault set-policy \
--name myKeyVault \
--object-id $(az identity show --resource-group myResourceGroup --name myPodIdentity --query principalId -o tsv) \
--secret-permissions get list
# Example: Grant access to Storage Account
az role assignment create \
--role "Storage Blob Data Reader" \
--assignee $(az identity show --resource-group myResourceGroup --name myPodIdentity --query principalId -o tsv) \
--scope /subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.Storage/storageAccounts/mystorageaccount
Creating AzureIdentity and AzureIdentityBinding
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: my-pod-identity
namespace: default
spec:
type: 0 # 0 = User Assigned, 1 = Service Principal
resourceID: /subscriptions/{subscription-id}/resourceGroups/myResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/myPodIdentity
clientID: {client-id-guid}
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentityBinding
metadata:
name: my-pod-identity-binding
namespace: default
spec:
azureIdentity: my-pod-identity
selector: my-app # Pods with this label will use this identity
Using the Identity in Pods
Label your pods with the identity selector:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
aadpodidbinding: my-app # This label binds to the AzureIdentityBinding
spec:
containers:
- name: app
image: myregistry.azurecr.io/my-app:v1
env:
- name: AZURE_CLIENT_ID
value: "{client-id-guid}"
Example: Accessing Key Vault
from azure.identity import ManagedIdentityCredential
from azure.keyvault.secrets import SecretClient
# No credentials needed - uses pod identity
credential = ManagedIdentityCredential()
client = SecretClient(
vault_url="https://mykeyvault.vault.azure.net",
credential=credential
)
secret = client.get_secret("my-secret")
print(f"Secret value: {secret.value}")
Example: Accessing Azure Storage
from azure.identity import ManagedIdentityCredential
from azure.storage.blob import BlobServiceClient
credential = ManagedIdentityCredential()
blob_service = BlobServiceClient(
account_url="https://mystorageaccount.blob.core.windows.net",
credential=credential
)
container_client = blob_service.get_container_client("mycontainer")
blobs = container_client.list_blobs()
for blob in blobs:
print(blob.name)
Example: Accessing Azure SQL
using Azure.Identity;
using Microsoft.Data.SqlClient;
var credential = new ManagedIdentityCredential();
var token = await credential.GetTokenAsync(
new TokenRequestContext(new[] { "https://database.windows.net/.default" })
);
using var connection = new SqlConnection(
"Server=myserver.database.windows.net;Database=mydb;"
);
connection.AccessToken = token.Token;
await connection.OpenAsync();
// Execute queries...
Namespace Isolation
For multi-tenant clusters, use namespace-scoped identities:
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentity
metadata:
name: team-a-identity
namespace: team-a
spec:
type: 0
resourceID: /subscriptions/.../userAssignedIdentities/teamAIdentity
clientID: {team-a-client-id}
---
apiVersion: aadpodidentity.k8s.io/v1
kind: AzureIdentityBinding
metadata:
name: team-a-binding
namespace: team-a
spec:
azureIdentity: team-a-identity
selector: team-a-workload
Troubleshooting
Check MIC Logs
kubectl logs -n kube-system -l app=mic --tail=100
Check NMI Logs
kubectl logs -n kube-system -l app=nmi --tail=100
Verify Identity Assignment
# Check if identity is assigned to the node
az vmss identity show \
--resource-group MC_myResourceGroup_myAKSCluster_eastus \
--name aks-nodepool1-12345678-vmss
Security Best Practices
- Principle of least privilege - Grant minimal permissions required
- Use namespace isolation - Scope identities to namespaces
- Audit identity usage - Monitor Azure AD sign-in logs
- Rotate identities periodically - Update identity bindings regularly
- Use Azure Policy - Enforce identity requirements
Conclusion
AKS Pod Identity provides a secure, credential-free way to access Azure resources from your Kubernetes workloads. By leveraging managed identities, you eliminate the need to manage secrets while maintaining strong security controls.
Tomorrow, we’ll explore the newer Workload Identity approach, which is becoming the recommended method for Azure identity in Kubernetes.