Applied GitOps with Kustomize
Tags: kubernetes, kustomize, gitops, continuousdeployment
Published: 2021-12-01 18:07:50

### What is Kustomize?

Have you always wanted to have different settings between production and staging but never knew how? You can do this with Kustomize!

[Kustomize](https://kustomize.io/) is a CLI configuration manager for Kubernetes objects that leverage layering to preserve the base settings of the application. This is done by overlaying the declarative YAML artifacts to override default settings without actually making any changes to the original manifest.

Kustomize settings are defined in a kustomization.yaml file. Kustomize is also integrated with kubectl. With Kustomize, you can configure raw, template-free YAML files, which allows you to modify settings between deployment and production easily. This enables troubleshooting misconfigurations and keeps use-case-specific customization overrides intact.

Kustomize also allows you to scale easily by reusing a base file across all your environments (development, production, staging, etc.) and then overlay specifications for each.

<li>**Base Layer**: This layer specifies the most common resources and original configuration.</li>
<li>**Overlays Layer**: This layer specifies use-case-specific resources by utilizing patches to override other kustomization files and Kubernetes manifests.</li>
Overlays are what help us accomplish our goal by producing variants without templating.

### Benefits of Kustomize

Kustomize offers some of the following benefits:

1. **Reusability**
With Kustomize you can reuse one of the base files across all environments (development, staging, production, etc.) and overlay specifications for each of those environments.

2. **Quick Generation**
Since Kustomize doesn't utilize templates, a standard YAML file can be used to declare configurations.

3. **Debug Easily**
Using a YAML file allows easy debugging, along with patches that isolate configurations, allowing you to pinpoint the root cause of performance issues quickly. You can also compare performance to the base configuration and other variations that are running.

4. **Kubernetes Native Configuration**
Kustomize understands Kubernetes resources and their fields and is not just a simple text templating solution like other tools.

See below an example of a Kustomize file structure including the base and overlays within an application. You can also reference a code-based demo project on [GitHub](https://github.com/hseligson1/kustomize-gitops-example).

<a href="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-12-01-at-10.32.44-AM.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-12-01-at-10.32.44-AM-300x175.png" alt="" width="300" height="175" class="alignnone size-medium wp-image-20681" /></a>

The tree structure above is a simple example of how you can deploy a single application to 2 different environments (staging and production). Let's dig deeper into each directory and create an overlay.

**base folder**

The [base](https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#base) folder holds common resources, such as the deployment.yaml, service.yaml, and configuration files. It contains the initial manifest and includes a namespace and label for the resources.

**overlays folder**

The [overlays](https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#overlay) folder houses environment-specific overlays, which use patches to allow YAML files to be defined and overlaid on top of the base for any changes. Let's take a look at a couple of the environments within the overlays folder below that also includes the kustomization.yaml.

**kustomization.yaml**

Each directory contains [a kustomization file](https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#kustomization-root), which is essentially a list of resources or manifests that describes how to generate or transform Kubernetes objects. There are [multiple fields](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/) that can be added, and when this list is injected, the kustomization action can be referenced as an overlay that refers to the base.

### Creating Overlays

Let's explore a simple example of how overlays work.
We'll make the following changes within our production and staging directories:
<li>Within the staging overlay, we will enable a risky feature that is NOT enabled in production.</li>
<li>Within the production overlay, we'll assign a higher replica count.</li>

We'll also ensure the web server from the cluster variants is different from one another.

**overlays/staging/kustomization.yaml**

In the staging directory, let's make a kustomization defining a new name prefix and different labels.

<pre>namePrefix: staging-
commonLabels:
 variant: staging
commonAnnotations:
  note: “Welcome to staging!”
bases:
- ../../base
patchesStrategicMerge:
- config-map.yaml
</pre>

**Staging patch**

Add a configMap kustomization to change the server greeting from &quot;Hello!&quot; to &quot;Kustomize rules!&quot; We'll also enable the risky flag.

<pre>apiVersion: v1
kind: ConfigMap
metadata:
 name: the-map
data:
 altGreeting: “Kustomize rules!”
 enableRisky: “true”
</pre>

**overlays/production/kustomization.yaml**

Within the production directory, we will make a kustomization with a different name prefix and label.

<pre>namePrefix: production-
commonLabels:
 variant: production
commonAnnotations:
  note: “Welcome to production!”
bases:
- ../../base
patchesStrategicMerge:
- deployment.yaml
</pre>

**Production patch**

We'll make a production patch that will increase the replica count.

<pre>apiVersion: apps/v1
kind: Deployment
metadata:
 name: the-deployment
spec:
 replicas: 10
</pre>

Now, we can compare these overlays - the kustomizations and patches are required to create noticeable differences between staging and production variants within the Kubernetes cluster.

Based on the changes above, the output would look something like this:

<pre>
<   altGreeting: Kustomize rules!
<   enableRisky: "true"
---
>   altGreeting: Hello!
>   enableRisky: "false"

<     note: Welcome, I am staging!
---
>     note: Welcome, I am production!

<     variant: staging
---
>     variant: production
</pre>

You can now see the difference between the staging and production overlays.
Overlays contain a kustomization.yaml, and can also include manifests as new or additional resources, or to patch resources. The kustomization file is what defines how the overlays should be applied to the base and this is what we refer to as a [variant](https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#variant).

Each time a change is made to an application, like the example above - it is the overlays that are doing the heavy lifting.

So, now that you have learned a bit about Kustomize, you might be wondering how you can apply the GitOps workflow to it. Below we'll explain more about GitOps and how you can apply it to your Kustomize project and deploy it.

### GitOps works with all your existing tools

Now, let's learn more about how to apply GitOps to your Kustomize application deployment!

[GitOps](https://codefresh.io/gitops/) is a paradigm that incorporates best practices applied to both an application development workflow and the infrastructure of a system. This is done to empower organizations and developers to operate their systems from a single source of truth enabled by Git.
A couple of key aspects of GitOps that most aren't as familiar with and are crucial are the:

1. **GitOps controller**

The controller reads the declarative configuration and uses the reconciliation loops to converge the desired end state. This controller detects the differences between states and makes the necessary changes to maintain the desired state.

2. **Automation reconciliation loop**

The concept of the reconciliation loop is used to keep the state as defined within a manifest. This is such an important principle for the GitOps paradigm because these loops are what drive the entire cluster to the desired state in Git.

Now that you have a basic understanding of what both Kustomize and [GitOps](https://opengitops.dev/) are and what some of their capabilities are, perhaps you've considered applying GitOps to your existing or future application and infrastructure workflow.

We'll explore 2 approaches on how to use Kustomize with or without GitOps:
<li>Using only Kustomize</li>
<li>Using Kustomize with ArgoCD</li>


### What is ArgoCD?

[ArgoCD](https://github.com/argoproj/argo-cd) is a GitOps controller specifically created for Kubernetes deployments. It supports a variety of configuration management tools like Helm (take a look at [our documentation](https://codefresh.io/helm-tutorial/using-helm-with-gitops/) for more information), Ksonnet, Kustomize, [etc](https://argo-cd.readthedocs.io/en/stable/user-guide/application_sources/). The core component is the Application Controller, which continuously monitors any running applications and compares the live state against the desired state defined in a Git repository.

If a deployed application whose live state drifts from the target state, ArgoCD is then considered OutOfSync. It then provides reports and visualizations to identify these changes and can provide automation when any modifications are made so that the target environments reflect the desired state of a system in Git.

If you'd like to explore these different deployment approaches with Kustomize from a code-based perspective, here is an [example project](https://github.com/hseligson1/kustomize-gitops-example) that you can follow along with on GitHub. However, we will explore both of these approaches below with some more details.

## Approach #1: Deploying only with Kustomize

If you want to use Kustomize, but your organization isn&#39;t ready to implement GitOps with your workflow, you can still use Kustomize on its own.

**Install Kustomize**

First, install Kustomize and this can be done either by utilizing kubectl version 1.14 or later, otherwise you can install based on your operating system and reference the [Kustomize documentation](https://kubectl.docs.kubernetes.io/installation/kustomize/).

**Create a base directory**

Next, in order to deploy an application with Kustomize, you need a kustomization.yaml file, and this is added to the base directory.

<a href="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-12-01-at-11.17.06-AM.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-12-01-at-11.17.06-AM-300x213.png" alt="" width="300" height="213" class="alignnone size-medium wp-image-20682" /></a>

The kustomization.yaml file specifies what resources to manage due to the complexity of multiple resource types and different environments when handling configuration files for Kubernetes.

Within the base directory, there is also a service and deployment resource.

**Create an Overlays directory**

Next, you'll want to create an overlays directory, and this directory is what allows you to kustomize the base and apply any changes with a [patch](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/) to modify a resource.

The overlays still use the same resources as the base but may vary in the number of replicas in a deployment, the CPU for a specific pod, or the data source used in the ConfigMap, etc.

Within our example, we have a staging and production overlay. These overlay directories contain the kustomizations and patches previously mentioned that are required to create distinct staging and production [variants](https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#variant) in a cluster. However, with Kustomize you can use the overlays for anything needed to organize environments, whether it's based on location: USA, Asia, Europe or internal/external, team A/team B, etc.

<a href="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-12-01-at-11.18.43-AM.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-12-01-at-11.18.43-AM-293x300.png" alt="" width="293" height="300" class="alignnone size-medium wp-image-20683" /></a>

Kustomize is essentially an overlay-based engine that functions by finding and replacing specific sections in the manifest and replacing it with required fields and values. These values are then merged and deployed!

**Create a namespace for specific environments**

<pre>kubectl create ns staging
</pre> 
or 
<pre>kubectl create ns production
</pre>

**Build and Deploy to environments**

You can then apply the overlays to your cluster and deploy with the command:

<pre>kubectl apply -k overlays/staging
</pre> 
or 
<pre>kubectl apply -k overlays/production
</pre>

You are now successfully using Kustomize to manage your Kubernetes configurations and deploy your application to production and staging environments!

## Approach #2: Deploying using Kustomize with GitOps

In the previous approach, you learned how to deploy an application using only Kustomize, so let's see how it fits into ArgoCD and how it can be used in a GitOps workflow.

[ArgoCD supports Kustomize](https://argo-cd.readthedocs.io/en/stable/user-guide/kustomize/) and has the ability to read a kustomization.yaml file to enable deployment with Kustomize and allow ArgoCD to manage the state of the YAML files.

ArgoCD monitors the resources within the git repository for any changes, ensuring that the live state of your system matches the desired state. Each time customization is made, ArgoCD detects those modifications and updates the deployment.

So, let's begin walking through the process to deploy a Kustomize project using ArgoCD!

**Install ArgoCD and access a Kubernetes Cluster**

First, we need to ensure the Kubernetes cluster is set up and you are logged into ArgoCD so that these resources are provided and can be deployed. You can use any Kubernetes cluster and [install](https://github.com/argoproj/argo-cd/blob/master/docs/cli_installation.md) the argocd CLI.

Once you've accessed the argocd CLI you can [access the ArgoCD server and log in](https://argo-cd.readthedocs.io/en/stable/getting_started/#4-login-using-the-cli) to the ArgoCD UI. However, if you're more of a terminal fan, you can also deploy the application through the argocd CLI. Feel free to reference the [demo application](https://github.com/hseligson1/kustomize-gitops-example) that will walk you through the deployment process through your terminal.

**Create an ArgoCD application**

Now, we can set up the Kustomize Project. Similar to [using Helm with GitOps](https://codefresh.io/helm-tutorial/using-helm-with-gitops/), we will approach this deployment the same way within the UI by creating an ArgoCD application.

Let's begin! First, click on the +NEW APP and include the name of the ArgoCD application, select the default project, and enable the Automatic SYNC POLICY.

<a href="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-11-22-at-11.55.41-AM.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/Screen-Shot-2021-11-22-at-11.55.41-AM.png" alt="" width="1835" height="505" class="alignnone size-full wp-image-20686" /></a>

Next, when adding your Kustomize project it helps to include a specific Path to segregate the application manifests inside the Git repository. We can then ask ArgoCD to only read the specific directories in the repository and read manifests within that path. 

<a href="https://codefresh.io/wp-content/uploads/2021/12/argocd-source-ui-staging.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/argocd-source-ui-staging.png" alt="" width="1474" height="416" class="alignnone size-full wp-image-20693" /></a>

Then, within the Destination section, you need to provide the destination of the Kubernetes cluster details. Also, make sure to click on the checkbox for auto-create namespace when adding the input field value, or you can add a custom namespace you've created prior.

<a href="https://codefresh.io/wp-content/uploads/2021/12/argocd-ns-ui.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/argocd-ns-ui.png" alt="" width="1453" height="335" class="alignnone size-full wp-image-20689" /></a>

ArgoCD will read the kustomization.yaml file in the path you provided and prompt you to allow override with different values.

<a href="https://codefresh.io/wp-content/uploads/2021/12/argocd-kustomize-ui-staging.png"><img src="https://codefresh.io/wp-content/uploads/2021/12/argocd-kustomize-ui-staging.png" alt="" width="1508" height="439" class="alignnone size-full wp-image-20688" /></a>

**Synchronize Application and Deploy**

Assuming you enabled auto-synchronization when creating your ArgoCD application, it will read the parameters and the Kubernetes manifests. Then, once the manifests are applied, you can review the application health and resources you deployed.

If your application has an error when trying to synchronize, you can execute the argocd history command, allowing you to view the application deployment history to identify a possible error:

<pre>
argocd app history argocd_app_name
</pre>

If you need to rollback you can do so by executing this command:

<pre>
argocd app rollback argocd_app_name history_id
</pre>

These commands leverage a faster and more secure deployment by enabling the tracking from the Git repository. This allows you to track the active Kubernetes resources and events. These actions can also be done within the UI.

Once the application is healthy and synchronized, each time you create a new kustomization.yaml file and the file changes, ArgoCD will be able to detect those changes and make updates to your deployment. You can even mention specific [Kustomize tags](https://argo-cd.readthedocs.io/en/stable/user-guide/kustomize/) and set up custom build options for your Kustomize build.

## Summary

Kustomize allows you to use different configurations of a base Kubernetes manifest. Within this post, we've covered the Kustomize basics and how to deploy using just Kustomize and deploying with GitOps. This allows you to leverage the power of Kustomize to define the Kubernetes files without using a templating system.

To start deploying your Kustomize application, sign up for a [Codefresh](https://codefresh.io/codefresh-signup/) account today to apply [GitOps](https://codefresh.io/gitops/) to your deployment process!