OPA Bundles and Policy Management

πŸ“– Introduction

When I started with OPA, I was loading policies directly into Gatekeeper via ConstraintTemplates applied with kubectl. That works fine for a handful of policies on a single cluster. It breaks down quickly when you have many policies, multiple clusters, or need to ensure every cluster runs the same verified policy set.

OPA Bundles solve this. A bundle is a compressed archive of Rego policies and data that OPA fetches from a remote server and applies atomically. Policies are versioned, distributed, and updated without restarting OPA. This article covers the bundle format, serving bundles, and the workflow for managing policies at scale.


πŸ“¦ What Is an OPA Bundle?

A bundle is a .tar.gz archive containing:

bundle/
β”œβ”€β”€ .manifest          # bundle metadata (revision, roots)
β”œβ”€β”€ policies/
β”‚   β”œβ”€β”€ pod-security.rego
β”‚   β”œβ”€β”€ image-registry.rego
β”‚   └── resource-limits.rego
└── data/
    └── config.json    # data document loaded alongside policies

OPA fetches the bundle from a configured URL, validates it, atomically replaces the in-memory policy store, and begins evaluating against the new policies β€” without a restart.


πŸ—‚οΈ Bundle Manifest File

The .manifest file at the bundle root declares metadata:

Field
Purpose

revision

Identifies the bundle version. OPA reports this in status and logs.

roots

Data/policy paths this bundle owns. OPA won't accept conflicting bundles for the same root.

metadata

Optional β€” can include minimum OPA version requirements.


πŸ—οΈ Building a Bundle

Directory Structure

approved-registries.json:

k8s/image-registry.rego:

Notice data.approved_registries.registries β€” the policy reads from the data file loaded in the same bundle, rather than hardcoding registry values in the policy itself. Policy logic and configuration are separated.

Build the Bundle

Inspect the built bundle:


πŸ–₯️ Bundle Server Options

OPA can pull bundles from any HTTP server that serves files. Common options in practice:

Option 1: Nginx (Simplest)

Option 2: Object Storage (S3 / GCS)

OPA has native support for S3-compatible storage:

Option 3: OCI Registry

Since OPA v0.44, bundles can be stored in OCI-compliant container registries:

This integrates naturally with existing registry infrastructure and promotion workflows.


βš™οΈ Configuring OPA to Use Bundles

In a standalone OPA server, the config file:

For Gatekeeper

Gatekeeper uses a slightly different bundle mechanism via the externalData feature and the native ConstraintTemplate mechanism. For raw OPA deployments (non-Gatekeeper), the config above applies directly.


πŸ”„ Bundle Update Workflow

With bundles, the policy deployment workflow becomes:

spinner

Policy updates go through the same review and CI process as application code. No kubectl apply needed per cluster. Every OPA instance pulls the authoritative bundle from the registry.


🏷️ Bundle Versioning Strategy

A practical versioning approach:

  • Production clusters pin to a specific version

  • Staging can track latest

  • Rollback is just pointing the cluster config back to a previous version


πŸ“Š Monitoring Bundle Status

OPA exposes bundle status via its status API:

Alert if:

  • last_successful_download is stale (bundle server unreachable)

  • active_revision differs from expected version (bundle not updating)

  • Status shows bundle_load_or_save_error (policy compilation error in new bundle)


🧭 What's Next

Policies need tests just as much as application code. The next article covers the OPA test framework β€” unit tests in Rego, table-driven tests, and how Conftest extends this to CI/CD pipelines.

Next: Article 07 β€” Testing OPA Policies


πŸ“Ž References

Last updated