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

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:

  1. Edit the kube-apiserver manifest:
vim /etc/kubernetes/manifests/kube-apiserver.yaml
  1. Add this line under command: section:
- --anonymous-auth=false
  1. Save and exit. Kubelet will auto-restart the API server.

  2. Verify:

ps aux | grep kube-apiserver

Enable RBAC Authorization

Objective: Use roles to limit user access.

Steps:

  1. Create a Role:
kubectl create role pod-reader \
--verb=get,list,watch --resource=pods -n dev
  1. Bind the role:
kubectl create rolebinding read-only-binding \
--role=pod-reader --user=dev-user -n dev
  1. Test access:
kubectl auth can-i get pods --as=dev-user -n dev

Enable Audit Logging

Steps:

  1. Create policy:
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: Metadata
  1. Modify kube-apiserver manifest:
- --audit-policy-file=/etc/kubernetes/audit-policy.yaml
- --audit-log-path=/var/log/k8s-audit.log
  1. Save & restart automatically.

  2. 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:

  1. Patch your deployment:
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  1. Apply it:
kubectl apply -f secure-deployment.yaml
  1. Confirm:
kubectl describe pod <pod-name> | grep -i runAs

Drop All Capabilities

Steps:

  1. Edit deployment YAML:
securityContext:
  capabilities:
    drop:
      - ALL
  1. Apply & test:
kubectl apply -f secure-deployment.yaml
  1. 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:

  1. Install Trivy:
brew install aquasecurity/trivy/trivy
  1. Scan an image:
trivy image nginx:latest
  1. Review results for HIGH or CRITICAL CVEs

Sign and Verify Images with Cosign

Steps:

  1. Generate key:
cosign generate-key-pair
  1. Sign:
cosign sign --key cosign.key docker.io/myapp:v1
  1. 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
  1. Check logs:
kubectl logs -n falco <falco-pod>

Enable PodSecurity Admission (PSA)

Steps:

  1. Add label to namespace:
kubectl label ns dev pod-security.kubernetes.io/enforce=restricted
  1. 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

External Resources

Troubleshooting

Common Security Issues

  1. RBAC Not Working: Check authorization mode and role bindings
  2. Network Policies Blocking: Verify policy configuration and pod selectors
  3. Security Context Rejected: Check Pod Security Standards and admission controllers
  4. 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

  1. Implement cluster hardening starting with API server security
  2. Configure container security with proper security contexts
  3. Set up network policies to restrict pod communication
  4. Enable supply chain security with image scanning and signing
  5. 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