# Gatekeeper vs Kyverno

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1689935553249/afaf2098-73b8-4cf0-b152-0bfbf00c5a8d.jpeg align="center")

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**

1. **Installation:** Gatekeeper supports three methods of installation.
    
    1. Install using releases to deploy:
        
        ```bash
        kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
        ```
        
    2. Deploy using Helm:
        
        ```bash
        helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
        helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace
        ```
        
    3. Deploy HEAD using make:
        
        ```bash
        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
        ```
        
2. 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.
    
    1. Create a template.yaml file and paste this YAML and apply the file
        
        ```yaml
        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])
                }
        ```
        
    2. Create a constraint.yaml file and paste this YAML and apply the file
        
        ```yaml
        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.
        
        ```yaml
        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  
        
        ```yaml
        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**

1. Installation:
    
    1. Installation using Helm:
        
        ```bash
        helm repo add kyverno https://kyverno.github.io/kyverno/
        helm install kyverno-policies kyverno/kyverno-policies -n kyverno -- create-namespace
        ```
        
    2. Install using YAMLs:
        
        ```bash
        kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.10.0/install.yaml
        ```
        
    3. Testing unreleased code:
        
        ```bash
        kubectl create -f https://github.com/kyverno/kyverno/raw/main/config/install-latest-testing.yaml
        ```
        
2. Here, you can directly create policies using the YAML files. We will create a cluster policy using Kyverno’s CRDs
    
    ```yaml
    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.
    
    ```bash
    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](https://www.linkedin.com/in/jayakumar-s-bba536194)
