Skip to content

Pod Security Standards

Pod Security Standards enforce security policies at the pod level. Configure based on workload sensitivity.

Standard Levels

  • Privileged: Unrestricted (not recommended)
  • Baseline: Minimal restrictions, prevents known exploits
  • Restricted: Hardened, enforces security best practices

Terraform Configuration

# gke/security/pod-security.tf
resource "kubernetes_namespace" "prod" {
  metadata {
    name = "prod"

    labels = {
      "pod-security.kubernetes.io/enforce"        = "restricted"
      "pod-security.kubernetes.io/audit"          = "restricted"
      "pod-security.kubernetes.io/warn"           = "restricted"
    }
  }
}

resource "kubernetes_namespace" "dev" {
  metadata {
    name = "dev"

    labels = {
      "pod-security.kubernetes.io/enforce"        = "baseline"
      "pod-security.kubernetes.io/audit"          = "restricted"
      "pod-security.kubernetes.io/warn"           = "restricted"
    }
  }
}

resource "kubernetes_namespace" "system" {
  metadata {
    name = "kube-system"

    labels = {
      "pod-security.kubernetes.io/enforce"        = "privileged"
    }
  }
}

Production Standard

Production namespaces must use restricted standard. Development can use baseline for compatibility.

Pod Manifest Examples

# manifests/secure-pod.yaml
---
# Secure pod for production
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: prod
spec:
  serviceAccountName: secure-app

  containers:
    - name: app
      image: gcr.io/my-project/secure-app:latest
      imagePullPolicy: Always

      securityContext:
        allowPrivilegeEscalation: false
        runAsNonRoot: true
        runAsUser: 1000
        runAsGroup: 1000
        readOnlyRootFilesystem: true
        capabilities:
          drop:
            - ALL
          add:
            - NET_BIND_SERVICE

      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 500m
          memory: 512Mi

      livenessProbe:
        httpGet:
          path: /health
          port: 8080
        initialDelaySeconds: 10
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3

      readinessProbe:
        httpGet:
          path: /ready
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 5
        timeoutSeconds: 3
        failureThreshold: 3

      volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: cache
          mountPath: /app/cache

  volumes:
    - name: tmp
      emptyDir: {}
    - name: cache
      emptyDir:
        sizeLimit: 1Gi

  # Pod security context
  securityContext:
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault

  # Network policies (implicit default-deny)
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector:
              matchExpressions:
                - key: app
                  operator: In
                  values:
                    - secure-app
            topologyKey: kubernetes.io/hostname

Security Best Practices

  • Always set runAsNonRoot: true
  • Drop all capabilities, add only what's needed
  • Use readOnlyRootFilesystem: true when possible
  • Define resource limits to prevent DoS

Deployment Workflow

1. Configure Pod Security Standards

# Label production namespace for restricted policy
kubectl label namespace prod pod-security.kubernetes.io/enforce=restricted
kubectl label namespace prod pod-security.kubernetes.io/audit=restricted
kubectl label namespace prod pod-security.kubernetes.io/warn=restricted

# Verify labels
kubectl get namespace prod -o yaml | grep pod-security

Runtime Security Checklist

#!/bin/bash
# Pod Security Standards verification

echo "=== Pod Security Standards ==="
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-security\.kubernetes\.io/enforce}{"\n"}{end}' | column -t

echo ""
echo "=== Pod Security Violations ==="
kubectl get events --all-namespaces --field-selector reason=FailedCreate | grep -i "violates PodSecurity" | wc -l | \
  awk '{if ($1 > 0) print "⚠ "$1" pod security violations"; else print "✓ No violations"}'

References

Comments