What Is OPA Gatekeeper in Kubernetes?
OPA Gatekeeper is a Kubernetes-native policy engine that uses a validating admission webhook to enforce custom policies written in Rego. It provides constraint templates for reusable policy definitions and constraints for applying them to specific resources.
Detailed Answer
OPA Gatekeeper brings the Open Policy Agent (OPA) to Kubernetes as a native admission controller. It intercepts API requests and evaluates them against policies you define, blocking requests that violate your rules.
Architecture
kubectl apply → API Server → Gatekeeper Webhook → Policy Decision
↓
ConstraintTemplates (Rego logic)
Constraints (parameters + targets)
↓
Allow / Deny + Reason
Installation
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
# Verify installation
kubectl get pods -n gatekeeper-system
kubectl get crd | grep gatekeeper
ConstraintTemplate: Define the Policy
A ConstraintTemplate defines reusable policy logic in Rego:
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg, "details": {"missing_labels": missing}}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
Constraint: Apply the Policy
A Constraint instantiates a template with specific parameters:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
enforcementAction: deny
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
- apiGroups: ["apps"]
kinds: ["Deployment"]
excludedNamespaces:
- kube-system
- gatekeeper-system
parameters:
labels:
- "team"
- "environment"
Now any Deployment or Namespace without team and environment labels is rejected:
kubectl create deployment nginx --image=nginx
# Error: admission webhook denied the request:
# Missing required labels: {"environment", "team"}
Common Policy Examples
Deny Privileged Containers
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sdenyprivileged
spec:
crd:
spec:
names:
kind: K8sDenyPrivileged
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdenyprivileged
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged == true
msg := sprintf("Privileged container not allowed: %v", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[_]
container.securityContext.privileged == true
msg := sprintf("Privileged init container not allowed: %v", [container.name])
}
Enforce Resource Limits
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequireresourcelimits
spec:
crd:
spec:
names:
kind: K8sRequireResourceLimits
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequireresourcelimits
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.cpu
msg := sprintf("Container %v must have CPU limits", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.memory
msg := sprintf("Container %v must have memory limits", [container.name])
}
Restrict Image Registries
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sallowedrepos
spec:
crd:
spec:
names:
kind: K8sAllowedRepos
validation:
openAPIV3Schema:
type: object
properties:
repos:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedrepos
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not startswith(container.image, input.parameters.repos[_])
msg := sprintf("Container %v uses image %v which is not from an allowed registry", [container.name, container.image])
}
Enforcement Actions
| Action | Behavior |
|--------|----------|
| deny | Reject the request |
| dryrun | Allow the request but log the violation |
| warn | Allow but return a warning to the user |
Start with dryrun to understand impact before switching to deny:
spec:
enforcementAction: dryrun
Audit Mode
Gatekeeper periodically audits existing resources against all constraints:
# View audit violations
kubectl get k8srequiredlabels require-team-label -o yaml
# status.violations lists all existing resources that violate the policy
kubectl get constraint -o json | jq '.items[].status.violations'
Gatekeeper vs. Kyverno
| Feature | Gatekeeper | Kyverno | |---------|-----------|---------| | Policy language | Rego | YAML | | Learning curve | Steep | Low | | Mutation support | Limited (alpha) | Full | | Generation (create resources) | No | Yes | | Audit existing resources | Yes | Yes | | CNCF status | Graduated (OPA) | Graduated |
Best Practices
- Start with dryrun — deploy all constraints in dryrun mode first to assess impact
- Exclude system namespaces — always exclude kube-system and gatekeeper-system
- Use the Gatekeeper library — the gatekeeper-library repo contains pre-built ConstraintTemplates
- Monitor webhook latency — Gatekeeper adds latency to API requests
- Set failurePolicy carefully —
Failblocks all requests if Gatekeeper is down,Ignorebypasses policy
Why Interviewers Ask This
Policy enforcement is critical for multi-tenant clusters and compliance. This question tests your ability to implement guardrails that prevent misconfigurations before they reach production.
Common Follow-Up Questions
Key Takeaways
- Gatekeeper enforces policies as a validating admission webhook — violations are blocked before reaching etcd.
- ConstraintTemplates define reusable policy logic; Constraints apply them to specific resources.
- The audit feature detects policy violations in existing resources, not just new requests.