Ideas Engineered for Tomorrow
We Engineer Services & Solutions for Your Business Needs
Home About
Products
Services
Hire
Industries
Consulting
Partners
Articles Careers Contact
Cybersecurity

Kubernetes Security Best Practices for Production

Kubernetes is secure by default — said nobody who's actually run it in production. Here's the checklist that matters, organized by attack surface.

October 27, 2025 14 min read Cloud & DevOps

A default Kubernetes installation is wide open. Pods run as root. There are no network policies (everything can talk to everything). Secrets are base64-encoded (not encrypted). The API server accepts any authenticated request. If you deployed K8s without hardening it, you have a cluster that works — and is one misconfiguration away from a breach. This guide covers the security controls that matter most, organized from highest impact to lowest.

The Kubernetes Attack Surface

Attack Surface Risk Common Exploit Mitigation
API Server Critical — full cluster control Exposed API server with weak/no auth; leaked kubeconfig RBAC, network restrictions, audit logging
Container images High — supply chain attack vector Vulnerable base image, malicious package in image layer Image scanning, signed images, minimal base images
Pod-to-pod network High — lateral movement Compromised pod scans internal services, accesses databases Network policies (deny by default)
Pod runtime High — container escape Privileged container, mounted host filesystem, kernel exploits Pod Security Standards, seccomp, AppArmor
Secrets Medium-High — credential theft Secrets readable in etcd, exposed via env vars in logs External secret managers, encryption at rest
etcd Critical — stores all cluster state Unencrypted etcd, network-accessible etcd Encryption at rest, mTLS, restricted network access

RBAC: The Foundation of K8s Security

Role-Based Access Control determines who can do what in your cluster. The default in most managed K8s (EKS, GKE, AKS): too permissive. The goal: least privilege — every user and service account gets only the permissions they need.

Key Principles

  1. No cluster-admin for humans. Nobody should have cluster-admin for daily work. Create role-specific bindings: developers get read access to their namespace, ops gets broader access with audit logging.
  2. Namespace isolation. Each team/application gets its own namespace. RBAC roles are scoped to namespaces, not cluster-wide.
  3. Service account per workload. Don't use the default service account. Create dedicated service accounts with minimal permissions for each deployment.
# Example: Restricted developer role for a specific namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: team-frontend
  name: developer
rules:
- apiGroups: [""]
  resources: ["pods", "services", "configmaps"]
  verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "update"]  # Can update deployments but not create/delete
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["list"]  # Can list secret names but NOT read values
---
# Bind to a specific user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: team-frontend
  name: developer-binding
subjects:
- kind: User
  name: "priya@company.com"
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Network Policies: Zero Trust Networking

By default, every pod can communicate with every other pod in the cluster. This means a compromised frontend pod can reach your database directly. Network policies fix this.

# Default deny all ingress and egress for a namespace
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}  # Applies to ALL pods in namespace
  policyTypes:
  - Ingress
  - Egress

---
# Allow frontend → backend on port 8080 only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - port: 8080

---
# Allow backend → database on port 5432 only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-backend-to-db
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: postgres
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: backend
    ports:
    - port: 5432

Important: Network policies require a CNI that supports them. Calico, Cilium, and Weave support network policies. The default kubenet CNI in some managed clusters does not. Verify before assuming your policies are enforced.

Pod Security Standards

Kubernetes 1.25+ replaced PodSecurityPolicies with Pod Security Standards (PSS) — three profiles that control what pods can do:

Profile What It Allows Use For
Privileged Everything — no restrictions System-level pods only (CNI, monitoring agents)
Baseline Prevents known privilege escalations. Blocks hostNetwork, hostPID, privileged containers. General workloads — good starting point
Restricted Strict hardening. Non-root, read-only root filesystem, dropped capabilities. Security-sensitive workloads — target for all new deployments
# Apply restricted profile to a namespace
kubectl label namespace production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/audit=restricted

Target state: all application namespaces at restricted, system namespaces at baseline, only the bare minimum at privileged.

Secrets Management

Kubernetes secrets are base64-encoded, not encrypted. Anyone with get secrets permission can read them. And they're stored in etcd in plaintext by default.

