Saturday, November 20, 2021

TLDR Intro to Kustomize

 1. Motivation

Suppose you have to deploy off-the-shelf a complex component, be it defined as a plain Yaml or a Helm chart, which require some customization. A possibility may be to edit the yaml or fork the existing helm to a new chart. Cool, you have now become the maintainer! From now on you will be integrating changes to the project in your derived version. Beside the additional work required to ensure compatibility, this brings in the risk of adding bugs and misconfigurations.

2. Kustomize

2.1 About

Kustomize comes to the rescue by allowing for the combination of source configurations and the definition and application of declarative changes as overrides or patches. For instance, whereas one centralized configuration may be defined for a deployment multiple flavours may be defined depending on the target environment of choice (e.g. test, QA, prod).

2.2 Installation

Kustomize is now fully integrated with kubectl since 1.14 so there are no additional requirements to care of. Alternatively, kustomize is a go project that can be installed with a usual go get (i.e. go get sigs.k8s.io/kustomize/kustomize/v3). See here for an overview.

If you need kubectl or have an older version, you may want to have a look here to update it.

Depending on your choice you will be using one of the following:

  1. kustomize build <path>
  2. kubectl kustomize <path> 
To render and apply in one single step the latter can be replaced with kubectl apply -k <path>.

2.2 Basic Usage

The basic idea behind kustomize is to define a kustomization.yaml file along with the existing configuration files. The kustomization defines modifications and a list of resources on which they are to be applied to. 

For instance [1]:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app: my-app
resources:
- deployment.yaml
- service.yaml

When running kustomize build or kubectl kustomize on the directory a yaml configuration is rendered and print to stdout.

Kustomize can also compose configurations residing in different directories, by creating multiple bases. As in the example above, a base is defined by creating a kustomization.yaml file, listing a number of resources. Once done, a base can be recalled by listing it as a base, for instance:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
  app: my-app
bases:
  - ./mysql
  - ./my-app

2.3 Overlays

The power of kustomize comes from the possibility of defining overlays over base configurations [2]. Overlays define patches over base configurations, to specialize behavior (e.g. patchesJson6902) or to add additional resources (e.g. patchesStrategicMerge).  Here is a complete list of those features.

For instance:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
- deployment.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: my-nginx
  path: patch.yaml

with the patch.yaml being:

- op: replace
  path: /spec/replicas
  value: 3

where the overlay does change the number of replicas to 3.

3. Integration in GitOps - ArgoCD

There are multiple possibilities to use Kustomize in ArgoCD: i) simply apply kustomize to the path monitored by the ArgoCD Application resource, as in this example, and ii) apply kustomize to the output rendered by Helm [3, 4]. The latter requires the following steps:

1. kustomized-helm is added to the plugins in the argocd-cm configmap

configManagementPlugins: |
  - name: kustomized-helm
    init:
      command: ["/bin/sh", "-c"]
      args: ["helm dependency build"]
    generate:
      command: [sh, -c]
      args: ["helm template --release-name release-name . > all.yaml && kustomize build"]


2. a kustomization.yaml is placed in the folder monitored by the ArgoCD Application, in order to refer to the all.yaml rendered as output of the helm template command

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - all.yaml
patchesJson6902:
...

3. the plugin is referred directly by the ArgoCD Application under spec.source.plugin.name: kustomized-helm

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapplication
  namespace: argocd
spec:
  project: myproject
  source:
    path: myapplication
    repoURL: {{ .Values.spec.source.repoURL }}
    targetRevision: {{ .Values.spec.source.targetRevision }}
    plugin:
      name: kustomized-helm
  destination:
    namespace: myproject
    server: {{ .Values.spec.destination.server }}

A full example of the integration between ArgoCD and Kustomize is reported here.

You are done. If you want to read more, please have a look at the official documentation [5] and this very good overview [6].

Cheers.

Resources

  1. https://www.mirantis.com/blog/introduction-to-kustomize-part-1-creating-a-kubernetes-app-out-of-multiple-pieces/
  2. https://www.densify.com/kubernetes-tools/kustomize
  3. https://dev.to/camptocamp-ops/use-kustomize-to-post-render-helm-charts-in-argocd-2ml6
  4. https://github.com/argoproj/argocd-example-apps/tree/master/plugins/kustomized-helm
  5. https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
  6. https://skryvets.com/blog/2019/05/15/kubernetes-kustomize-json-patches-6902/

No comments:

Post a Comment