Module 3: Containers & Workload Security
Hardening containers from image build to runtime with Pod Security Standards, seccomp, and distroless images
3 hours. 3 hands-on labs. Free course module.
Learning Objectives
- Understand Linux container isolation primitives (namespaces, cgroups)
- Build secure container images with distroless and rootless patterns
- Configure Pod Security Standards for cluster-wide enforcement
- Implement seccomp and capabilities restrictions
Why This Matters
Container escapes are the most impactful Kubernetes attacks — breaking out of a container gives the attacker access to the node and potentially the entire cluster. Proper container hardening is the first line of defense and the most frequently misconfigured.
Lesson Content
Containers are not VMs. They share the host kernel and rely on Linux primitives — namespaces, cgroups, seccomp, capabilities — for isolation. Misconfigure any of these, and the container boundary dissolves.
Linux Container Isolation Primitives
- Namespaces: Isolate what a container can see (PID, network, mount, user, IPC, UTS)
- cgroups: Limit what a container can use (CPU, memory, I/O)
- Seccomp: Filter which syscalls a container can make (block dangerous ones like ptrace, mount)
- Capabilities: Fine-grained root privileges (drop everything except what is needed)
- AppArmor/SELinux: Mandatory access control for file and network operations
Secure Container Image Patterns
# Insecure: full OS, root user, unnecessary tools
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl wget vim
COPY app /app
CMD ["/app"]
# Secure: distroless, non-root, minimal attack surface
FROM gcr.io/distroless/static-debian12:nonroot
COPY --chown=65534:65534 app /app
USER 65534
ENTRYPOINT ["/app"]
# No shell, no package manager, no curl, no wget
# Attacker with RCE cannot spawn a shell
Pod Security Standards
Kubernetes defines three Pod Security Standards that enforce container hardening at the namespace level:
- Privileged: No restrictions (for system workloads only)
- Baseline: Prevents known privilege escalations (blocks hostPID, hostNetwork, privileged)
- Restricted: Maximum hardening (requires non-root, read-only root FS, drops ALL capabilities)
# Enforce restricted Pod Security Standard on a namespace
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
Real-World Use Cases
- Hardening container images for production
- Implementing Pod Security Standards cluster-wide
- Building distroless CI pipelines
- Container escape prevention in multi-tenant clusters
Production Notes
- Use distroless or scratch base images for all production workloads. A container with no shell cannot be used for interactive exploitation.
- Apply the restricted Pod Security Standard to all production namespaces. Use warn mode first to identify non-compliant workloads before enforcing.
Common Mistakes
- Running containers as root (the default in most base images)
- Using ubuntu or alpine base images that include shells and package managers
- Not dropping ALL capabilities and adding back only what is needed
- Setting privileged: true "just to make it work" and never removing it
- Not enforcing Pod Security Standards on production namespaces
Security Risks to Watch
- privileged: true gives the container ALL capabilities including CAP_SYS_ADMIN — equivalent to root on the host
- hostPID exposes all host processes to the container — enables credential theft from other pods
- hostNetwork puts the container on the host network stack — bypasses all NetworkPolicies
Production Story
A container running as root with hostPID was used by an attacker to read K8s secrets from kubelet process memory. After enforcing Pod Security Standards cluster-wide, privileged containers were blocked before reaching production.
Career Relevance
Container hardening is foundational for any K8s security role. Organizations need engineers who build secure-by-default container pipelines.
Key Terms
- Namespace (Linux)
- Kernel feature that isolates what a process can see (PID, network, mount, etc.)
- cgroup
- Control group — limits CPU, memory, and I/O resources for a set of processes
- Seccomp
- Secure computing mode — filters which syscalls a process can make
- Distroless
- Container image containing only the application binary and runtime — no OS tools
- Pod Security Standard
- Kubernetes policy level (Privileged/Baseline/Restricted) for container hardening
Hands-On Labs
-
Harden an Insecure Container
Transform an insecure Dockerfile into a hardened production image.
30 min - Beginner
- Start with a vulnerable Dockerfile (root, full OS, unnecessary tools)
- Rebuild with distroless base image
- Add non-root user and read-only filesystem
- Compare image sizes and attack surfaces
-
Configure Pod Security Standards
Enforce container hardening at the namespace level.
25 min - Beginner
- Label a namespace with restricted Pod Security Standard
- Deploy a compliant pod (succeeds)
- Deploy a non-compliant pod with hostPID (rejected)
- Review audit logs for policy violations
-
Container Escape Demonstration
Understand how misconfigurations enable container escape.
30 min - Intermediate
- Deploy a privileged container with hostPID
- Access host processes from inside the container
- Read host filesystem via /proc/1/root
- Fix the configuration and verify isolation is restored
Key Takeaways
- Containers share the host kernel — isolation depends on namespaces, cgroups, seccomp
- Distroless images eliminate shells and tools, drastically reducing attack surface
- Pod Security Standards enforce container hardening at the namespace level
- Never run containers as root or with privileged: true in production
- Seccomp profiles block dangerous syscalls — always enable the default profile