Kubernetes Security — Pod Security, RBAC & Network Policies Guide
In this tutorial, you'll learn about Kubernetes Security. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
Kubernetes security protects cluster workloads through pod security standards, role-based access control, network policies, and admission controllers that enforce security at every layer of the stack.
What You Will Learn
How to harden a Kubernetes cluster using pod security contexts, RBAC roles and bindings, network isolation policies, and admission Webhooks that prevent misconfigured deployments.
Why It Matters
Kubernetes clusters are complex attack surfaces. A single overly permissive RBAC role or unrestricted pod can allow an attacker to pivot from a compromised container to the entire cluster.
Real-World Use
A fintech company runs 50 Microservices on EKS. They use OPA Gatekeeper to enforce that every pod specifies a read-only root filesystem and a non-root user. GuardDuty monitors runtime anomalies across all namespaces.
Kubernetes Security Model
flowchart TD
subgraph Control Plane
API[API Server] --> Auth[Authentication]
Auth --> RBAC[RBAC Authorization]
RBAC --> Adm[Admission Controllers]
Adm --> Pods[Workloads]
end
subgraph Data Plane
Pods --> PSA[Pod Security Standards]
PSA --> Net[Network Policies]
Net --> Secrets[Secrets Management]
end
style RBAC fill:#f90,color:#fff
style PSA fill:#390,color:#fff
Pod Security Standards
Kubernetes defines three pod security standards: privileged, baseline, and restricted. Apply the restricted profile to enforce least-privilege pod behavior.
# Apply the restricted pod security standard to a namespace
kubectl label ns production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
# Verify the label
kubectl get ns production -o yaml
# Output:
# apiVersion: v1
# kind: Namespace
# metadata:
# labels:
# pod-security.kubernetes.io/enforce: restricted
# name: production
RBAC Configuration
RBAC controls who can access what resources and with which verbs. Always use least-privilege roles.
# Create a role that allows only reading pods and logs
kubectl create role pod-reader \
--verb=get,list,watch \
--resource=pods,pods/log \
--namespace=production
# Bind the role to a service account
kubectl create rolebinding pod-reader-binding \
--role=pod-reader \
--serviceaccount=production:app-sa \
--namespace=production
# Test the binding
kubectl auth can-i list pods --as=system:serviceaccount:production:app-sa
# Output:
# yes
Network Policies
By default, all pods can communicate with all other pods. Network policies enforce zero-trust network segmentation.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# Apply the default-deny policy, then allow specific traffic
kubectl apply -f deny-all.yaml
# Output: networkpolicy.networking.k8s.io/deny-all created
# Allow ingress only from frontend pods
kubectl create networkpolicy allow-frontend \
--namespace production \
--pod-selector app=backend \
--ingress '{"from":[{"podSelector":{"matchLabels":{"app":"frontend"}}]}'
Secrets Management
Store secrets in cloud-native vaults like AWS Secrets Manager, Azure Key Vault, or GCP Secret Manager. Use the Secrets Store CSI driver to mount them into pods.
# Install the Secrets Store CSI driver on EKS
helm repo add secrets-store-csi-driver \
https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver \
--namespace kube-system
# Mount an AWS Secrets Manager secret as a volume
# See the Secrets Store CSI driver provider documentation
Admission Controllers
Admission controllers intercept API requests before persistence. OPA Gatekeeper and Kyverno enforce custom security policies.
# Install OPA Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
# Apply a constraint requiring all containers to have resource limits
kubectl apply -f - <<EOF
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResources
metadata:
name: container-must-have-limits
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
limits:
memory: "required"
cpu: "required"
EOF
Common Mistakes
- Running containers as root: Containers with root privileges can escape the container to the host. Enforce runAsNonRoot in security contexts.
- Overly permissive RBAC roles: ClusterRole with
*verbs on*resources gives full cluster admin. Scope roles to namespaces and specific resources. - No network policies: Without policies, any compromised pod can probe any other pod across the cluster.
- Secrets in environment variables: Environment variables leak in logs, exec sessions, and bug reports. Mount secrets as files or use the CSI driver.
- Disabling audit logging: The Kubernetes API server generates audit logs for every request. Disabling them eliminates forensic visibility.
Practice Questions
- What is the difference between a Role and a ClusterRole?
- How do pod security standards enforce container behavior?
- Why is a default-deny network policy important for cluster security?
- How do admission controllers like OPA Gatekeeper improve security?
- What is the safest way to inject secrets into Kubernetes pods?
Challenge
Harden a Kubernetes cluster. Create three namespaces (dev, staging, production). Apply the restricted pod security standard to production. Create RBAC roles that allow developers to only view pods and logs in staging. Apply a network policy that allows ingress only from the ingress controller to web pods. Install OPA Gatekeeper and add a constraint requiring all containers to run as non-root.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro