Text size
Tried & Tested7 min read

My Kubernetes security checklist

RBAC, network policies, runtime security. The settings I check on every cluster.

My Kubernetes security checklist
AI-generated editorial illustration

Kubernetes isn't insecure, but it isn't secure by default either. A fresh cluster lets pods run as root, talk to every other pod, and mount the host's file system if you ask. Most clusters I review have at least a few of these doors open.

This is the order I check things on every cluster, from most important to less urgent.

1. Who can do what (RBAC)

  • No shared admin kubeconfigs. People log in with SSO and get roles based on groups.
  • Nobody uses cluster-admin day to day. Keep it for break-glass access, logged and alerted.
  • Least privilege for service accounts. Most applications don't need to talk to the Kubernetes API at all. Set automountServiceAccountToken: false for those.
  • Watch for dangerous permissions: access to secrets across namespaces, pods/exec, creating pods in kube-system, escalate and bind verbs, and wildcards (*).
  • Review regularly. Tools like kubectl auth can-i --list, rbac-tool or KubiScan help find over-privileged accounts.

2. Locking down pods

Kubernetes has a built-in mechanism for this: Pod Security Admission, with three levels: privileged, baseline and restricted. Enable it per namespace with labels:

apiVersion: v1
kind: Namespace
metadata:
  name: shop
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted

The restricted level requires pods to follow best practices. A compliant pod's security context looks like:

securityContext:
  runAsNonRoot: true
  seccompProfile:
    type: RuntimeDefault
containers:
- name: app
  securityContext:
    allowPrivilegeEscalation: false
    readOnlyRootFilesystem: true
    capabilities:
      drop: ["ALL"]

Aim for restricted on all application namespaces. Keep privileged only for system components that genuinely need it (CNI, storage drivers, monitoring agents), in their own namespaces.

A container running as root with every capability is one vulnerability away from owning the node.

3. Network policies

By default, every pod can talk to every other pod in the cluster. If an attacker gets into one, they can reach everything.

Start with a default deny in each namespace, then allow what's needed:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: shop
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]

Then add policies allowing, for example, the gateway to reach the API, the API to reach its database, and everything to reach DNS. Remember: network policies only work if your CNI supports them (Cilium, Calico and most modern CNIs do).

Restricting egress (outgoing traffic) is just as valuable: a compromised pod that can't reach the internet can't download tools or send data out easily.

4. Secrets

  • Encrypt secrets at rest in etcd, using KMS on managed clusters.
  • Don't store secrets in Git in plain YAML. Use External Secrets, Sealed Secrets or SOPS.
  • Limit get and list on secrets in RBAC. Listing secrets in a namespace reveals all of them.
  • Prefer workload identity over static cloud credentials in secrets.

5. Image policy

  • Only allow images from trusted registries.
  • No latest tags. Pin versions, ideally digests.
  • Require signed images (Cosign) for production.
  • Scan images in CI and continuously in the registry.

These are enforced with an admission policy engine like Kyverno or OPA Gatekeeper, or with Kubernetes' built-in ValidatingAdmissionPolicy for simpler rules.

6. Watching what runs (runtime security)

Preventive controls can be bypassed. Runtime security detects suspicious behaviour as it happens:

  • Falco (CNCF) watches system calls and alerts on things like a shell spawned in a container, unexpected outbound connections, or writes to sensitive directories.
  • Tetragon (from the Cilium project) uses eBPF for observability and can also enforce policies, like killing a process that does something forbidden.

Send their alerts to the same place as your other alerts, and tune them, or they'll become noise.

7. The control plane and nodes

  • API server not publicly exposed, or at least restricted to known IP ranges.
  • Audit logging enabled, and logs shipped somewhere central.
  • Keep Kubernetes up to date. Security fixes only land in supported versions.
  • Hardened node images, minimal OS (like Bottlerocket, Talos or Container-Optimized OS), regularly replaced.
  • Block access to cloud metadata endpoints from pods that don't need it, or enforce IMDSv2 on AWS.

8. Benchmarks

  • CIS Kubernetes Benchmark: a detailed set of recommendations. kube-bench checks a cluster against it.
  • Kubescape and Trivy (trivy k8s) scan clusters for misconfigurations and map them to frameworks like NSA/CISA hardening guidance.

Run them regularly. Don't aim for 100%, aim for understanding every finding.

So, where do I start?

If you can only do three things: switch people to SSO with least-privilege RBAC, enforce Pod Security restricted on application namespaces, and add default-deny network policies. That closes the biggest security gaps in most clusters.

My take: Kubernetes gives you all the locks you need. They just come unlocked in the box.

— Desly