TecLeads TecLeads Blog
2026-07-27 · 6 min read

OPA and Kyverno Without Breaking Your Cluster

Workstation with two monitors showing source code
devsecopskubernetespolicy-as-codecontainer-securitysupply-chain-security

I have seen Kubernetes clusters stop accepting perfectly valid deployments because somebody enabled a new admission policy in production and discovered, rather late, that half the workloads violated it. The policy was technically correct. The rollout was not.

That distinction matters. Policy as code is not mainly a language choice between Rego and YAML. It is a way to turn security requirements into tested, reviewable controls without making the API server your first test environment.

OPA and Kyverno can both do the job. Start with one small policy, run it in CI, measure existing violations, then enforce it. Anything more ambitious on day one usually produces an impressive pile of exceptions.

Pick the tool based on where the decision lives

OPA is a general policy engine. It evaluates structured input against policies written in Rego, whether that input comes from Kubernetes, Terraform, an API gateway, or an application. For Kubernetes admission, OPA recommends Gatekeeper, which adds constraints, reusable templates, and auditing.

Choose OPA when the same decision model needs to work beyond Kubernetes, or when your platform team already maintains Rego. It is particularly useful when policies need richer logic, shared data, or consistent evaluation across infrastructure and application boundaries.

Kyverno is the shorter route when your immediate problem is Kubernetes. Policies are Kubernetes resources, matching uses familiar API groups and kinds, and the CLI can evaluate them before anything reaches a cluster. Current Kyverno releases provide CEL-based ValidatingPolicy and ImageValidatingPolicy resources. Older examples built around ClusterPolicy still exist everywhere, but those legacy types are deprecated in Kyverno 1.18. Do not begin a fresh policy library by copying old manifests without checking the version.

My default is Kyverno for a Kubernetes-only platform and OPA when policy is a shared service across several systems. Running both is possible. Running both without clear ownership is how teams end up debugging two denial messages for the same Pod.

Begin with a boring rule

Blocking privileged containers sounds security-focused, but it immediately collides with networking, storage, monitoring, and assorted vendor agents. Start with something developers can fix without an architecture meeting, such as banning the latest image tag.

Here is the core decision in Rego for a Deployment manifest:

package tecleads.kubernetes

import rego.v1

deny contains message if {
 some container in input.spec.template.spec.containers
 endswith(container.image, ":latest")
 message := sprintf("container %q uses the latest tag", [container.name])
}

Run it locally or in CI:

yq -o=json deployment.yaml > deployment.json
opa test policies/ -v --fail-on-empty
opa eval \
 --data policies/no_latest.rego \
 --input deployment.json \
 --fail-defined \
 'data.tecleads.kubernetes.deny'

The test command matters more than the first policy. Add cases for compliant input, rejected input, missing fields, init containers, and whatever exemptions you permit. A policy repository without tests is just production logic wearing a YAML costume.

The Kyverno equivalent can start in audit mode:

apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
 name: disallow-latest-tag
spec:
 validationActions: [Audit]
 matchConstraints:
 resourceRules:
 - apiGroups: ['']
 apiVersions: [v1]
 operations: [CREATE, UPDATE]
 resources: [pods]
 validations:
 - expression: >-
 object.spec.containers.all(container,
 !container.image.endsWith(':latest'))
 message: Images must use an explicit tag or digest.

Audit mode allows the request and records the result. Kyverno policy reports describe the current cluster state, including failures found by background scans. They are useful rollout evidence, but they are not a historical record of blocked requests. Keep admission metrics, events, and controller logs if you need that history.

Before committing, exercise the policy against representative manifests:

kyverno apply policies/disallow-latest.yaml \
 --resource manifests/ \
 --audit-warn

kyverno test policy-tests/ --detailed-results

CI is the first enforcement point

A developer should learn that a manifest violates policy while looking at a pull request, not while watching a deployment time out. Put the same policy bundle used by admission control into the repository, pin the tool version, and make policy tests part of the normal pipeline.

Keep three things together:

This fits naturally beside the rest of a DevSecOps pipeline. SAST finds unsafe code patterns. SCA checks dependencies. Secret scanning catches credentials. IaC policy checks cloud changes. Image scanning and container hardening inspect what will actually run. Admission policy is the last gate, not a substitute for those earlier checks.

If admission is the first place a team encounters a rule, feedback is late and the platform becomes the villain. That is an operating model failure, not a developer education problem.

Move from visibility to denial carefully

Run the policy against stored manifests first. Then enable audit in a non-production cluster. After that, audit production and inspect every failure by workload owner and namespace.

Do not switch to denial until you know which violations are genuine defects, which are system workloads, and which expose a badly written rule. Exclude platform namespaces explicitly. Use narrow, time-bounded exceptions with an owner and reason. An undocumented namespace exclusion is not an exception process. It is a bypass somebody will forget.

Also decide what happens when the admission controller is unavailable. A fail-closed policy protects the control but can block deployments during an outage. A fail-open policy preserves availability but allows unvalidated changes. For policies protecting high-risk production workloads, I prefer fail closed after the webhook has proven stable and is monitored. For an early audit rollout, fail open is usually the sensible setting.

Watch admission latency, error rates, webhook availability, and policy evaluation failures. The denial message must name the offending field and the expected fix. Policy failed is technically a message, much like smoke is technically an observability system.

Supply chain controls come after identity

Once basic manifest checks are dependable, connect admission to the software supply chain. Require immutable image digests. Verify signatures produced by an approved build identity. Then verify attestations for provenance, vulnerability scanning, or an SBOM.

Kyverno's ImageValidatingPolicy can verify Cosign or Notary signatures and inspect signed attestations. It can also validate that an attached SBOM uses an expected format. That is useful container security, provided the identity rule is specific. Trusting any signature issued by a broad identity range proves very little.

An SBOM alone does not say an image is safe. It says what the producer claims is inside. Bind it to the image digest, verify who produced the attestation, and make the admission decision against that evidence. Compliance teams get traceable controls. Operators get a concrete answer to the question, “Why was this image allowed?”

If you only do one thing this week

Put one admission rule into a repository with one passing fixture, one failing fixture, and a CI command that developers can run locally. Keep it in audit mode in the cluster until you have reviewed the violations with the people who own the workloads.

That small loop, write, test, observe, enforce, is the foundation. The clever Rego and supply chain attestations can wait until the team trusts the machinery.


If this is on your plate, TecLeads does exactly this as part of our DevSecOps work. If you'd like a second pair of eyes on your setup, book a 30-minute call or explore what we do.

📍 Tech Pulse · today's quick question 🟢 Level: Basic DevSecOps

What does shift-left security mean?

Pick an answer to see how other engineers voted.

Want a hand with this?

TecLeads helps engineering teams ship faster and more securely.

Book a 30-minute call

← All posts