Policy as Code with OPA: A Practical Guide for SMB Kubernetes Security and Compliance in 2026

Policy as Code with OPA: A Practical Guide for SMB Kubernetes Security and Compliance in 2026

What Is Policy as Code?

Policy as Code (PaC) is the practice of defining and enforcing rules for your infrastructure and applications using code — rather than manual processes, spreadsheets, or wiki pages. Instead of asking “Did the security team approve this change?”, you let your pipeline automatically check: “Does this deployment satisfy our defined policies?”

For SMBs running Kubernetes, PaC is no longer optional. Between SOC 2 compliance, GDPR requirements, and the sheer complexity of cloud-native environments, manual policy enforcement simply doesn’t scale. Enter Open Policy Agent (OPA) — the CNCF-graduated project that has become the de facto standard for policy enforcement in cloud-native stacks, adopted by companies like Netflix, Goldman Sachs, and Atlassian, but equally powerful for SMBs with 10–200 employees.

Why OPA Matters for SMBs in 2026

In 2026, the Kubernetes ecosystem has matured significantly. But with that maturity comes complexity:

  • Average SMB K8s cluster runs 15+ microservices across 3+ namespaces
  • Developers need self-service access, but security must be maintained
  • Compliance frameworks (SOC 2, ISO 27001, PCI-DSS) require audit trails
  • Cloud costs spiral when unapproved resource types are deployed
  • Multi-team environments need clear separation of concerns

OPA solves these problems by letting you write policies as Rego code — a declarative query language purpose-built for policy enforcement. Unlike traditional firewall rules or manually maintained configuration management databases (CMDBs), OPA policies are version-controlled, testable, and automatically enforced at every stage of your deployment pipeline.

How OPA Works with Kubernetes: Gatekeeper

Gatekeeper is the Kubernetes-specific implementation of OPA. It acts as an admission controller — intercepting API requests before resources are created and checking them against your policies. Gatekeeper implements the OPA Constraint Framework, which provides a structured way to define and manage policies across your cluster.

# Install Gatekeeper on your cluster
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml

# Verify installation
kubectl get pods -n gatekeeper-system
# Expected: gatekeeper-controller-manager, gatekeeper-audit

Once installed, Gatekeeper runs in two modes:

  • Synchronous admission control: Blocks non-compliant resources at creation time
  • Audit mode: Periodically scans existing resources and reports violations without blocking

Writing Your First Rego Policy

Let’s write a policy that prevents deploying containers running as root — a common security best practice and a requirement for SOC 2 compliance:

# constraint_template.yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8scontainernoprivileged
spec:
  crd:
    spec:
      names:
        kind: K8sContainerNoPrivileged
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8scontainernoprivileged

        violation[{"msg": msg}] {
          container := input.review.object.spec.containers[_]
          container.securityContext.privileged == true
          msg := sprintf("Container '%v' is running with privileged access. SMB security policy disallows this.", [container.name])
        }

        # Also check init containers
        violation[{"msg": msg}] {
          container := input.review.object.spec.initContainers[_]
          container.securityContext.privileged == true
          msg := sprintf("Init container '%v' is running with privileged access.", [container.name])
        }

Then apply it as a constraint to the production namespace only:

# constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sContainerNoPrivileged
metadata:
  name: no-privileged-containers
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "production"
  parameters: {}

Now any attempt to create a privileged pod in production gets automatically rejected with a clear, actionable error message. Your developers know exactly what to fix without needing to open a ticket.

Practical Policies for SMBs

Here are three policies every SMB should implement on day one:

1. Resource Quota Enforcement

Prevent resource abuse by ensuring every container has CPU and memory limits:

package k8srequiredresources

violation[{"msg": msg}] {
  container := input.review.object.spec.containers[_]
  not container.resources.limits
  msg := sprintf("Container '%v' has no resource limits set. Please define CPU and memory limits for cost control.", [container.name])
}

violation[{"msg": msg}] {
  container := input.review.object.spec.containers[_]
  container.resources.limits.memory == "0"  # Catches zero-value limits
  msg := sprintf("Container '%v' has explicit zero memory limit. This bypasses quota enforcement.", [container.name])
}

2. Disallowed Image Registries

Only allow images from your approved registries — critical for supply chain security:

package k8sallowedrepos

# List of approved registries
approved_registries = {
  "docker.io/your-org",
  "gcr.io/your-org",
  "ghcr.io/your-org",
}

violation[{"msg": msg}] {
  container := input.review.object.spec.containers[_]
  registry := approved_registries[_]
  not startswith(container.image, registry)
  msg := sprintf("Container '%v' uses unapproved image registry: %v. Allowed: your-org on Docker Hub, GCR, or GHCR.", [container.name, container.image])
}

