Writing Kubernetes Admission Policies

πŸ“– Introduction

This is the article I wish I'd had when I started writing Kubernetes policies. The conceptual foundation is important, but most of what you actually need is practical: how do I enforce image registry restrictions? How do I require labels? How do I stop people from using latest tags? What does the admission input actually look like?

This article covers the most common Kubernetes admission policies, written in Rego for OPA Gatekeeper. Each policy comes with the ConstraintTemplate, a Constraint example, and notes on edge cases.


πŸ—‚οΈ The Admission Review Input Shape

Before writing policies, you need to know what input contains inside a Gatekeeper Rego policy:

{
  "review": {
    "operation": "CREATE",
    "kind": {
      "group": "apps",
      "version": "v1",
      "kind": "Deployment"
    },
    "object": {
      // the Kubernetes resource being created/updated
    },
    "oldObject": {
      // previous version (for UPDATE operations)
    },
    "userInfo": {
      "username": "system:serviceaccount:ci:deployer",
      "groups": ["system:serviceaccounts"]
    }
  },
  "parameters": {
    // values from the Constraint instance
  }
}

Most policies operate on input.review.object β€” the resource itself. For debugging, the OPA Playground is useful: paste in a real Kubernetes YAML converted to JSON and test your policy interactively.


🧱 Policy 1: Required Labels

Enforce that specific labels exist on resources. In multi-team clusters, labels like team, app, and environment are required for cost allocation and incident response.

ConstraintTemplate:

Constraint:

Test:


πŸ–ΌοΈ Policy 2: Approved Image Registries

One of the first policies I deployed on a shared cluster. Prevents workloads from pulling from arbitrary public registries and pulling unvetted images.

ConstraintTemplate:

Constraint:


🏷️ Policy 3: No Latest Tag

The latest tag is mutable β€” what an image resolves to can change between deployments, making rollbacks unreliable and behavior unpredictable.

ConstraintTemplate:

Constraint:


πŸ” Policy 4: Pod Security β€” No Root Containers

Containers running as UID 0 have elevated privileges inside the container. This policy enforces non-root execution.

ConstraintTemplate:

Constraint:


πŸ“Š Policy 5: Resource Limits Required

Workloads without resource limits can starve neighbors on a shared cluster. This policy enforces that every container declares CPU and memory limits.

ConstraintTemplate:

Constraint:


🌐 Policy 6: Disallow HostNetwork

Pods with hostNetwork: true bypass network isolation and can see all host-level network traffic. It should be restricted to a small set of system workloads.

ConstraintTemplate:

Constraint:


πŸ”¬ Debugging Policies

When a policy isn't behaving as expected, the most useful debugging workflow:

1. Check audit violations

2. Test the Rego logic directly

Extract the input from a real resource:

Then test against your policy file:

3. Use dryrun enforcement

Switch a constraint to enforcementAction: dryrun, apply it, and check status violations without blocking real traffic:


πŸ“ Gatekeeper Library

The Gatekeeper Libraryarrow-up-right project maintains a collection of production-ready ConstraintTemplates. Before writing a policy from scratch, it's worth checking if a tested version already exists there.

Common library policies: K8sRequiredLabels, K8sAllowedRepos, K8sNoPrivilegedContainers, K8sResourceLimits, K8sRequiredProbes.


🧭 What's Next

You now have a working library of Kubernetes policies. The next article covers how to manage and distribute policies at scale β€” OPA bundles, versioning, and the bundle server pattern.

Next: Article 06 β€” OPA Bundles and Policy Management


πŸ“Ž References

Last updated