Cloud & Infrastructure Security

Container & Kubernetes Security

4 min read

Container security is a hot interview topic. This lesson covers Docker hardening, Kubernetes RBAC, and cluster security patterns.

Docker Security Fundamentals

Container Isolation Layers

┌────────────────────────────────────────────────────────────┐
│                      HOST KERNEL                            │
├────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │
│  │ Container A │  │ Container B │  │ Container C │        │
│  │             │  │             │  │             │        │
│  │ ├─ PID NS   │  │ ├─ PID NS   │  │ ├─ PID NS   │        │
│  │ ├─ NET NS   │  │ ├─ NET NS   │  │ ├─ NET NS   │        │
│  │ ├─ MNT NS   │  │ ├─ MNT NS   │  │ ├─ MNT NS   │        │
│  │ ├─ USER NS  │  │ ├─ USER NS  │  │ ├─ USER NS  │        │
│  │ └─ cgroups  │  │ └─ cgroups  │  │ └─ cgroups  │        │
│  └─────────────┘  └─────────────┘  └─────────────┘        │
└────────────────────────────────────────────────────────────┘

Secure Dockerfile Practices

# Multi-stage build to minimize attack surface
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/app/deps -r requirements.txt

# Use distroless for minimal runtime
FROM gcr.io/distroless/python3-debian12

# Copy only what's needed
COPY --from=builder /app/deps /app/deps
COPY --chown=nonroot:nonroot app.py /app/

# Never run as root
USER nonroot

# Use specific entrypoint
ENTRYPOINT ["python", "/app/app.py"]

Docker Security Checklist

Practice Why It Matters
Non-root user Limits container escape impact
Read-only filesystem Prevents runtime modifications
No privileged mode Prevents host access
Resource limits Prevents DoS
Minimal base image Smaller attack surface
No secrets in images Prevents credential exposure
Image signing Ensures image integrity

Interview Question

Q: "What is a container escape and how do you prevent it?"

Answer: A container escape is when an attacker breaks out of container isolation to access the host system.

Prevention:

  • Never run containers as root
  • Never use --privileged flag
  • Drop all capabilities: --cap-drop=ALL
  • Use read-only root filesystem
  • Enable seccomp and AppArmor profiles
  • Keep kernel and container runtime updated
  • Use gVisor or Kata containers for high-security workloads

Kubernetes Security

RBAC (Role-Based Access Control)

# Role: What actions are allowed
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]

---
# RoleBinding: Who gets the role
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
- kind: ServiceAccount
  name: monitoring-sa
  namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Pod Security Standards

Level Description Use Case
Privileged No restrictions System workloads only
Baseline Minimal restrictions, prevents known escalations Most workloads
Restricted Heavily restricted, security best practices Sensitive workloads
# Enforce restricted security at namespace level
apiVersion: v1
kind: Namespace
metadata:
  name: secure-apps
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Secure Pod Specification

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 10000
    fsGroup: 10000
    seccompProfile:
      type: RuntimeDefault

  containers:
  - name: app
    image: myapp:v1.0.0@sha256:abc123...  # Pin by digest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]

    resources:
      limits:
        cpu: "500m"
        memory: "256Mi"
      requests:
        cpu: "100m"
        memory: "128Mi"

    volumeMounts:
    - name: tmp
      mountPath: /tmp

  volumes:
  - name: tmp
    emptyDir: {}

  automountServiceAccountToken: false  # Disable if not needed

Network Policies

# Default deny all ingress traffic
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress

---
# Allow specific traffic only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

Secrets Management in Kubernetes

# BAD: Secret in plain YAML (base64 is not encryption!)
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  password: cGFzc3dvcmQxMjM=  # Just base64 encoded!

---
# GOOD: Use external secrets operator
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: db-credentials
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: db-credentials
  data:
  - secretKey: password
    remoteRef:
      key: production/database
      property: password

Interview Tip: When discussing Kubernetes security, always mention the 4C's of cloud-native security: Code, Container, Cluster, Cloud. Each layer adds defense in depth.

Next, we'll cover Zero Trust architecture. :::

Quiz

Module 4: Cloud & Infrastructure Security

Take Quiz