Implement Kubernetes admission controllers with OPA Gatekeeper for policy enforcement

Advanced 45 min Apr 02, 2026 13 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up OPA Gatekeeper admission controllers to enforce security policies, resource governance, and compliance rules across your Kubernetes cluster with custom constraint templates.

Prerequisites

  • Kubernetes cluster with admin access
  • kubectl installed and configured
  • Basic understanding of YAML and Kubernetes resources

What this solves

OPA Gatekeeper provides policy-as-code enforcement for Kubernetes clusters through admission controllers that validate and mutate resources before they're created. This tutorial shows you how to implement comprehensive policy enforcement including security controls, resource limits, and compliance requirements using constraint templates and custom policies.

Step-by-step installation

Update system packages and install kubectl

Start by ensuring your system has the latest packages and kubectl installed for cluster management.

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget apt-transport-https ca-certificates gnupg
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
sudo dnf update -y
sudo dnf install -y curl wget ca-certificates
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

Verify Kubernetes cluster access

Confirm you have administrative access to your Kubernetes cluster before installing Gatekeeper.

kubectl cluster-info
kubectl auth can-i '' '' --all-namespaces
Note: You need cluster-admin privileges to install admission controllers. If you don't have a cluster yet, follow our Kubernetes installation guide.

Install OPA Gatekeeper

Deploy Gatekeeper using the official release manifests which include all necessary CRDs, RBAC, and admission controller components.

kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.14/deploy/gatekeeper.yaml

Wait for Gatekeeper components to start

Monitor the deployment until all Gatekeeper pods are running and the admission controller webhook is ready.

kubectl wait --for=condition=ready pod -l gatekeeper.sh/operation=webhook -n gatekeeper-system --timeout=120s
kubectl get pods -n gatekeeper-system
kubectl get validatingadmissionwebhooks.admissionregistration.k8s.io

Create constraint template for required labels

Define a reusable constraint template that enforces required labels on resources. This template uses Rego language for policy logic.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        type: object
        properties:
          labels:
            type: array
            items:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        
        violation[{"msg": msg}] {
          required := input.parameters.labels
          provided := input.review.object.metadata.labels
          missing := required[_]
          not provided[missing]
          msg := sprintf("Missing required label: %v", [missing])
        }

Apply the constraint template

Install the constraint template to make it available for creating specific policy constraints.

kubectl apply -f required-labels-template.yaml
kubectl get constrainttemplates

Create a constraint for environment labeling

Use the template to create a specific constraint that requires pods to have environment and team labels.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: pod-must-have-env
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system", "gatekeeper-system", "kube-public", "kube-node-lease"]
  parameters:
    labels: ["environment", "team"]

Apply the pod labeling constraint

Install the constraint to start enforcing required labels on new pod deployments.

kubectl apply -f require-pod-labels.yaml
kubectl get k8srequiredlabels

Create security policy constraint template

Define a template for container security policies that prevents privileged containers and enforces security contexts.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8ssecuritypolicy
spec:
  crd:
    spec:
      names:
        kind: K8sSecurityPolicy
      validation:
        type: object
        properties:
          allowPrivileged:
            type: boolean
          requiredSecurityContext:
            type: boolean
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8ssecuritypolicy
        
        violation[{"msg": msg}] {
          not input.parameters.allowPrivileged
          container := input.review.object.spec.containers[_]
          container.securityContext.privileged == true
          msg := "Privileged containers are not allowed"
        }
        
        violation[{"msg": msg}] {
          input.parameters.requiredSecurityContext
          container := input.review.object.spec.containers[_]
          not container.securityContext
          msg := "Containers must define securityContext"
        }
        
        violation[{"msg": msg}] {
          input.parameters.requiredSecurityContext
          container := input.review.object.spec.containers[_]
          not container.securityContext.runAsNonRoot
          msg := "Containers must run as non-root user"
        }

Apply security policy template and constraint

Install the security template and create a constraint that enforces container security best practices.

kubectl apply -f security-policy-template.yaml

cat << 'EOF' > security-constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sSecurityPolicy
metadata:
  name: container-security-policy
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
    excludedNamespaces: ["kube-system", "gatekeeper-system"]
  parameters:
    allowPrivileged: false
    requiredSecurityContext: true
EOF

kubectl apply -f security-constraint.yaml

Create resource limits constraint template

Define a template that enforces CPU and memory limits on containers to prevent resource starvation.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sresourcelimits
spec:
  crd:
    spec:
      names:
        kind: K8sResourceLimits
      validation:
        type: object
        properties:
          maxCpu:
            type: string
          maxMemory:
            type: string
          requireLimits:
            type: boolean
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sresourcelimits
        
        violation[{"msg": msg}] {
          input.parameters.requireLimits
          container := input.review.object.spec.containers[_]
          not container.resources.limits
          msg := sprintf("Container %v missing resource limits", [container.name])
        }
        
        violation[{"msg": msg}] {
          input.parameters.requireLimits
          container := input.review.object.spec.containers[_]
          not container.resources.limits.cpu
          msg := sprintf("Container %v missing CPU limit", [container.name])
        }
        
        violation[{"msg": msg}] {
          input.parameters.requireLimits
          container := input.review.object.spec.containers[_]
          not container.resources.limits.memory
          msg := sprintf("Container %v missing memory limit", [container.name])
        }