Minimum Requirements

  1. Enable encryption at rest for etcd. This is a cluster-level configuration — every managed K8s provider supports it, but it's not always enabled by default.
  2. Use external secret managers. Store secrets in HashiCorp Vault, AWS Secrets Manager, or GCP Secret Manager. Sync them to K8s using the External Secrets Operator or CSI Secret Store Driver.
  3. Never put secrets in environment variables. They appear in pod specs, can leak into logs, and are visible to anyone with pod describe access. Use mounted volumes instead.
  4. Rotate secrets automatically. External secret managers support automatic rotation. If you're using native K8s secrets, build a rotation mechanism or accept the risk.

Image Security and Supply Chain

  • Use minimal base images. Alpine or distroless instead of Ubuntu. Fewer packages = fewer vulnerabilities. A typical Ubuntu base image has 100+ known CVEs; distroless has near zero.
  • Scan images in CI/CD. Trivy (free), Snyk Container, or Aqua scan images for known CVEs before they're pushed to the registry. Block deployments with critical/high CVEs.
  • Pin image digests, not tags. nginx:1.25 can change (someone pushes a new build with the same tag). nginx@sha256:abc123... is immutable.
  • Sign images. Use Cosign (Sigstore) to sign images in CI/CD. Configure Kubernetes admission controllers (Kyverno, OPA Gatekeeper) to reject unsigned images.
  • Private registry only. Don't pull images from Docker Hub in production. Mirror needed images to your private registry (ECR, GCR, ACR) and restrict pull sources.

Runtime Protection

Even with all preventive controls, assume a pod will eventually be compromised. Runtime protection detects and responds to active attacks:

Tool What It Detects License
Falco Unexpected system calls, file access, network connections, process execution Open source (CNCF)
Tetragon (Cilium) eBPF-based: process execution, file access, network flows with enforcement Open source
KubeArmor Process whitelisting, file access control, network restrictions per pod Open source
Aqua / Sysdig Full CNAPP: runtime detection, compliance, forensics Commercial

For getting started, Falco is the standard — it's CNCF-graduated, has strong community support, and detects the most common runtime threats (shell spawned in container, crypto mining, unexpected outbound connections). Deploy it as a DaemonSet and pipe alerts to your SIEM or Slack.

Frequently Asked Questions

What's the minimum security baseline for production K8s?

Five things, in order of priority: (1) RBAC with least-privilege roles, no default service account usage. (2) Network policies with default-deny. (3) Pod Security Standards at baseline or restricted. (4) Image scanning in CI/CD, blocking critical CVEs. (5) Encryption at rest for etcd. This covers 80% of the attack surface. Everything else is defense-in-depth.

Should we use managed K8s (EKS/GKE/AKS) or self-managed?

Managed, unless you have specific compliance requirements that mandate full control plane ownership. Managed K8s handles control plane security, etcd encryption, API server hardening, and automatic upgrades. Self-managing these is a full-time job for 1-2 engineers. Use that capacity for application-level security instead.

How do we handle multi-tenancy securely?

Namespace-per-tenant with: (1) RBAC restricting each tenant to their namespace. (2) Network policies isolating tenant namespaces. (3) Resource quotas preventing noisy-neighbor issues. (4) Pod Security Standards preventing privilege escalation. For strong isolation (hostile tenants), consider separate clusters — namespaces share a kernel, which is a meaningful attack surface. vCluster provides virtual clusters as a middle ground.

What compliance frameworks apply to K8s?

CIS Kubernetes Benchmark is the de facto standard — covers 200+ controls across API server, etcd, kubelet, and workload configuration. Run kube-bench (free, open-source) to audit against CIS benchmarks automatically. For specific regulations: SOC 2 requires access controls (RBAC + audit logging), PCI-DSS requires network segmentation (network policies), and HIPAA requires encryption at rest and in transit.

PI
Pillai Infotech Team

Cloud Infrastructure & Security

We deploy and secure Kubernetes clusters for production workloads. Our approach: security as code — every control in this article is automated in our CI/CD pipelines. Secure your K8s infrastructure.