Kubernetes Security Hardening: A Production Checklist

Kicked TeamFebruary 18, 20264 min read

We've audited dozens of Kubernetes clusters. The pattern is almost always the same: a team spins up a managed cluster (or worse, kubeadm with defaults), deploys their apps, and calls it production. Six months later, they call us after an incident.

Default Kubernetes is not secure. It's designed for flexibility, not safety. Here's the checklist we follow for every cluster we manage.

1. RBAC — Stop Using cluster-admin for Everything

The single most common mistake we see: every service account, CI pipeline, and developer bound to cluster-admin.

# Bad: giving your CI pipeline god mode
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: ci-pipeline
subjects:
  - kind: ServiceAccount
    name: ci-deployer
    namespace: ci
roleRef:
  kind: ClusterRole
  name: cluster-admin # Don't do this

Instead, create scoped roles per namespace. Your CI pipeline only needs permission to update Deployments and ConfigMaps in its target namespaces — not to delete PersistentVolumes cluster-wide.

# Better: namespace-scoped, least-privilege
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ci-deployer
  namespace: production
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "patch", "update"]
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get", "list", "create", "update"]

2. Network Policies — Default Deny

By default, every pod can talk to every other pod. That means a compromised frontend can reach your database directly.

# Default deny all ingress in a namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress

Then explicitly allow only the traffic you need. We use Cilium for network policies because it supports L7 filtering (HTTP method, path) in addition to L3/L4.

3. Pod Security Standards

Kubernetes deprecated PodSecurityPolicy in v1.25 and replaced it with Pod Security Standards (PSS) enforced via the built-in admission controller.

At minimum, enforce the restricted profile on production namespaces:

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

This prevents containers from running as root, using host networking, escalating privileges, or mounting dangerous volume types.

4. Image Security

  • Use digest pinning — Tags are mutable. nginx:latest today is not nginx:latest tomorrow. Pin to nginx@sha256:abc123...
  • Scan images in CI — We run Trivy in every pipeline. Block deployments with critical CVEs
  • Private registry — Don't pull from Docker Hub in production. Mirror what you need into your own registry
  • Admission control — Use a tool like Kyverno or OPA Gatekeeper to reject images from untrusted registries

5. Secrets Management

Kubernetes Secrets are base64-encoded, not encrypted. Anyone with get secrets RBAC can read them.

Our approach:

  • Encrypt etcd at rest — Configure EncryptionConfiguration with aescbc or secretbox
  • External secrets — Use the External Secrets Operator to sync from HashiCorp Vault, AWS Secrets Manager, or similar
  • Never commit secrets — Sealed Secrets or SOPS for GitOps workflows

6. Runtime Security

Everything above is preventive. Runtime security catches what slipped through:

  • Falco for anomaly detection — alerts on unexpected process execution, file access, network connections
  • Read-only root filesystem — Prevents malware from writing to the container filesystem
  • Seccomp profiles — Restrict syscalls to only what the application needs

7. Audit Logging

Enable the Kubernetes audit log. You need to know who did what, when:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets", "configmaps"]
  - level: RequestResponse
    resources:
      - group: "rbac.authorization.k8s.io"
        resources: ["clusterroles", "clusterrolebindings"]

Ship audit logs to your SIEM. We use Loki + Grafana for cost-effective log aggregation.

Our Hardening Stack

Layer Tool Purpose
Network Cilium Network policies + L7 filtering
Admission Kyverno Policy enforcement
Scanning Trivy Image vulnerability scanning
Secrets External Secrets + Vault Secrets management
Runtime Falco Anomaly detection
Audit Loki + Grafana Log aggregation

Start Today

You don't need to implement all of this at once. Start with RBAC and network policies — they'll eliminate the most common attack vectors. Then layer on the rest.

Need help auditing your cluster? We've hardened clusters running everything from fintech workloads to gaming backends. Get in touch and we'll start with a security review.