Azure AKS Kubernetes identity

AKS Workload Identity Federation: migracja z przestarzałego aad-pod-identity na uwierzytelnianie OIDC

Kompletny przewodnik migracji z przestarzałego aad-pod-identity na AKS Workload Identity Federation z użyciem OIDC issuer, managed identity i federated credentials.

·
Azure oznaczył aad-pod-identity jako przestarzały na rzecz Workload Identity Federation. Nowy system używa tokenów OIDC wstrzykiwanych do podów - koniec z DaemonSet NMI, koniec z CRD AzureIdentity. Oto kompletna ścieżka migracji z poleceniami az CLI i kubectl.

Objawy

Wciąż korzystasz z aad-pod-identity (pody NMI, CRD AzureIdentity i AzureIdentityBinding) i obserwujesz:

# Pody NMI zużywające zasoby na każdym nodzie
kubectl get pods -n kube-system -l app=nmi
# NAME              READY   STATUS    AGE
# nmi-abc12         1/1     Running   45d
# nmi-def34         1/1     Running   45d
# nmi-ghi56         1/1     Running   45d

# Ostrzeżenia o przestarzałości w powiadomieniach o aktualizacji AKS
az aks show --resource-group my-rg --name my-cluster \
  --query "agentPoolProfiles[0].currentOrchestratorVersion"
# Warning: aad-pod-identity add-on is deprecated. Migrate to Workload Identity.

# Sporadyczne błędy pobierania tokenów
kubectl logs -n kube-system -l app=nmi --tail=20 | grep -i error
# E0707 token request failed: timeout waiting for token response from IMDS

Stary system używa podów NMI z dostępem do sieci hosta, by przechwytywać wywołania IMDS. To rozwiązanie jest kruche, dodaje opóźnienia i nie będzie już otrzymywać poprawek bezpieczeństwa.

Przyczyna

Microsoft oznaczył aad-pod-identity jako przestarzały z powodu fundamentalnych problemów architektonicznych:

  • DaemonSet NMI przechwytuje cały ruch IMDS na poziomie noda za pomocą reguł iptables. Tworzy to pojedynczy punkt awarii i dodaje opóźnienie do każdego wywołania Azure SDK z dowolnego poda.
  • Sytuacje wyścigu podczas startu podów. Powiązanie AzureAssignedIdentity jest eventually consistent - pody mogą wystartować zanim ich tożsamość zostanie przypisana, powodując błędy uwierzytelniania.
  • Problemy bezpieczeństwa. NMI wymaga dostępu do sieci hosta i podwyższonych uprawnień. Każdy pod na tym samym nodzie może potencjalnie uzyskać dostęp do tożsamości przypisanych do innych podów.
  • Brak obsługi user-assigned managed identity na dużą skalę. System oparty na CRD nie skaluje się powyżej setek powiązań tożsamości bez degradacji wydajności.

Workload Identity Federation zastępuje to wszystko wstrzykiwanymi tokenami OIDC, które Azure AD weryfikuje bezpośrednio - bez przechwytywania na poziomie noda.

Rozwiązanie

Krok 1: Włącz OIDC issuer i Workload Identity na klastrze AKS

# Włącz OIDC issuer (wymagany dla Workload Identity)
az aks update \
  --resource-group my-rg \
  --name my-cluster \
  --enable-oidc-issuer

# Włącz funkcję Workload Identity
az aks update \
  --resource-group my-rg \
  --name my-cluster \
  --enable-workload-identity

# Pobierz URL OIDC issuer (potrzebny do federated credential)
export AKS_OIDC_ISSUER=$(az aks show \
  --resource-group my-rg \
  --name my-cluster \
  --query "oidcIssuerProfile.issuerUrl" -o tsv)

echo $AKS_OIDC_ISSUER
# https://oidc.prod-aks.azure.com/abc123-def456/

Krok 2: Utwórz user-assigned managed identity

# Utwórz managed identity dla Twojej aplikacji
az identity create \
  --resource-group my-rg \
  --name my-app-identity \
  --location westeurope

# Pobierz client ID
export IDENTITY_CLIENT_ID=$(az identity show \
  --resource-group my-rg \
  --name my-app-identity \
  --query "clientId" -o tsv)

# Przypisz role (przykład: Storage Blob Reader)
export IDENTITY_PRINCIPAL_ID=$(az identity show \
  --resource-group my-rg \
  --name my-app-identity \
  --query "principalId" -o tsv)

az role assignment create \
  --assignee-object-id $IDENTITY_PRINCIPAL_ID \
  --assignee-principal-type ServicePrincipal \
  --role "Storage Blob Data Reader" \
  --scope /subscriptions/YOUR_SUB/resourceGroups/my-rg/providers/Microsoft.Storage/storageAccounts/mystorageaccount

Krok 3: Utwórz federated credential

To łączy Kubernetes service account z Azure managed identity:

# Zdefiniuj namespace i nazwę service account w Kubernetes
export SERVICE_ACCOUNT_NAMESPACE="default"
export SERVICE_ACCOUNT_NAME="my-app-sa"

# Utwórz federated credential
az identity federated-credential create \
  --name my-app-federated-cred \
  --identity-name my-app-identity \
  --resource-group my-rg \
  --issuer $AKS_OIDC_ISSUER \
  --subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME} \
  --audience api://AzureADTokenExchange

Krok 4: Utwórz adnotowany Kubernetes service account

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: default
  annotations:
    azure.workload.identity/client-id: "${IDENTITY_CLIENT_ID}"
  labels:
    azure.workload.identity/use: "true"
EOF

Krok 5: Zaktualizuj spec poda, by używał nowego service account

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
        azure.workload.identity/use: "true"  # Wymagana etykieta
    spec:
      serviceAccountName: my-app-sa  # Wskazuje na adnotowany SA
      containers:
        - name: my-app
          image: myregistry.azurecr.io/my-app:latest
          env:
            # Te zmienne są automatycznie wstrzykiwane przez mutating webhook,
            # ale możesz się do nich odwoływać jawnie jeśli potrzebujesz:
            - name: AZURE_CLIENT_ID
              value: ""  # Wstrzykiwane automatycznie
            - name: AZURE_TENANT_ID
              value: ""  # Wstrzykiwane automatycznie
            - name: AZURE_FEDERATED_TOKEN_FILE
              value: ""  # Wstrzykiwane automatycznie

Mutating webhook Workload Identity automatycznie wstrzykuje zmienne środowiskowe i wolumen z tokenem. Nie trzeba zmieniać kodu jeśli używasz Azure SDK (DefaultAzureCredential automatycznie wykrywa token federacyjny).

Krok 6: Usuń stare zasoby aad-pod-identity

Gdy nowa tożsamość działa poprawnie:

# Usuń CRD AzureIdentity i AzureIdentityBinding
kubectl delete azureidentity my-app-identity -n default
kubectl delete azureidentitybinding my-app-identity-binding -n default

# Jeśli używasz managed add-on, wyłącz go
az aks update \
  --resource-group my-rg \
  --name my-cluster \
  --disable-pod-identity

# Jeśli używasz aad-pod-identity zainstalowanego przez Helm
helm uninstall aad-pod-identity -n kube-system

# Zweryfikuj, że pody NMI zniknęły
kubectl get pods -n kube-system -l app=nmi
# Oczekiwane: No resources found

Weryfikacja

Po migracji zweryfikuj, że workload może się uwierzytelnić do zasobów Azure:

# 1. Zweryfikuj, że service account ma prawidłowe adnotacje
kubectl get serviceaccount my-app-sa -o yaml | grep -A2 annotations
# Oczekiwane: azure.workload.identity/client-id: "<twoje-client-id>"

# 2. Zweryfikuj, że mutating webhook wstrzykuje zmienne środowiskowe
kubectl describe pod -l app=my-app | grep -A3 "AZURE_"
# Oczekiwane:
# AZURE_CLIENT_ID:              <client-id>
# AZURE_TENANT_ID:              <tenant-id>
# AZURE_FEDERATED_TOKEN_FILE:   /var/run/secrets/azure/tokens/azure-identity-token

# 3. Zweryfikuj, że wolumen z tokenem istnieje
kubectl exec -it deploy/my-app -- ls /var/run/secrets/azure/tokens/
# Oczekiwane: azure-identity-token

# 4. Przetestuj dostęp do zasobów Azure z poda
kubectl exec -it deploy/my-app -- az storage blob list \
  --account-name mystorageaccount \
  --container-name mycontainer \
  --auth-mode login
# Oczekiwane: lista obiektów blob (bez błędów uwierzytelniania)

# 5. Zweryfikuj, że nie pozostały żadne pody NMI
kubectl get pods -A -l app=nmi
# Oczekiwane: No resources found

# 6. Sprawdź czy webhook workload identity jest zdrowy
kubectl get pods -n kube-system -l azure-workload-identity.io/system=true
# Oczekiwane: pody webhook w stanie Running

Utrzymywanie przestarzałej infrastruktury tożsamości to odpowiedzialność za bezpieczeństwo. Stary DaemonSet NMI wymaga dostępu do sieci hosta i podwyższonych uprawnień na każdym nodzie. Workload Identity Federation całkowicie eliminuje tę powierzchnię ataku, jednocześnie zapewniając szybsze i bardziej niezawodne pobieranie tokenów. Każdy tydzień opóźnienia w migracji to tydzień, w którym klaster działa ze znanymi podatnościami w komponencie, który nigdy więcej nie zostanie załatany.

 

Jerzy Kopaczewski

Migracja tożsamości AKS na dużą skalę?

Umów bezpłatną 30-minutową rozmowę. Przeprowadzamy pełną migrację z aad-pod-identity na Workload Identity Federation na wszystkich Twoich klastrach i workloadach.