Sandeep

Let's Kustomize

Let's Kustomize

How to Kustomize a Helm Chart?

Kustomize


Kustomize is a standalone tool to customize Kubernetes objects through a kustomization file. Kustomize lets you customize raw, template-free YAML files for multiple purposes, leaving the original YAML untouched and usable as is.

Kustomize is a very opinionated tool. If you are interested to know more about it, you can listen/subscribe to this Kubernetes Podcast from Google by Adam Glick and Craig Box.

Source: "Kubernetes podcast from Google #007"

Let’s try to understand Kustomize using an example. Personally, Kustomize and Helm solves different problems and if you seriously think about patching the current kubernetes applications, Kustomize is the best tool. You can do the same with Helm and if you like lot of templating, Helm is what you need.

You can watch the below talk about limits of Helm.

Kustomize - Helm Chart


Lets Kustomize a Helm Chart. I took datadog helm chart for this blog. But you can take any helm chart that you want. Base idea will remain the same.

Here is my example repo for this blog Kustomization of datadog Helm Chart

[⎈ k8s ] tree -d
.
└── k8s
    ├── bases
    │   └── vendor
    │       └── stable
    │           └── datadog-2.3.14
    │               ├── charts
    │               │   └── kube-state-metrics
    │               │       └── templates
    │               ├── ci
    │               ├── docs
    │               └── templates
    └── overlays
        ├── dev
        │   ├── patches
        │   └── secrets
        └── prod
            ├── patches
            └── secrets

18 directories

Kustomize - Its Patching


There are 2 main directories that Kustomize uses i.e. bases and overlays.

bases will contain the base/raw form of Helm chart converted into a plain YAML file which can be easily understandable by kustomization.

overlays will contain the actual patches that you will put on bases. There will be different patches as per your needs. Here I took an example of patches for dev and prod environments.

Kustomize - bases dissection


bases contains the main helm chart for datadog.

├── Makefile ------------------> use to template the helm chart into yaml format
├── datadog.values.yaml -------> is the values files use to tempaltise datadog helm chart
├── datadog.yaml --------------> is the actual kustomize manifest file
├── kustomization.yaml --------> contains the templated helm chart manifests in yaml format
├── transformer-common.yaml ---> transformer used by kustomize to override images
├── transformer-images.yaml ---> transformer used by kustomize to add labels
├── transformer-patches.yaml --> transformer used by kustomize to patche k8s resources
└── vendor --------------------> actual helm chart here

#1. Makefile
Makefile have just 1 update command which will be used to create datadog manifest file again. If a new version of datadog helm chart released, just fetch the helm chart in vendor/stable directory and update Makefile

[⎈ k8s ] cat Makefile
update:
    helm3 template \
          datadog \
          --namespace=monitoring \
          --values datadog.values.yaml \
          vendor/stable/datadog-2.3.14/ \
          > datadog.yaml

#2. datadog.values.yaml
The actual values for datadog helm chart are present in this file. These values can be default values from helm chart.

datadog.values.yaml will be applied everytime with Makefile update command which in turn run helm template command for the datadog helm chart.

All the common values that can be applied to helm chart should be put in datadog.values.yaml

datadog:
  apiKey: ""
  appKey: ""
  clusterName: "eks-dev-cluster-1"
  kubeStateMetricsEnabled: true
  tags:
    - "region: eu-east-1"
    - "customer: xyz"
clusterAgent:
  enabled: true

#3. datadog.yaml
This file is the result of Makefile update command.
Kustomize will be using it to create kubernetes resources.

---
# Source: datadog/templates/agent-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: datadog-cluster-agent
  labels:
...
---
...
---
...
---

#4. kustomization.yaml
kustomization.yaml file has a specific syntax to create kubernetes manifests.
Under resources and transformers sections, need to add relative files location paths.

resources:
- ./datadog.yaml

transformers:
- ./transformer-common.yaml
- ./transformer-patches.yaml
- ./transformer-images.yaml

More details about kustomize docs

#5. transformer-common.yaml
The labels transformer adds labels to the metadata/labels field for all manifest files.
LabelTransformer code will look like below.

