Kustomize 101: Part 2 – Configuration Data

In the previous article we tackled some of the very basic functionality of Kustomize. Today we will extend a bit upon this and see how we can create customizations for ConfigMaps through the configMapGenerator. All examples are available on our github page.

To get started we will add a new file to our app folder, config.yaml. This will contain our base ConfigMap.

apiVersion: v1
data:
  DB: SQL01-QA
  ENV: QA
  VERSION: BETA1-QA
kind: ConfigMap
metadata:
  name: config

This is currently set up for our QA environment, but we will use a customization to change this to our dev environment. In our development branch lets go ahead and add a new folder config and create a file named .env. The file name does not matter and you are free to name as desired. This will be used to hold our new ConfigMap data. In this case the keys/values from the .env file are added as individual elements.

DB=SQL01-DEV
ENV=DEV
VERSION=BETA1-DEV

Now all we need to do it update our developerment/kustomization.yaml to reference the new data and instruct it on which ConfigMap it should be replacing. This is done through a configMapGenerator:

bases: 
  - ../app
patches:
  - image.yaml
configMapGenerator:
  - name: config
    behavior: replace
    envs: 
      - config/.env

You are now free to run a new build and confirm the changes were added. A quick dry run to produce output for inspection:

$ kustomize build .
apiVersion: v1
data:
  DB: SQL01-DEV
  ENV: DEV
  VERSION: BETA1-DEV
kind: ConfigMap
metadata:
  name: config

NOTE: There are some nuances I am finding between using kubectl kustomize and kustomize build. Some things, like envs throws errors under kubectl about unknown fields. Additionally, the depraction of bases vs resources seems to work a bit differently between the two. Using kubectl includes resources outside of the current folder fails and requires bases to be used. Where as kustomze runs just find outside the pwd with resources references. I will look to clean this up a bit shortly with more notes about this changes.

Our options for injected data are not just limited to an ENV key/value file. The configMapGenerator also supports:

FILES: When using files the key in the ConfigMap will be the name of the file. The entire contents of the file will be added as the value for this key. In the example below the key is config.yaml as seen in the results.

bases: 
  - ../app
patches:
  - image.yaml
configMapGenerator:
  - name: config
    behavior: replace
    files:
      - config/config.yaml

RESULT:

apiVersion: v1
data:
  config.yaml: |-
    Username=admin
    Password=secret
    Database=dbhost01-qa
kind: ConfigMap
metadata:
  name: config

LITERALS:

bases: 
  - ../app
patches:
  - image.yaml
configMapGenerator:
  - name: config
    behavior: replace
    literals: 
      - DB=SQL01-DEV
      - DBUser=admin

RESULT:

apiVersion: v1
data:
  config.yaml: |-
    Username=admin
    Password=secret
    Database=dbhost01-qa
kind: ConfigMap
metadata:
  name: config

The same principles apply for using Kubernetes secrets with the only real difference being configMapGenerator will be replaced with secretGenerator.

secretGenerator:
  - name: db-creds
    behavior: replace
    envs:
      - config/secret.env

This can be useful for overriding credentials in different overlays depending on the environment type or changing the docker pull credentials based on different registries.