A default Kubernetes cluster is not secure. Pods can communicate freely, containers run as root, and the API server may be accessible from the internet. Here's what we harden before any production cluster serves traffic.
1. RBAC — least privilege, always
Define the minimum necessary permissions for every service account. Never use cluster-admin for application workloads. Regularly audit RBAC bindings with kubectl auth can-i --list and tools like Rakkess. Remove unused service accounts. Disable the default service account token auto-mounting on pods that don't need API server access.
2. Network Policies — default deny
Install a CNI that supports NetworkPolicy (Calico, Cilium, or Weave). Apply a default-deny-all policy to every namespace, then explicitly allow the traffic that needs to flow. Pods that can't talk to each other can't be used for lateral movement after a compromise.
3. Pod Security Standards
Kubernetes 1.25+ includes Pod Security Admission as a built-in control. Apply the restricted profile to all production namespaces — this enforces: no privileged containers, no root, read-only root filesystem, dropped capabilities, no host network/PID/IPC access. Use baseline for system namespaces that need slightly more permissions.
4. Secret management
Kubernetes Secrets are base64-encoded, not encrypted, by default. Enable etcd encryption at rest. Better: use the External Secrets Operator to sync secrets from AWS Secrets Manager, HashiCorp Vault, or GCP Secret Manager. Secrets never touch etcd in plaintext. Rotate secrets without redeploying applications.
5. Image security
Use an admission controller (Kyverno or OPA Gatekeeper) to enforce image policies: images must come from your private registry, images must have a non-latest tag, images must pass vulnerability scanning before admission. Implement Cosign image signing and verify signatures at admission time.
6. API server access control
The Kubernetes API server should not be publicly accessible. Use a private endpoint for EKS/GKE/AKS. Access it through a bastion or VPN. Enable audit logging to CloudWatch or a SIEM. Alert on: anonymous requests, exec/port-forward to production pods, secret reads, RBAC changes.
7. Runtime security
Deploy Falco for runtime anomaly detection. Falco watches system calls and alerts on suspicious behaviour: a container spawning a shell, reading files it shouldn't, making outbound network connections to unexpected destinations. It catches attacks that admission controls miss because they happen at runtime.
8. Cluster version and node updates
Run nodes within 1–2 versions of the latest Kubernetes release. Enable automatic node group updates in managed Kubernetes services. Old Kubernetes versions have known CVEs that attackers actively exploit. Treat cluster version as a security patch, not just a feature upgrade.
9. Limit container resources
Every container must have resource requests and limits defined. Without limits, a compromised container can consume all node resources (CPU, memory, disk) and affect other workloads — a form of denial of service from within the cluster. Use LimitRange objects to enforce defaults at the namespace level.
10. Regular penetration testing
Run kube-bench against CIS Kubernetes Benchmark. Run Kubescape for compliance checking. Conduct annual penetration tests focused on the cluster. Attack your own cluster with controlled tools like kube-hunter to discover vulnerabilities before attackers do.