Implement Kubernetes Pod Security Standards and admission controllers for policy enforcement

Advanced 45 min Apr 07, 2026 1,124 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure Pod Security Standards with baseline and restricted profiles, deploy OPA Gatekeeper admission controller with custom policies, and implement ValidatingAdmissionWebhooks for comprehensive security enforcement in production Kubernetes clusters.

Prerequisites

  • Existing Kubernetes cluster with admin access
  • kubectl configured
  • Basic understanding of Kubernetes RBAC
  • Prometheus monitoring stack (optional for alerting)

What this solves

Kubernetes Pod Security Standards provide a built-in framework for enforcing security policies at the namespace level, replacing deprecated Pod Security Policies. This tutorial shows you how to implement Pod Security Standards with baseline and restricted profiles, deploy OPA Gatekeeper for custom policy enforcement, and configure ValidatingAdmissionWebhooks to prevent insecure workloads from running in your cluster. You'll also set up comprehensive monitoring and alerting for security violations to maintain compliance in production environments.

Step-by-step configuration

Update system and install dependencies

Start by updating your system and installing necessary tools for Kubernetes security management.

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git jq
sudo dnf update -y
sudo dnf install -y curl wget git jq

Install kubectl and helm

Install kubectl for cluster management and Helm for package management.

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt update
sudo apt install -y helm
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

Create namespace labels for Pod Security Standards

Configure namespaces with appropriate Pod Security Standard labels for baseline and restricted security profiles.

# Create test namespaces
kubectl create namespace baseline-ns
kubectl create namespace restricted-ns
kubectl create namespace privileged-ns

# Label namespaces with Pod Security Standards
kubectl label namespace baseline-ns \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=baseline \
  pod-security.kubernetes.io/warn=baseline

kubectl label namespace restricted-ns \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

kubectl label namespace privileged-ns \
  pod-security.kubernetes.io/enforce=privileged \
  pod-security.kubernetes.io/audit=privileged \
  pod-security.kubernetes.io/warn=privileged

Configure cluster-wide Pod Security Standards

Set default Pod Security Standards at the cluster level by modifying the kube-apiserver configuration.

spec:
  containers:
  - command:
    - kube-apiserver
    - --admission-control-config-file=/etc/kubernetes/admission-control.yaml
    - --feature-gates=PodSecurity=true
    # Add other existing flags here
    volumeMounts:
    - mountPath: /etc/kubernetes/admission-control.yaml
      name: admission-control-config
      readOnly: true
  volumes:
  - hostPath:
      path: /etc/kubernetes/admission-control.yaml
      type: File
    name: admission-control-config

Create admission control configuration

Define the admission control configuration file for Pod Security Standards enforcement.

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1beta1
    kind: PodSecurityConfiguration
    defaults:
      enforce: "baseline"
      enforce-version: "latest"
      audit: "baseline"
      audit-version: "latest"
      warn: "baseline"
      warn-version: "latest"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces: ["kube-system", "kube-public", "kube-node-lease"]

Install OPA Gatekeeper

Deploy OPA Gatekeeper admission controller for custom policy enforcement using Helm.

helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update

# Create gatekeeper-system namespace
kubectl create namespace gatekeeper-system

# Install Gatekeeper with audit enabled
helm install gatekeeper gatekeeper/gatekeeper \
  --namespace gatekeeper-system \
  --set audit.replicas=2 \
  --set replicas=3 \
  --set audit.auditInterval=60 \
  --set audit.logLevel=INFO \
  --set logLevel=INFO

Create constraint templates for security policies

Define constraint templates for common security policies like required security contexts and resource limits.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredsecuritycontext
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredSecurityContext
      validation:
        properties:
          runAsNonRoot:
            type: boolean
          runAsUser:
            type: integer
          fsGroup:
            type: integer
          allowPrivilegeEscalation:
            type: boolean
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredsecuritycontext
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsNonRoot
          msg := "Container must run as non-root user"
        }
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.allowPrivilegeEscalation != false
          msg := "Container must not allow privilege escalation"
        }
        
        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsUser
          msg := "Container must specify runAsUser"
        }

