How to Secure Kubernetes: Step-by-Step Best Practices for Locking Down Your Cluster
25+ hands-on examples from CKS lab scenarios to make you a Kubernetes security pro with comprehensive cluster hardening, container security, and runtime protection
Quick Navigation
Difficulty: 🔴 Advanced
Estimated Time: 45-60 minutes
Prerequisites: Advanced Kubernetes knowledge, kubectl experience, Understanding of security concepts, Access to cluster control plane, Basic Linux administration
What You'll Learn
This tutorial covers essential Kubernetes security concepts and tools:
- Cluster Hardening - Step-by-step API server security and RBAC implementation
- Container Security - Non-root containers, capability dropping, and read-only filesystems
- Network Security - Network policies, mTLS, and ingress security
- Supply Chain Security - Image scanning, signing, and admission policies
- Runtime Security - Falco monitoring and Pod Security Standards
- Node Security - OS hardening, SSH restrictions, and regular patching
- Advanced Configurations - Pod Security Standards and security contexts
Prerequisites
- Advanced Kubernetes knowledge and cluster administration experience
- kubectl command-line tool experience
- Understanding of security concepts and best practices
- Access to cluster control plane for configuration changes
- Basic Linux administration and security knowledge
Related Tutorials
- API Server Security - Comprehensive API server hardening
- NGINX Ingress with HTTPS - Secure external access
- Main Tutorials Hub - Step-by-step implementation guides
Introduction
In the world of cloud-native applications, Kubernetes reigns supreme. But it's also a tempting target for attackers. Without security guardrails, it becomes a hacker's paradise.
This comprehensive guide blends theory with practice, using real examples to show you how to secure your Kubernetes cluster from all angles.
Cluster Hardening - Step by Step
Disable Anonymous Access
Objective: Secure API server from unauthenticated access.
Steps:
- Edit the kube-apiserver manifest:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
- Add this line under
command:
section:
- --anonymous-auth=false
-
Save and exit. Kubelet will auto-restart the API server.
-
Verify:
ps aux | grep kube-apiserver
Enable RBAC Authorization
Objective: Use roles to limit user access.
Steps:
- Create a Role:
kubectl create role pod-reader \
--verb=get,list,watch --resource=pods -n dev
- Bind the role:
kubectl create rolebinding read-only-binding \
--role=pod-reader --user=dev-user -n dev
- Test access:
kubectl auth can-i get pods --as=dev-user -n dev
Enable Audit Logging
Steps:
- Create policy:
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
- Modify kube-apiserver manifest:
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/k8s-audit.log
-
Save & restart automatically.
-
Check audit logs:
tail -f /var/log/k8s-audit.log
Rotate TLS Certificates Regularly
Why: Mitigates risks from compromised or expired certs.
Steps:
kubeadm alpha certs renew all
systemctl restart kubelet
Automate using cronjobs and tools like cert-manager.
Use TLS for All Communication
Why: Encrypts traffic between components.
Steps:
Ensure all kubelet, etcd, and API server traffic uses --tls-cert-file
and --tls-private-key-file
Use mTLS between pods via service mesh like Istio.
Container Security - Deep Dive
Run as Non-Root
Steps:
- Patch your deployment:
securityContext:
runAsNonRoot: true
runAsUser: 1000
- Apply it:
kubectl apply -f secure-deployment.yaml
- Confirm:
kubectl describe pod <pod-name> | grep -i runAs
Drop All Capabilities
Steps:
- Edit deployment YAML:
securityContext:
capabilities:
drop:
- ALL
- Apply & test:
kubectl apply -f secure-deployment.yaml
- Verify:
kubectl exec -it <pod> -- capsh --print
Read-Only Filesystem
Steps:
securityContext:
readOnlyRootFilesystem: true
Test by trying to write to /
inside the pod:
kubectl exec -it <pod> -- touch /test.txt
It should fail!
Set CPU and Memory Limits
Why: Prevents resource abuse or denial-of-service.
Example:
resources:
limits:
memory: "128Mi"
cpu: "500m"
requests:
memory: "64Mi"
cpu: "250m"
Use Trusted Base Images
Why: Avoids preloaded vulnerabilities.
Use:
FROM gcr.io/distroless/base
COPY myapp /
ENTRYPOINT ["/myapp"]
Network Security - Locked Down
Deny All NetworkPolicy
Steps:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Apply:
kubectl apply -f deny-all.yaml
Test:
kubectl exec -it <pod-a> -- curl pod-b
Should be blocked!
Use Network Policies
Why: Restrict pod communication.
Deny-All Example:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
Use mTLS Between Services
Why: Encrypts service-to-service communication.
Tools: Istio, Linkerd, or Consul Connect.
Block Unnecessary Ports
Why: Minimizes exposed attack surfaces.
Steps:
iptables -A INPUT -p tcp --dport 80 -j DROP
Use External Load Balancer with WAF
Why: Protects against HTTP-level attacks.
Tools: AWS ALB + WAF, Cloudflare, Azure Front Door.
Whitelist Source IPs for Ingress
Why: Restrict access to known IPs.
Nginx Ingress Example:
nginx.ingress.kubernetes.io/whitelist-source-range: "192.168.1.0/24"
Supply Chain Security - Image Integrity
Scan Images with Trivy
Steps:
- Install Trivy:
brew install aquasecurity/trivy/trivy
- Scan an image:
trivy image nginx:latest
- Review results for HIGH or CRITICAL CVEs
Sign and Verify Images with Cosign
Steps:
- Generate key:
cosign generate-key-pair
- Sign:
cosign sign --key cosign.key docker.io/myapp:v1
- Verify:
cosign verify --key cosign.pub docker.io/myapp:v1
Enforce Admission Policies
Why: Block insecure pods before they run.
Use:
- Kyverno
- OPA Gatekeeper
kind: ConstraintTemplate
metadata:
name: k8spspallowprivilegeescalation
Monitoring & Runtime Security - Real-Time Protection
Install Falco via Helm
Steps:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco
- Check logs:
kubectl logs -n falco <falco-pod>
Enable PodSecurity Admission (PSA)
Steps:
- Add label to namespace:
kubectl label ns dev pod-security.kubernetes.io/enforce=restricted
- Deploy insecure pod — it should be rejected
Node & Host Security
Use Minimal OS Images
Why: Reduces attack surface.
Use: Bottlerocket, Flatcar, or Ubuntu minimal.
Example:
# For Ubuntu minimal
sudo apt-get remove --purge nano curl telnet
Disable Direct SSH Access
Why: Prevents lateral movement attacks.
Steps:
- Use firewall rules to block port 22
- Implement bastion host with audit logging
Regularly Patch Nodes
Why: Prevents exploits from known vulnerabilities.
Steps:
sudo apt update && sudo apt upgrade -y
sudo reboot
Automate via unattended-upgrades.
Enforce Seccomp
Why: Restricts syscalls to prevent kernel-level exploits.
Example:
securityContext:
seccompProfile:
type: RuntimeDefault
Apply to pods in deployments or pod templates.
Enable AppArmor or SELinux
Why: Adds MAC (Mandatory Access Control) to containers.
Steps (AppArmor):
apparmor_parser -r /etc/apparmor.d/my_profile
# In pod spec:
annotations:
container.apparmor.security.beta.kubernetes.io/nginx: localhost/my_profile
Advanced Security Configurations
Pod Security Standards (PSS)
Implement Pod Security Standards for automatic policy enforcement:
apiVersion: v1
kind: Namespace
metadata:
name: secure-namespace
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Security Context Best Practices
Comprehensive security context configuration:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
seccompProfile:
type: RuntimeDefault
allowPrivilegeEscalation: false
Network Policy Examples
Advanced network policy configurations:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-specific-traffic
namespace: production
spec:
podSelector:
matchLabels:
app: web
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: frontend
ports:
- protocol: TCP
port: 80
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
Next Steps
- Security Auditing: Implement continuous security scanning
- Compliance: Meet CIS Kubernetes Benchmark requirements
- Incident Response: Create security incident playbooks
- Training: Conduct regular security workshops
- Automation: Implement security-as-code practices
Related Tutorials
- API Server Security - Comprehensive API server hardening
- NGINX Ingress with HTTPS - Secure external access
- PostgreSQL on Kubernetes - Secure database deployments
External Resources
- CIS Kubernetes Benchmark
- Kubernetes Security Documentation
- Falco Security
- Trivy Vulnerability Scanner
- Cosign Image Signing
Troubleshooting
Common Security Issues
- RBAC Not Working: Check authorization mode and role bindings
- Network Policies Blocking: Verify policy configuration and pod selectors
- Security Context Rejected: Check Pod Security Standards and admission controllers
- TLS Handshake Failures: Validate certificate configuration and paths
Debug Commands
# Check security context
kubectl describe pod <pod-name> | grep -i security
# Verify network policies
kubectl get networkpolicy -A
kubectl describe networkpolicy <policy-name> -n <namespace>
# Check RBAC configuration
kubectl auth can-i <verb> <resource> --as=<user> -n <namespace>
# Validate Pod Security Standards
kubectl label namespace <namespace> pod-security.kubernetes.io/enforce=restricted --dry-run=server
Security Checklist
- Anonymous authentication disabled
- RBAC enabled and configured
- Audit logging enabled
- TLS certificates configured
- Non-root containers enforced
- Capabilities dropped
- Read-only filesystems
- Resource limits set
- Network policies implemented
- Image scanning enabled
- Admission controllers configured
- Runtime security monitoring
- Node security hardened
- Regular patching schedule
- Security context enforced
Conclusion
Kubernetes security is not one big task — it's hundreds of small steps. This article gave you real-world examples, battle-tested practices, and production-proven techniques.
Key Takeaways
- Comprehensive Security - Multi-layered approach covering all attack vectors
- Practical Implementation - Real-world examples from CKS lab scenarios
- Production Ready - Battle-tested practices for enterprise environments
- Continuous Improvement - Regular patching, monitoring, and policy updates
- Security as Code - Automated security policies and configurations
Next Steps
- Implement cluster hardening starting with API server security
- Configure container security with proper security contexts
- Set up network policies to restrict pod communication
- Enable supply chain security with image scanning and signing
- Implement runtime monitoring with Falco and Pod Security Standards
These 25 best practices are battle-tested and production-proven. Combine them with tools like kubectl, trivy, cosign, falco, and kyverno to fully armor your Kubernetes environment.
Don't just read. Practice these steps. Build muscle memory. Pass CKS. Protect your production.
Ready to become a Kubernetes security expert? Practice these steps and build your security muscle memory!
Tags: #Kubernetes #DevOps #DevSecOps #Security #CKS #ClusterHardening #ContainerSecurity #NetworkSecurity #SupplyChainSecurity #RuntimeSecurity