Deploy Django on Azure Kubernetes Service (AKS)

Deploy Django on Azure Kubernetes Service: push images to Azure Container Registry, connect to Azure Database for PostgreSQL with workload identity and Key Vault secrets, expose it through Application Gateway or an ingress, and run migrations as Jobs.

Problem statement

Your organization runs on Azure and wants Django on Kubernetes rather than App Service or Container Apps, usually because several services share a cluster, or because the platform team standardizes on AKS. AKS manages the control plane, but you still decide how images are pulled, how pods reach the database and secrets without static passwords, how traffic and TLS get in, and how migrations run during releases.

Django on AKSBuild imagepush to ACRPods on AKSworkload identityIngressApp Gateway, routingAzure dataPostgres, Blob, VaultAKS runs pods; Azure services hold data and secrets, reached through managed identity.
  1. Create an AKS cluster with OIDC issuer and workload identity enabled, and attach Azure Container Registry: az aks create ... --attach-acr acmeregistry --enable-oidc-issuer --enable-workload-identity.
  2. Push the Django image to ACR with a commit SHA tag.
  3. Use Azure Database for PostgreSQL Flexible Server with private networking; store credentials in Key Vault.
  4. Mount Key Vault secrets with the Secrets Store CSI driver, authenticated through workload identity.
  5. Expose the app with Application Gateway for Containers or the AKS application routing add-on, with cert-manager or Key Vault certificates for HTTPS.

Step-by-step solution

1. Create the cluster

az group create -n acme-prod -l westeurope
az acr create -g acme-prod -n acmeregistry --sku Standard
az aks create -g acme-prod -n acme-aks \
  --node-count 2 --node-vm-size Standard_D2s_v5 \
  --enable-cluster-autoscaler --min-count 2 --max-count 5 \
  --attach-acr acmeregistry \
  --enable-oidc-issuer --enable-workload-identity \
  --enable-addons azure-keyvault-secrets-provider \
  --network-plugin azure
az aks get-credentials -g acme-prod -n acme-aks

--attach-acr grants the cluster's kubelet identity pull access to the registry, so no image pull secret is needed.

2. Build and push

az acr login -n acmeregistry
docker buildx build --platform linux/amd64 -t acmeregistry.azurecr.io/web:$SHA --push .

Or build in Azure with az acr build -r acmeregistry -t web:$SHA ., which avoids local architecture issues.

identity per dependencyIdentityNo static secret?Container Registrykubelet identityyesKey Vaultworkload identityyesBlob Storageworkload identityyesPostgreSQLpassword or Entra tokenwith Entra authWorkload identity removes most long-lived credentials from the clusterdjango-deployment.com
Federated credentials tie a Kubernetes service account to an Azure managed identity.

3. Set up workload identity and Key Vault

Create a user-assigned managed identity, grant it access to Key Vault secrets, and federate it with a Kubernetes service account:

az identity create -g acme-prod -n django-web
CLIENT_ID=$(az identity show -g acme-prod -n django-web --query clientId -o tsv)
ISSUER=$(az aks show -g acme-prod -n acme-aks --query oidcIssuerProfile.issuerUrl -o tsv)
az identity federated-credential create -g acme-prod --identity-name django-web \
  --name aks-prod-web --issuer "$ISSUER" --subject system:serviceaccount:prod:web
apiVersion: v1
kind: ServiceAccount
metadata:
  name: web
  namespace: prod
  annotations:
    azure.workload.identity/client-id: "<CLIENT_ID>"

A SecretProviderClass then maps Key Vault secrets into the pod as files and, optionally, a synced Kubernetes Secret for environment variables. See Use Azure Key Vault With Django.

4. Connect to PostgreSQL

Create Azure Database for PostgreSQL Flexible Server with private access in a subnet peered with the AKS virtual network. Require TLS:

DATABASES = {"default": dj_database_url.config(conn_max_age=60, ssl_require=True)}

With Microsoft Entra authentication enabled, pods can request a short-lived access token through workload identity and use it as the password, removing database passwords entirely. Enable the server's built-in PgBouncer when many pods connect.

5. Deploy, migrate, and expose

Apply a Deployment that uses serviceAccountName: web, the label azure.workload.identity/use: "true", and the image from ACR. Run migrations as a Job with the same service account before each rollout. For ingress, use Application Gateway for Containers or the AKS application routing add-on, with cert-manager or Key Vault certificates for HTTPS. Store media in Blob Storage through django-storages[azure].

before switching trafficImage in ACR by commit SHAimmutable tagSecrets from Key VaultCSI driver, workload identityMigrate Job completedsame image and identityReadiness probe passesHost header setIngress TLS validcert-manager or Key VaultEvery item can be checked from CI before the rollout continuesdjango-deployment.com
A failed Job stops the pipeline before any pod runs new code.

Explanation

AKS integrates Kubernetes with Azure identity. Instead of storing connection strings and keys in Kubernetes Secrets, pods present a service account token that Azure exchanges for a managed identity token through the OIDC federation. That identity can read Key Vault, write Blob Storage, and, with Entra authentication, log in to PostgreSQL. Django itself is unchanged; settings read values from environment variables or mounted files as usual.

Edge cases / notes

  • Pod identity (legacy). AAD Pod Identity is deprecated; use workload identity for new clusters.
  • Egress. Private clusters need outbound rules or NAT for package mirrors, Sentry, and email APIs.
  • Container Apps. If you only run one Django app with workers, Azure Container Apps gives you most of this with far less to manage.

Next steps

FAQ

Do I need image pull secrets for ACR on AKS?

No, if you attach the registry with --attach-acr. The kubelet identity gets pull permission.

What is workload identity?

A way for Kubernetes service accounts to obtain Azure tokens through OIDC federation, so pods can access Azure services without stored secrets.

Should I use AKS or Container Apps for Django?

Container Apps for a single app with little platform work; AKS when you need full Kubernetes features or share a cluster with other services.

How do I run migrations on AKS?

As a Kubernetes Job using the new image and the same service account, completed before updating the Deployment.

Keep going