Create resource limits constraint template

Define a constraint template to enforce resource limits on all containers.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredresourcelimits
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredResourceLimits
      validation:
        properties:
          limits:
            type: array
            items:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredresourcelimits
        
        missing_limits[limit] {
          required := input.parameters.limits
          limit := required[_]
          not input.review.object.spec.containers[_].resources.limits[limit]
        }
        
        violation[{"msg": msg}] {
          limit := missing_limits[_]
          msg := sprintf("Container must specify resource limit: %v", [limit])
        }

Apply constraint templates

Deploy the constraint templates to your cluster.

kubectl apply -f required-security-context-template.yaml
kubectl apply -f resource-limits-template.yaml

# Wait for templates to be established
kubectl wait --for=condition=Established crd/k8srequiredsecuritycontext.templates.gatekeeper.sh --timeout=60s
kubectl wait --for=condition=Established crd/k8srequiredresourcelimits.templates.gatekeeper.sh --timeout=60s

Create security context constraints

Apply constraints using the templates to enforce security context requirements in specific namespaces.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredSecurityContext
metadata:
  name: must-have-security-context
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system", "gatekeeper-system", "kube-public"]
  parameters:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    allowPrivilegeEscalation: false

Create resource limits constraints

Apply constraints to enforce resource limits on all containers.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredResourceLimits
metadata:
  name: must-have-resource-limits
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system", "gatekeeper-system", "kube-public"]
  parameters:
    limits: ["memory", "cpu"]

Apply all constraints

Deploy the constraints to enforce security policies cluster-wide.

kubectl apply -f security-context-constraint.yaml
kubectl apply -f resource-limits-constraint.yaml

# Check constraint status
kubectl get constraints
kubectl describe K8sRequiredSecurityContext must-have-security-context

Create ValidatingAdmissionWebhook

Implement a custom ValidatingAdmissionWebhook for additional security checks beyond OPA Gatekeeper.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: security-webhook
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: security-webhook
  template:
    metadata:
      labels:
        app: security-webhook
    spec:
      containers:
      - name: webhook
        image: nginx:1.24
        ports:
        - containerPort: 8443
        volumeMounts:
        - name: certs
          mountPath: /etc/certs
          readOnly: true
        securityContext:
          runAsNonRoot: true
          runAsUser: 1000
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
            - ALL
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
      volumes:
      - name: certs
        secret:
          secretName: webhook-certs

Create webhook certificates

Generate TLS certificates for the ValidatingAdmissionWebhook using OpenSSL.

# Create certificate authority
openssl genrsa -out ca-key.pem 2048
openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 365 -subj "/CN=webhook-ca"

# Create webhook certificate
openssl genrsa -out webhook-key.pem 2048
openssl req -new -key webhook-key.pem -out webhook-csr.pem -subj "/CN=security-webhook.default.svc"
openssl x509 -req -in webhook-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out webhook-cert.pem -days 365

# Create secret with certificates
kubectl create secret tls webhook-certs \
  --cert=webhook-cert.pem \
  --key=webhook-key.pem

Configure ValidatingAdmissionWebhook

Create the ValidatingAdmissionWebhook configuration to intercept pod creation requests.

apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionWebhook
metadata:
  name: security-validator
webhooks:
- name: pod-security-validator.example.com
  clientConfig:
    service:
      name: security-webhook-service
      namespace: default
      path: "/validate"
    caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...  # Base64 encoded CA cert
  rules:
  - operations: ["CREATE", "UPDATE"]
    apiGroups: [""]
    apiVersions: ["v1"]
    resources: ["pods"]
  admissionReviewVersions: ["v1", "v1beta1"]
  sideEffects: None
  failurePolicy: Fail

Set up monitoring and alerting

