Defense in Depth for Kubernetes
Securing a cluster means layering controls: who can call the API (authentication/authorization), what traffic Pods can send or receive (network policy), what a container is allowed to do at runtime (Pod security context), and how sensitive data and images are handled before they ever run. No single control is sufficient on its own — they combine to reduce blast radius when something goes wrong.
Cricket analogy: Securing a cluster is like a franchise layering checks: who can enter the dressing room (authentication), what messages fielders can pass to each other (network policy), what a player is allowed to do on the pitch (security context), and how the trophy and player contracts are handled before the tournament even starts.
RBAC: Roles and RoleBindings
Role-Based Access Control governs who can perform which verbs (get, list, create, delete, etc.) on which resources. A Role (namespace-scoped) or ClusterRole (cluster-scoped) defines permissions; a RoleBinding or ClusterRoleBinding grants those permissions to a user, group, or ServiceAccount. Follow least privilege: grant only the verbs and resources actually needed, avoid binding cluster-admin to application or CI ServiceAccounts, and audit wildcard rules (resources: ["*"], verbs: ["*"]) closely.
Cricket analogy: RBAC is like a club's committee granting specific powers: a groundskeeper role can only water and mow (get, list), never sign new players (create, delete); avoid handing the tea-boy the chairman's full authority (cluster-admin), and audit any role with blanket powers over everything.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: prod
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-ci
namespace: prod
subjects:
- kind: ServiceAccount
name: ci-runner
namespace: prod
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioNetworkPolicies: restricting pod-to-pod traffic
By default, all Pods in a cluster can reach all other Pods on any port — there is no network isolation unless the CNI plugin enforces NetworkPolicy resources (Calico, Cilium, and others support this; some CNIs do not). A NetworkPolicy selects Pods by label and defines allowed ingress/egress rules; once any policy selects a Pod, all traffic not explicitly allowed is denied by default for that direction. A good baseline is a default-deny policy per namespace plus explicit allow rules for required paths only. This is combined with Pod-level securityContext hardening (covered next) to shrink the container's attack surface at both the network and OS-process layers.
Cricket analogy: By default all Pods reaching each other is like every player from every team having free access to every dressing room; a NetworkPolicy is like security enforcing that only registered squad members enter their own room, with a default-deny stance requiring explicit accreditation for any other access.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-api
namespace: prod
spec:
podSelector:
matchLabels: { app: api }
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels: { app: frontend }
ports:
- protocol: TCP
port: 8080Pod Security: securityContext and Pod Security Standards
securityContext (at the Pod or container level) restricts what a container process can do on the host: runAsNonRoot/runAsUser avoid running as root, readOnlyRootFilesystem prevents writes to the container filesystem (mount a writable emptyDir at specific paths that need it, rather than disabling the setting), allowPrivilegeEscalation: false blocks gaining more privileges than the parent process, and capabilities.drop: ["ALL"] removes all Linux capabilities by default. Kubernetes also defines Pod Security Standards (Privileged, Baseline, Restricted) enforceable per-namespace via the built-in Pod Security Admission controller using namespace labels.
Cricket analogy: securityContext hardening is like a player's kit restrictions: runAsNonRoot means no one plays as the untouchable captain by default, readOnlyRootFilesystem means you can't rewrite the official rulebook (only scribble on a scratchpad), and capabilities.drop ALL strips every special privilege unless explicitly re-granted.
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
containers:
- name: web
image: registry.example.com/web:1.5.0
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
---
# Enforce the Restricted Pod Security Standard on a namespace
apiVersion: v1
kind: Namespace
metadata:
name: prod
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restrictedKubernetes Secrets are base64-encoded, not encrypted, by default — treat base64 as encoding, not security. Enable encryption at rest for the etcd datastore, restrict RBAC access to Secret objects tightly (get on secrets is effectively read access to credentials), avoid mounting Secrets as environment variables when possible (volume mounts are generally preferred), and consider an external secrets manager (Vault, AWS/GCP/Azure secret stores) synced in via a controller for rotation and auditing. Separately, scan container images for known CVEs before deployment (tools like Trivy or Grype), pin images by digest rather than a mutable tag like latest in production, and use admission control (OPA Gatekeeper or Kyverno) to block images that fail a scan or lack a required provenance attestation.
Cricket analogy: Base64-encoded Secrets are like a scorecard written in a simple substitution code anyone can decode — not real security; encrypt the archive at rest, restrict who can view player contracts (RBAC on Secrets), prefer sealed envelopes over open memos (volume mounts over env vars), and use an external vault for player medical records with rotation and audit trails, while scanning new equipment for defects (image CVEs) and pinning the exact model used (digest) rather than 'latest gear'.
kubectl create secret generic db-creds \
--from-literal=username=app \
--from-literal=password='REDACTED' \
-n prod
# Prefer least-privilege RBAC: only specific ServiceAccounts should get/list secrets
kubectl auth can-i get secrets -n prod --as=system:serviceaccount:prod:ci-runner
trivy image registry.example.com/web:1.5.0
# Scans for OS package and application-dependency CVEs, reports by severity- RBAC Roles/ClusterRoles define permissions; RoleBindings/ClusterRoleBindings grant them — always apply least privilege.
- NetworkPolicies are deny-by-default only once a policy selects a Pod, and require a CNI that supports them.
- securityContext settings like runAsNonRoot, readOnlyRootFilesystem, and dropped capabilities shrink the container's attack surface.
- Pod Security Admission enforces Privileged/Baseline/Restricted standards per namespace via labels.
- Kubernetes Secrets are base64-encoded, not encrypted — enable etcd encryption at rest and restrict RBAC on secrets.
- Scan images for CVEs (e.g. Trivy) and pin by digest; use admission policies to enforce scanning before deploy.
Practice what you learned
1. What is the purpose of a Kubernetes RoleBinding?
2. By default, without any NetworkPolicy applied, how can Pods in a cluster communicate?
3. Which securityContext setting prevents a container from writing to its own filesystem at runtime?
4. Are Kubernetes Secrets encrypted by default?
5. What is a primary benefit of scanning container images before deployment?
6. Which Pod Security Standard level is the most restrictive, disallowing privilege escalation and requiring non-root execution?
Was this page helpful?
You May Also Like
Docker Security Basics
Defensive practices for hardening container images and runtime, including non-root users, minimal base images, vulnerability scanning, and dropped capabilities.
ConfigMaps and Secrets
Learn how to externalize configuration and sensitive data from container images using ConfigMaps and Secrets in Kubernetes.
Namespaces and Resource Quotas
Understand how Kubernetes Namespaces provide multi-tenant isolation and how ResourceQuotas and LimitRanges enforce fair compute usage across teams.
Kubernetes Monitoring and Logging
Learn the core tools and patterns for observing cluster and application health: metrics, logs, and the Prometheus/Grafana stack.
Related Reading
Related Study Notes in DevOps
Browse all study notesNginx Study Notes
DevOps · 30 topics
DevOpsAnsible Study Notes
DevOps · 30 topics
DevOpsAdvanced Kubernetes Study Notes
Kubernetes · 30 topics
DevOpsAdvanced Bash Scripting Study Notes
Bash · 30 topics
DevOpsApache Kafka Study Notes
Kafka · 30 topics
DevOpsCI/CD Tools & Pipelines Study Notes
YAML · 37 topics