Django Kubernetes Security Checklist

A security checklist for Django on Kubernetes: non-root containers with read-only filesystems, Pod Security Standards, minimal RBAC and service account tokens, secrets from a manager, NetworkPolicies, image scanning and signing, patched nodes, and audit logging.

Problem statement

Running Django on Kubernetes adds a layer of infrastructure with its own attack surface: pods running as root, service account tokens that can talk to the API server, secrets readable by anyone with namespace access, flat networks, and images nobody scanned. A vulnerability in a Python dependency can turn into cluster-wide compromise if these defaults are left in place. This checklist hardens the Kubernetes side of a Django deployment.

Securing Django on K8sWorkloadnon-root, read-onlyIdentityRBAC, no tokenSecrets + networkmanager, policiesSupply chainscan, sign, patchLimit what a compromised Django pod can do and reach.
  1. Run containers as non-root with a read-only root filesystem, no privilege escalation, and dropped capabilities.
  2. Enforce the restricted Pod Security Standard on application namespaces.
  3. Disable automatic service account token mounting for Django pods unless they call the Kubernetes API.
  4. Load secrets from a secrets manager (External Secrets, CSI driver) and enable encryption at rest for Kubernetes Secrets.
  5. Apply NetworkPolicies, scan and sign images, keep nodes and the control plane patched, and enable audit logs.

Checklist

Pod and container hardening

  • securityContext: runAsNonRoot: true, allowPrivilegeEscalation: false, readOnlyRootFilesystem: true, capabilities.drop: ["ALL"], seccompProfile.type: RuntimeDefault.
  • Writable paths (/tmp) mounted as emptyDir; logs to stdout; media in object storage.
  • Namespaces labeled pod-security.kubernetes.io/enforce: restricted.
  • Resource requests and limits set so a compromised pod cannot starve the node.
securityContext:
  runAsNonRoot: true
  runAsUser: 10001
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities: { drop: ["ALL"] }
  seccompProfile: { type: RuntimeDefault }

Identity and access

  • automountServiceAccountToken: false on Django and Celery pods that do not use the Kubernetes API.
  • Dedicated service accounts per workload; RBAC roles minimal and namespaced; no cluster-admin for CI.
  • Human access via SSO with short-lived credentials; kubectl exec into production restricted and audited.
  • Cloud workload identity (IRSA, GKE Workload Identity, Azure workload identity) instead of static cloud keys.
layer and controlControlLimits damage fromContainernon-root, read-only FScode executionPod identityno token, minimal RBACAPI server abuseSecretsmanager + encryptionsecret theftNetworkNetworkPolicieslateral movementSupply chainscan, sign, pinmalicious imagesClusterpatching, audit logsknown CVEsEach layer assumes the one before it may faildjango-deployment.com
Defense in depth means a single Python CVE stays a contained incident.

Secrets

  • Secrets synced from a secrets manager (External Secrets Operator, Secrets Store CSI driver), not committed to git.
  • etcd encryption at rest for Secrets enabled (default on most managed clusters; verify).
  • RBAC prevents broad get/list secrets permissions; reading secrets is limited to workloads and admins.
  • Rotation process tested for SECRET_KEY, database credentials, and API keys.

Network

  • Default-deny NetworkPolicies with explicit allows for ingress controller, database, Redis, DNS, and required APIs.
  • Database and cache not exposed outside the cluster or VPC.
  • Ingress with TLS, modern ciphers, and WAF or rate limiting in front of public endpoints.

Supply chain and cluster

  • Images built in CI from pinned base images, scanned (Trivy, Grype), and signed (Cosign); admission policy verifies signatures.
  • Images referenced by digest or immutable tags; no latest.
  • Control plane and node pools on supported, patched versions; automatic node upgrades in maintenance windows.
  • Kubernetes audit logs enabled and retained; alerts on suspicious API activity (exec into pods, secret reads, RBAC changes).
order of changes1Non-root image, securityContexttest in staging2Disable token automountper workload3Secrets from a managerremove from git4NetworkPoliciesallow rules, then deny5Enforce PSS restrictedand image signingChange one layer at a time and verify the app still worksdjango-deployment.com
Warn mode for Pod Security Standards shows violations before enforcing.

Explanation

Kubernetes security works in layers: the container's privileges, the pod's identity, the secrets it can read, the network it can reach, the images it runs, and the cluster underneath. A Django app compromised through a dependency vulnerability gains whatever its pod can do. Running non-root with a read-only filesystem limits local damage; removing API tokens and minimizing RBAC stops escalation into the cluster; NetworkPolicies limit lateral movement; secrets management and supply chain controls protect credentials and code integrity.

Edge cases / notes

  • Read-only filesystems. Python writes .pyc files and Django may write temp files; set PYTHONDONTWRITEBYTECODE=1 and mount /tmp.
  • Init containers. Migration Jobs and init containers need the same hardening as the main pods.
  • Managed add-ons. Cloud provider agents may need privileges; isolate them in their own namespaces.

Next steps

FAQ

Should Django pods run as root?

No. Run as a non-root user with no privilege escalation and dropped capabilities.

Does a Django pod need a service account token?

Usually not. Disable automounting unless the app calls the Kubernetes API.

Are Kubernetes Secrets secure?

They are base64-encoded, not encrypted, unless etcd encryption is enabled. Source them from a manager and restrict access with RBAC.

How do I stop unsigned images from running?

Sign images in CI with Cosign and enforce verification with an admission controller.

Learning path · step 15 of 16

Django on Kubernetes

Keep going