Apply resource limits policies

Install the resource template and create constraints that enforce resource limits on all workloads.

kubectl apply -f resource-limits-template.yaml

cat << 'EOF' > resource-limits-constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sResourceLimits
metadata:
  name: container-resource-limits
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
      - apiGroups: ["apps"]
        kinds: ["Deployment", "StatefulSet", "DaemonSet"]
    excludedNamespaces: ["kube-system", "gatekeeper-system"]
  parameters:
    maxCpu: "2"
    maxMemory: "4Gi"
    requireLimits: true
EOF

kubectl apply -f resource-limits-constraint.yaml

Configure constraint violation monitoring

Set up monitoring for policy violations to track compliance and identify problematic deployments.

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: gatekeeper-system
spec:
  match:
    - excludedNamespaces: ["kube-system", "gatekeeper-system"]
      processes: ["*"]
  validation:
    traces:
      - user:
          kind:
            group: "*"
            version: "*"
            kind: "*"
  readiness:
    statsEnabled: true

Apply monitoring configuration

Enable violation tracking and readiness monitoring to observe Gatekeeper's policy enforcement.

kubectl apply -f monitoring-config.yaml
kubectl get config -n gatekeeper-system

Verify your setup

Test your Gatekeeper installation by attempting to create pods that violate the configured policies.

# Check Gatekeeper status
kubectl get pods -n gatekeeper-system
kubectl get constrainttemplates
kubectl get constraints

Test label enforcement (this should fail)

kubectl run test-pod --image=nginx --restart=Never

Test with required labels (this should succeed)

kubectl run test-pod-labeled --image=nginx --restart=Never --labels="environment=test,team=platform"

Test security policy (this should fail)

kubectl run privileged-test --image=nginx --restart=Never --labels="environment=test,team=platform" -- /bin/sh -c "sleep 3600" --privileged

Check constraint violations

kubectl get k8srequiredlabels pod-must-have-env -o yaml kubectl get k8ssecuritypolicy container-security-policy -o yaml

Monitor and troubleshoot policy violations

View constraint status and violations

Monitor policy enforcement by checking constraint status and violation details.

# Check all constraint violations
kubectl get constraints -o json | jq '.items[] | {name: .metadata.name, violations: .status.violations}'

View specific constraint details

kubectl describe k8srequiredlabels pod-must-have-env

Check Gatekeeper audit logs

kubectl logs -n gatekeeper-system -l control-plane=audit-controller kubectl logs -n gatekeeper-system -l control-plane=controller-manager

Set up Prometheus monitoring integration

Configure Prometheus to scrape Gatekeeper metrics for comprehensive policy monitoring.

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: gatekeeper-controller-manager-metrics
  namespace: gatekeeper-system
spec:
  endpoints:
  - path: /metrics
    port: metrics
    interval: 30s
  selector:
    matchLabels:
      control-plane: controller-manager
      gatekeeper.sh/operation: webhook

Create policy exception configurations

Configure exceptions for system namespaces or specific workloads that need policy exemptions.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: pod-labels-with-exceptions
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    excludedNamespaces: ["kube-system", "gatekeeper-system", "monitoring"]
  parameters:
    labels: ["environment", "team"]
  exemptions:
    - name: "system-pods"
      subjects:
        - kind: "Pod"
          name: "coredns-*"
          namespace: "kube-system"

For comprehensive cluster monitoring including Gatekeeper metrics, check our Prometheus and Grafana monitoring guide. You can also integrate with service mesh security using Istio security policies.

Common issues

SymptomCauseFix
Webhook timeout errorsGatekeeper pods not readykubectl wait --for=condition=ready pod -l gatekeeper.sh/operation=webhook -n gatekeeper-system
Constraint template validation failsInvalid Rego syntaxTest Rego policy at play.openpolicyagent.org before applying
Policies blocking system podsMissing namespace exclusionsAdd excludedNamespaces: ["kube-system", "gatekeeper-system"] to constraints
No violation data in constraint statusAudit disabledCheck Config resource and enable audit: kubectl get config -n gatekeeper-system
Deployment blocked by security policyMissing securityContextAdd securityContext: {runAsNonRoot: true, runAsUser: 1000} to container specs

Next steps

Automated install script

Run this to automate the entire setup

#opa-gatekeeper #kubernetes #admission-controllers #policy-enforcement #security-policies

Need help?

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.

Talk to an engineer