Configure Prometheus monitoring for Pod Security Standards and Gatekeeper violations. This requires an existing Prometheus setup.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: gatekeeper-audit
  namespace: gatekeeper-system
spec:
  selector:
    matchLabels:
      gatekeeper.sh/operation: audit
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: pod-security-alerts
  namespace: gatekeeper-system
spec:
  groups:
  - name: gatekeeper.rules
    rules:
    - alert: GatekeeperViolation
      expr: increase(gatekeeper_violations_total[5m]) > 0
      for: 0m
      labels:
        severity: warning
      annotations:
        summary: "Gatekeeper policy violation detected"
        description: "Constraint {{ $labels.violation_kind }} has {{ $value }} violations in the last 5 minutes"
    - alert: HighGatekeeperViolationRate
      expr: rate(gatekeeper_violations_total[5m]) > 0.1
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "High rate of Gatekeeper violations"
        description: "Gatekeeper violation rate is {{ $value }} violations per second"

Create audit logging configuration

Configure audit logging to track Pod Security Standards violations and admission webhook activity.

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
  namespaces: ["default", "baseline-ns", "restricted-ns"]
  resources:
  - group: ""
    resources: ["pods"]
  omitStages:
  - RequestReceived
- level: Request
  users: ["system:serviceaccount:gatekeeper-system:gatekeeper-admin"]
  resources:
  - group: "templates.gatekeeper.sh"
  - group: "constraints.gatekeeper.sh"
- level: Violation
  annotationAuditLevels:
    pod-security.kubernetes.io/enforce-policy: "Request"
    pod-security.kubernetes.io/audit-policy: "Metadata"

Test your security policies

Test Pod Security Standards enforcement

Create test pods to verify that Pod Security Standards are properly enforced.

apiVersion: v1
kind: Pod
metadata:
  name: insecure-pod
  namespace: restricted-ns
spec:
  containers:
  - name: test
    image: nginx:1.24
    securityContext:
      runAsUser: 0  # This should be rejected in restricted namespace
# This should fail in restricted namespace
kubectl apply -f test-insecure-pod.yaml

# Create a compliant pod
cat <

Verify your setup

# Check Pod Security Standards labels
kubectl get namespaces --show-labels | grep pod-security

# Verify Gatekeeper installation
kubectl get pods -n gatekeeper-system
kubectl get constrainttemplates
kubectl get constraints

# Check constraint violations
kubectl get K8sRequiredSecurityContext must-have-security-context -o yaml
kubectl get K8sRequiredResourceLimits must-have-resource-limits -o yaml

# Review audit logs
sudo journalctl -u kubelet | grep -i "pod-security"

# Check Gatekeeper metrics
kubectl port-forward -n gatekeeper-system svc/gatekeeper-webhook-service 8443:443 &
curl -k https://localhost:8443/metrics

Common issues

SymptomCauseFix
Pod creation fails with "violates PodSecurity"Pod doesn't meet security standard requirementsAdd proper securityContext with runAsNonRoot, runAsUser, and drop capabilities
Gatekeeper constraints not enforcingTemplate not properly created or constraint misconfiguredCheck kubectl get constrainttemplates and verify Rego policy syntax
ValidatingAdmissionWebhook failsCertificate issues or webhook service unreachableVerify certificate validity and service endpoints with kubectl get svc
High violation rates in monitoringExisting workloads don't comply with new policiesGradually migrate workloads or use "warn" mode before "enforce"
System namespaces affected by policiesConstraints not properly excluding system namespacesAdd exclusions in constraint spec for kube-system, gatekeeper-system

Next steps

Automated install script

Run this to automate the entire setup

不想自己管理这些吗?

我们为依赖稳定运行时间的企业管理基础设施。全托管服务,配备一位熟悉您系统架构的固定联系人。

您将拥有一位了解您整体架构的固定联系人

Rotterdam 07:49 · 一条消息即可联系我们,无需填写工单表单