Kubernetes policy engines: OPA vs. Kyverno vs. jsPolicy

Learn what features to look for in a Kubernetes policy engine.
Register or Login to like
How Kubernetes became the solution for migrating legacy applications


A Kubernetes policy engine is essential for keeping your cluster safe and ensuring policies are set correctly at the outset. For example, you probably need a policy to control who has the authority to set a privileged pod. These engines define what end users can do on the cluster and ensure that clusters can communicate. Any time a Kubernetes object is created, a policy evaluates and validates or mutates the request. Policies can apply across a namespace or different pods with a specific label in the cluster.

Kubernetes policy engines block objects that could harm or affect the cluster if they don't meet the policy's requirements. Using policies enables users to build complex configurations that other tools, such as Terraform or Ansible, cannot achieve.

The policy landscape has evolved in recent years, and the number of policy engines available continues to increase. Newer products compete against well-established tools.

This article highlights some features you should look for in a policy engine and where these three examples excel and underperform. It compares three popular open source policy engines, Open Policy Agent (OPA), Kyverno, and jsPolicy.

Policy engine features

I'll begin by listing various features so you can compare the policy engines:

  • Supported language: A policy engine must use a language supported by Kubernetes for easy management of policy resources.
  • Validation: Validation rules decide the properties with which a resource can be created. Resources are validated when they are checked against the rules and accepted.
  • Mutation: Mutation rules can modify specific resources in the cluster. These rules modify a particular object in a given way.
  • Tooling for development and testing: These tools test a set of resources against one or more policies to compare the resources against your desired results (declared in a separate file).
  • Package management: Package management handles where your rules are stored and how they are managed in the cluster.
  • Image verification: The use of policies to verify and sign container images.
  • Extensions: Custom-built functions and plugins that extend and implement functionality, like support for new protocols.
  • Metrics: Monitoring any applied changes to policies, activities related to incoming requests, and the results produced as an outcome.

Open Policy Agent (OPA)

Open Policy Agent (OPA) is an easy-to-use policy engine that can be colocated with your service and incorporated as a sidecar, host-level daemon, or library. OPA is a general-purpose engine that manages policies across several stacks, and you can utilize it for other tasks like data filtering and CI/CD pipelines.

OPA allows you to decouple your policies from your infrastructure, service, or application so that people responsible for policy management can control the policy separately from the service. You can also decouple policies from any software service you like and write content-aware policies using any context you want. Decoupling policies will help you build services at scale, improve the capacity to locate violations and conflicts, and reduce the risk of human errors.

OPA policies use a language called Rego. Rego is a query language that extends Datalog to support structured data models such as JSON. OPA provides a framework to write tests for your policies. This framework speeds up the development of new rules and reduces the time to modify existing ones. OPA can also report performance metrics at runtime. These metrics can be requested on individual API calls and are returned in line with the API response.

OPA works by making decisions on policies, not necessarily enforcing them. When a query is sent into the system, it gets passed to OPA, which then validates the query against the policies in place and makes a decision. OPA makes policy decisions by comparing the query input against policies and data. OPA and Rego are domain-agnostic, meaning you can describe any invariant in the policies. Also, policy decisions are not restricted to yes/no or allow/deny answers. Like query inputs, your policies can create structured data as an output.


Kyverno is a Kubernetes policy engine that employs a declarative management paradigm to construct policies for changing, validating, or generating resources or configurations. In contrast to OPA, which uses policy as code, you specify the code rather than write it, and Kyverno then figures out how to execute it. Kyverno uses YAML, so these policies are taken as Kubernetes resources and can be written without learning a new language. This makes it easy to view and process policy results. Kyverno outshines OPA here, as developing code in the Rego language can be difficult, especially without in-depth knowledge.

Kyverno works well with other developer tools like Git and kubectl. Validation rules are the primary use case for admission controllers like Kyverno, which makes it very easy to validate resources that respect the policy rules when creating them. Kyverno uses Cosign to verify and sign images. If the image is not found in the OCI registry or was not signed using the specified key, the policy rule will not validate it. Also, Kyverno uses Grafana to expose and collect metrics from the cluster. It simplifies and consolidates policy distribution using a container registry (OCI registry).

Kyverno works as a dynamic admission controller, receiving HTTP callbacks from the Kubernetes API server and applying matching policies to these callbacks. The policies match the resources using selectors like name, kind, and label. Kyverno uses a webhook as the controller as it handles admission review requests from the server. In the webhook, a monitor creates and manages all the required configurations. There's a generator controller that generates requests and manages the span of generated resources, and a policy controller that creates, updates, deletes, and watches policy resources, running background scans at intervals to decide what course of action to take.


jsPolicy is an open source policy engine for Kubernetes that lets users build policies using JavaScript or TypeScript. Managing policies with JavaScript is less complex and more straightforward. Due to the widespread use of the JavaScript programming language, frameworks, and numerous libraries and modules, jsPolicy is a natural choice as a policy engine tool. Kyverno and OPA are more difficult to alter and validate than jsPolicy. Its distribution uses npm packages and features a built-in JavaScript SDK for creating and packaging policies.

jsPolicy is the first policy engine to have controller policies (policies that respond to Kubernetes events). This feature lets you do something on Kubernetes events and validate or mutate them using jsPolicy. Like OPA, jsPolicy is a policy-as-code platform. However, it was created to solve the Rego language problem and provide some functionality for some features not available on Kyverno.

You can use kubectl and the Kubernetes API with jsPolicy, and every request that comes in persists in etcd. Before the requests get persisted, a webhook manager will execute the policy inside your cluster. It uses prebuilt JavaScript sandboxes in your cluster to aid policy execution, increasing efficiency and speed. A policy compiler reads the jsPolicy code and compiles it into a policy bundle, which is placed and run in the sandbox to provide policy violations. The policy violation is queried for alerting and auditing objects that violate the policy code. Since jsPolicy lets you work with JavaScript, you can use the entire JavaScript ecosystem with its great dev tools and frameworks for testing to write, test, and maintain policies.

Compare Kubernetes policy engines

The features of each policy engine differ. While they can all validate and mutate resources, they differ in other specific functions. For instance, OPA and Kyverno support extensions, but jsPolicy does not. The summary below compares the features of these three policies:

Comparing the three Kubernetes policy engines

(Joseph Eshiett, CC BY-SA 4.0)

All three of these do validation. Here are the differences.

  • OPA
    • Language: Rego
    • Mutation: Alpha
    • Development/testing: Limited
    • Package management: NA
    • Image validation: Yes
    • Extensions: Yes
    • Metrics: Prometheus
  • Kyverno
    • Language: YAML
    • Mutation: Yes
    • Development/testing: Limited
    • Package management: NA
    • Image validation: Yes
    • Extensions: Yes
    • Metrics: Grafana
  • jsPolicy
    • Language: JavaScript
    • Mutation: Yes
    • Development/testing: Extensive
    • Package management: npm
    • Image validation: No
    • Extensions: No
    • Metrics: Prometheus

Wrap up

This article discussed the concepts surrounding Kubernetes policy engines and compared three different Kubernetes policy engines: OPA, Kyverno, and jsPolicy.

Deciding which engine to use depends on your personal preference. If you'd like a more direct and simple approach, or if you're well-versed in JavaScript and TypeScript, you should use jsPolicy. But, if you prefer YAML and want to stick with working directly with Kubernetes resources, Kyverno is a good option, too.

Joseph Eshiett
Joseph Eshiett is a DevOps practitioner who is fascinated by cloud technologies, software development, and deployment processes. He is also a technical writer who enjoys documenting the processes and learning new things.
Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.