Gatekeeper 3.1: Policy as Code Goes Production

Table of Contents
Introduction
By late 2020, Gatekeeper 3.1 had matured into a production-ready policy enforcement tool for Kubernetes. With improved performance, a curated policy library, and migration tools, Gatekeeper became a viable alternative to PodSecurityPolicy and enabled teams to implement policy-as-code at scale.
This mattered because policy enforcement had become essential for multi-tenant clusters, compliance requirements, and security best practices. While PodSecurityPolicy provided basic pod security controls, it had limitations that made it difficult to use in production. Gatekeeper offered a more flexible, scalable approach that could enforce policies beyond just pod security.
Historical note: Gatekeeper 3.1 was released in May 2020, but by late 2020 it had gained significant production adoption. With PodSecurityPolicy deprecation on the horizon (announced in Kubernetes 1.21), teams began migrating to Gatekeeper as a replacement.
Gatekeeper Production Features
Performance Improvements
- Parallel Audit: Audit controller parallelizes evaluations across namespaces, reducing audit time by up to 5x.
- Caching: Improved caching reduces API server load.
- Metrics: Comprehensive metrics for monitoring policy enforcement.
- Status Reporting: Constraint status provides violation counts and remediation hints.
Policy Library
- Community Templates: Pre-built constraint templates for common use cases.
- Versioned Artifacts: Templates with semantic versioning and documentation.
- kubectl Plugin:
kubectl gatekeeperplugin for managing policies. - Migration Tools: Tools for migrating from PodSecurityPolicy to Gatekeeper.
Mutation Support (Alpha)
- Default Injection: Automatically inject defaults into resources.
- Sidecar Injection: Inject sidecars based on policies.
- Label Enforcement: Automatically add required labels.
- Safe Testing: Dry-run and audit-only modes for safe testing.
Gatekeeper vs PodSecurityPolicy
| Capability | Gatekeeper | PodSecurityPolicy |
|---|---|---|
| Policy Scope | Any Kubernetes resource | Pods only |
| Policy Language | Rego (OPA) | Kubernetes API |
| RBAC Complexity | Simplified | Complex (requires PSP binding) |
| Performance | Good (caching, parallelization) | Poor (sequential evaluation) |
| Mutation | Yes (alpha) | No |
| Audit Mode | Yes | Limited |
| Best For | Comprehensive policy enforcement | Pod security only |
Migration from PodSecurityPolicy
PSP Policy Example
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'MustRunAsNonRoot'
Equivalent Gatekeeper Constraint
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8spspsecuritycontext
spec:
crd:
spec:
names:
kind: K8sPSPSecurityContext
validation:
openAPIV3Schema:
type: object
properties:
runAsNonRoot:
type: boolean
allowPrivilegeEscalation:
type: boolean
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8spspsecuritycontext
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.securityContext.runAsNonRoot
msg := "Container must run as non-root"
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPSecurityContext
metadata:
name: must-run-as-non-root
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
runAsNonRoot: true
allowPrivilegeEscalation: false
Common Policy Patterns
Require Resource Limits
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequiredresources
spec:
crd:
spec:
names:
kind: K8sRequiredResources
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredresources
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.memory
msg := "Container must have memory limits"
}
Disallow Latest Tags
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequiredimagetag
spec:
crd:
spec:
names:
kind: K8sRequiredImageTag
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredimagetag
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
endswith(container.image, ":latest")
msg := "Container image must not use :latest tag"
}
Require Labels
apiVersion: templates.gatekeeper.sh/v1beta1
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}] {
required := input.parameters.labels[_]
not input.review.object.metadata.labels[required]
msg := sprintf("Label '%v' is required", [required])
}
Multi-Cluster Policy Management
Policy Distribution
# Policy repository structure
policies/
├── constraint-templates/
│ ├── k8s-requiredresources.yaml
│ ├── k8s-requiredlabels.yaml
│ └── k8s-pspsecuritycontext.yaml
├── constraints/
│ ├── production/
│ │ ├── resource-limits.yaml
│ │ └── security-context.yaml
│ └── staging/
│ ├── resource-limits.yaml
│ └── security-context.yaml
GitOps Integration
# ArgoCD Application for policies
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: gatekeeper-policies
spec:
source:
repoURL: https://github.com/org/policies
path: constraints/production
destination:
server: https://kubernetes.default.svc
Practical Considerations
Performance Tuning
- Audit Interval: Adjust audit interval based on cluster size and policy complexity.
- Constraint Count: Limit number of constraints to avoid performance degradation.
- Caching: Enable caching for frequently evaluated policies.
- Metrics: Monitor policy evaluation latency and adjust as needed.
Policy Testing
- Dry-Run Mode: Test policies in dry-run mode before enforcement.
- Audit Mode: Use audit mode to identify violations without blocking.
- Staging Environment: Test policies in staging before production.
Policy Maintenance
- Version Control: Store policies in Git for version control.
- Documentation: Document why each policy exists and what it enforces.
- Regular Review: Review policies regularly and remove unused policies.
Getting Started
# Install Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.1/deploy/gatekeeper.yaml
# Install constraint template
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/restricted-psp/template.yaml
# Install constraint
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper-library/master/library/pod-security-policy/restricted-psp/samples/restricted-psp/constraint.yaml
# Verify installation
kubectl get constrainttemplates
kubectl get constraints
Caveats & Lessons Learned
- Rego Learning Curve: Writing Rego policies requires learning the language.
- Policy Complexity: Complex policies can impact performance; optimize carefully.
- False Positives: Policies may block legitimate workloads; test thoroughly.
- Migration Effort: Migrating from PSP requires rewriting policies.
Common Failure Modes
- “Policy too restrictive”: Policies block legitimate workloads; adjust policies.
- “Performance degradation”: Too many constraints slow down cluster; optimize policies.
- “Policy not enforced”: Constraints not matching resources; check match criteria.
Conclusion
Gatekeeper’s production readiness in 2020 marked a turning point in Kubernetes policy enforcement. It provided a flexible, scalable alternative to PodSecurityPolicy that could enforce policies beyond just pod security. With improved performance, a curated policy library, and migration tools, Gatekeeper became the tool of choice for teams implementing policy-as-code.
For organizations with multi-tenant clusters or compliance requirements, Gatekeeper became essential for policy enforcement. It demonstrated that Kubernetes policy enforcement didn’t have to be limited to pod security—it could be comprehensive, flexible, and manageable at scale. Gatekeeper proved that policy-as-code could be both powerful and production-ready.
The patterns and practices established with Gatekeeper would influence the development of other policy engines (Kyverno, Kubewarden) and set the foundation for comprehensive policy enforcement in Kubernetes. Gatekeeper demonstrated that Kubernetes security could be both declarative and enforceable, enabling teams to codify security policies alongside application code.