3. Enforce Labels for Cost Tracking

Ensure every namespace has proper cost-tracking labels — essential for FinOps:

package k8srequiredlabels

required_labels = {"cost-center", "environment", "team"}

violation[{"msg": msg}] {
  metadata := input.review.object.metadata
  required_labels[_] != label
  label := metadata.labels[_]
  # This is intentionally broad - use with match conditions
}

violation[{"msg": msg}] {
  metadata := input.review.object.metadata
  label := required_labels[_]
  not metadata.labels[label]
  msg := sprintf("Namespace '%v' is missing required label '%v'. All namespaces must have cost-center, environment, and team labels for FinOps tracking.", [metadata.name, label])
}

Testing OPA Policies Locally

Before deploying policies to your cluster, test them locally using the OPA CLI. This saves hours of debugging in production:

# Install OPA (one-time)
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64
chmod +x ./opa
sudo mv opa /usr/local/bin/

# Create a mock input
cat > mock-pod.json << 'EOF'
{
  "review": {
    "object": {
      "metadata": {"name": "test-pod"},
      "spec": {
        "containers": [{
          "name": "app",
          "image": "docker.io/your-org/app:latest",
          "securityContext": {"privileged": true}
        }]
      }
    }
  }
}
EOF

# Test the policy
opa eval --data policy.rego --input mock-pod.json "data"

# Run all tests in a directory
opa test ./policies/ --verbose

The OPA test framework supports mocking and assertions, enabling full test-driven development for your infrastructure policies.

OPA Beyond Kubernetes: CI/CD and API Gateways

OPA isn't limited to Kubernetes. You can integrate it with your entire DevOps toolchain:

  • CI/CD pipelines: Gate deployments based on compliance checks. Run OPA evaluations as a step in your GitHub Actions or GitLab CI pipelines to block non-compliant Terraform plans or Docker images.
  • API gateways (Kong, Envoy): Enforce authentication, rate-limiting, and authorization policies at the edge. OPA can make real-time decisions on every API request.
  • Terraform/OpenTofu: Validate infrastructure changes before apply. Feed JSON plans into OPA to check security group rules, IAM policies, and resource configurations.
  • SSH and session management: Control access to production servers based on dynamic policies like time of day, user role, or recent activity.
# Example: OPA policy check in a GitHub Actions CI pipeline
- name: Validate Terraform with OPA
  run: |
    tofu plan -out=plan.tfplan
    tofu show -json plan.tfplan > plan.json
    opa eval --data policies/ --input plan.json "data.terraform.deny"
  # Pipeline fails with non-zero exit code if violations found

OPA vs Kyverno: Which Should You Choose?

In 2026, two main policy engines dominate the Kubernetes ecosystem: OPA/Gatekeeper and Kyverno. Here's a quick comparison for SMBs:

  • OPA/Gatekeeper: Uses Rego language. Steeper learning curve but more powerful. Works beyond Kubernetes — integrates with CI/CD, APIs, SSH. Best if you need a unified policy engine across your stack.
  • Kyverno: Uses YAML-based policies. Easier to learn (no new language). Kubernetes-native only. Best if you want to write policies quickly and don't need multi-platform enforcement.

For most SMBs just starting with Policy as Code, we recommend starting with Kyverno for simplicity, then migrating to OPA/Gatekeeper as your policy needs grow and you need cross-platform enforcement.

Internal Links

For more on securing your DevOps pipeline, read our guide on DevSecOps for SMBs: Automating Security in Your CI/CD Pipeline. If you're setting up Kubernetes for the first time, check out Kubernetes vs Serverless in 2026. For secrets management, see Your Secrets Management Is a Breach Waiting to Happen.

Building a Compliance-First Culture

Policy as Code isn't just about tooling — it's about shifting your team's mindset from "security is a blocker" to "security is automated." By codifying your policies, you:

  • Reduce review time from days to milliseconds — policies are enforced automatically at every deployment
  • Create auditable evidence for compliance frameworks — every policy evaluation is logged and timestamped
  • Empower developers to self-serve within safe boundaries — they get immediate feedback on violations with actionable error messages
  • Catch violations before they reach production — prevention is always cheaper than remediation
  • Scale your security practices without scaling your security team — one OPA policy can protect hundreds of services

Take the Next Step

Ready to implement Policy as Code in your organization? At DevOps & SRE Hub, we help SMBs design and enforce cloud-native security policies — from OPA/Gatekeeper setup to full compliance automation. We provide hands-on workshops, starter policy libraries, and ongoing consulting to ensure your policies stay effective as your infrastructure evolves. Book your free consultation today and let's make your infrastructure secure by default.

en_GBEnglish
Scroll to Top