Gatekeeper vs Kyverno
Gatekeeper is a general-purpose policy engine based on Open Policy Agent (OPA). It allows you to define and enforce custom policies across various Kubernetes resources.
Kyverno is specifically designed for Kubernetes policy management. It focuses on validating and mutating resources in Kubernetes to enforce desired configurations and security policies.
Small Comparison of both tools that gives you a clear picture,
Gatekeeper | Kyverno |
It acts as an admission controller which means it evaluates policies during the admission of resources | It is built using Custom Resource Definitions (CRDs) and operates as a validating and mutating webhook. |
It uses the powerful Rego language, part of the OPA project, for defining policies | It uses a YAML or JSON-based declarative policy language that is easier to read and write for many users |
Users should have prior knowledge to understand and write rego policies | Users are familiar with Kubernetes YAML or JSON which makes it easier to write policies |
It does not provide built-in policies out of the box, but there are community-contributed policies available to get started | Kyverno comes with a set of built-in policies and examples that cover common use cases |
It is more extensible and can be used to enforce policy beyond Kubernetes since it’s general-purpose nature | Its primary focus is Kubernetes, making it highly optimised for handling Kubernetes resources and scenarios |
Key Points that you don’t miss!!
Gatekeeper is a general-purpose open policy agent whereas Kyverno is specifically designed for Kubernetes
Gatekeeper supports only validating webhooks but Kyverno supports validating, mutating, generating and image verification webhooks
Gatekeeper makes you feel complex for writing a simple policy but Kyverno is easier to implement
Some complex requirement to write custom policies in Kyverno is difficult where rego plays in the background of the OPA gatekeeper makes possible to solve those requirements
Kyverno is a straightforward method for the implementation of policies but in the case of gatekeeper we need to create the CRDs like templates and constraints
Implementation of Gatekeeper
Installation: Gatekeeper supports three methods of installation.
Install using releases to deploy:
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
Deploy using Helm:
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace
Deploy HEAD using make:
git clone https://github.com/open-policy-agent/gatekeeper.git export DESTINATION_GATEKEEPER_IMAGE=<add registry like "myregistry.docker.io/gatekeeper"> make docker-buildx REPOSITORY=$DESTINATION_GATEKEEPER_DOCKER_IMAGE OUTPUT_TYPE=type=registry make deploy REPOSITORY=$DESTINATION_GATEKEEPER_DOCKER_IMAGE
After successful installation, you can create templates and constraints to implement the policies. Here we are trying to restrict Deployment if the deployment is not having the label “app”. If the specified label is not present it should not be allowed to deploy.
Create a template.yaml file and paste this YAML and apply the file
apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: kubernetesvalidatinglabel spec: crd: spec: names: kind: KubernetesValidatingLabel targets: - target: admission.k8s.gatekeeper.sh rego: | package kubernetes.validating.labels import future.keywords.contains import future.keywords.if import future.keywords.in violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} required := {label | label := input.parameters.labels[_]} missing := required - provided count(missing) > 0 msg := sprintf("you must provide labels: %v", [missing]) }
Create a constraint.yaml file and paste this YAML and apply the file
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: KubernetesValidatingLabel metadata: name: require-deployment-labels spec: match: kinds: - apiGroups: kinds: - Deployment parameters: labels: - app
After successfully applying the template and constraints we will try to create a deployment without the label app such that we can see the error message.
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: test: prod spec: replicas: 2 selector: matchLabels: test: prod template: metadata: labels: test: prod spec: containers: - name: nginx-container image: nginx ports: - containerPort: 80
While applying this YAML you will get a message like this
Error from server (Forbidden): error when creating "deploy.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [require-deployment-labels] [require-deployment-labels] you must provide labels: {"app"}
Implementation of Kyverno
Installation:
Installation using Helm:
helm repo add kyverno https://kyverno.github.io/kyverno/ helm install kyverno-policies kyverno/kyverno-policies -n kyverno -- create-namespace
Install using YAMLs:
kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.10.0/install.yaml
Testing unreleased code:
kubectl create -f https://github.com/kyverno/kyverno/raw/main/config/install-latest-testing.yaml
Here, you can directly create policies using the YAML files. We will create a cluster policy using Kyverno’s CRDs
apiVersion: kyverno.io/v1 # The `ClusterPolicy` kind applies to the entire cluster. kind: ClusterPolicy metadata: name: require-ns-purpose-label # The `spec` defines properties of the policy. spec: # The `validationFailureAction` tells Kyverno if the resource being validated should be allowed but reported (`Audit`) or blocked (`Enforce`). validationFailureAction: Enforce # The `rules` is one or more rules which must be true. rules: - name: require-ns-purpose-label # The `match` statement sets the scope of what will be checked. In this case, it is any `Namespace` resource. match: any: - resources: kinds: - Namespace # The `validate` statement tries to positively check what is defined. If the statement, when compared with the requested resource, is true, it is allowed. If false, it is blocked. validate: # The `message` is what gets displayed to a user if this rule fails validation. message: "You must have label `purpose` with value `production` set on all new namespaces." # The `pattern` object defines what pattern will be checked in the resource. In this case, it is looking for `metadata.labels` with `purpose=production`. pattern: metadata: labels: app: test
We are using only one file to apply the policies rather than creating templates and constraints in the gatekeeper.
After applying this policy try to create the same deployment using the deployment file and you will get the error message like this.
Error from server: error when creating "deploy.yaml": admission webhook "validate.kyverno.svc-fail" denied the request: resource Deployment/default/nginx-deployment was blocked due to the following policies require-ns-purpose-label: require-ns-purpose-label: 'validation error: You must have label `purpose` with value `production` set on all new namespaces. rule require-ns-purpose-label failed at path /metadata/labels/jk/'
If you want to pass the deployment then you should add the label “app” in the metadata of your deployment file.
Summary
I hope now you have a good understanding of Gatekeeper and Kyverno and how it’s working.
As of my understanding for simple and general usage of policies we can go with Kyverno if you need some complex security policies to be implemented in your k8s then you can use Gatekeeper. Both Gatekeeper and Kyverno have their pros and cons, you can use any one of the tools based on your requirement.
Author: Jayakumar S