---
apiVersion: builtin
kind: LabelTransformer
metadata:
  name: stub
labels:
  app.kubernetes.io/name: kube-state-metrics
  app.kubernetes.io/instance: "datadog"
fieldSpecs:
- path: metadata/labels
  create: true

As seen from above, following 2 labels will be added to all the manifests generated by kustomization.

labels:
  app.kubernetes.io/name: kube-state-metrics
  app.kubernetes.io/instance: "datadog"

#6. transformer-images.yaml
The default images transformer updates the specified image key values found in paths that include containers and initcontainers sub-paths.

apiVersion: builtin
kind: ImageTagTransformer
metadata:
  name: image-quay-coreos
imageTag:
  name: quay.io/coreos/kube-state-metrics
  newName: my-registry.servers.xyz.com/mirrors/quay.io/coreos/kube-state-metrics
  newTag: v1.9.5

#7. transformer-patches.yaml
Patch Transformer can patch the k8s manifests and can replace/remove contents. Below PatchTransformer will replace the image for Deployment and remove the labels imposed by helm chart.

---
apiVersion: builtin
kind: PatchTransformer
metadata:
  name: helm-cleaner-kube-state
target:
  group: apps
  version: v1
  kind: Deployment
  namespace: monitoring
  name: datadog-kube-state-metrics
patch: |-
  - op: replace
    path: /spec/template/spec/containers/0/image
    value: "my-registry.servers.xyz.com/mirrors/quay.io/coreos/kube-state-metrics:v1.9.5"
  - op: remove
    path: /spec/template/spec/containers/0/resources/limits/cpu
  - op: remove
    path: "/metadata/labels/helm.sh~1chart"
  - op: remove
    path: "/metadata/labels/app.kubernetes.io~1managed-by"

Its clear from code that our target is Deployment datadog-kube-state-metrics in monitoring namespace.

target:
  group: apps
  version: v1
  kind: Deployment
  namespace: monitoring
  name: datadog-kube-state-metrics

PatchTransformer will replace first container’s image of the pod. Please lookout of numeral 0.
0 is first container as per spec definition
1 is second container as per spec definition and so on

- op: replace
    path: /spec/template/spec/containers/0/image
    value: "my-registry.servers.xyz.com/mirrors/quay.io/coreos/kube-state-metrics:v1.9.5"

PatchTransformer will remove first container’s resource limits CPU values.

- op: remove
    path: /spec/template/spec/containers/0/resources/limits/cpu

PatchTransformer will remove below label from deployment

- op: remove
    path: "/metadata/labels/helm.sh~1chart"

PatchTransformer will remove below label from deployment

- op: remove
    path: "/metadata/labels/app.kubernetes.io~1managed-by"

#8. vendor
vendor directory will contain actual helm chart from upstream stable repository.

[⎈ k8s ] tree -d vendor/
vendor/
└── stable
    └── datadog-2.3.14
        ├── charts
        │   └── kube-state-metrics
        │       └── templates
        ├── ci
        ├── docs
        └── templates

Kustomize - overlays dissection


Overlays can be divided into environment based directories. Every environment contains patches relevant to it. Patching becomes easy and we can add manifest per environment very easily using a pipeline.

secrets can be added which later can become env variables or volumes in Pod using configmap/secret.

[⎈ k8s ] tree -d
.
├── dev
│   ├── patches
│   └── secrets
└── prod
    ├── patches
    └── secrets

Kustomize - Run it


To run the kustomize, we change directory to overlays environment and apply it.

[⎈ k8s ] cd k8s/overlays/dev/
[⎈ k8s ] kustomize build .
[⎈ k8s ] kustomize build . | kubectl apply -f -
[⎈ k8s ] 
[⎈ k8s ] 
[⎈ k8s ] cd k8s/overlays/prod/
[⎈ k8s ] kustomize build .
[⎈ k8s ] kustomize build . | kubectl apply -f -

Kustomize - improvisation


  • Use kapp tool with kustomize for deployment
  • Use sops to encrypt secrets
  • Use pipelines to install patches per environment of overlays

walking

Reference lists