NEW! Mirantis Academy -   Learn confidently with expert guidance and On-demand content.   Learn More


Introduction to Kustomize, Part 2: Overriding values with overlays

In part 1 of this tutorial, we looked at how to use Kustomize to combine multiple pieces into a single YAML file that can be deployed to Kubernetes. In doing that, we used the example of combining specs for Wordpress and MySQL, automatically adding a common app label. Now we're going to move on and look at what happens when we need to override some of the existing values that aren't labels.

Curious about what else is new in Kubernetes 1.14 (besides integration of Kustomize)? Watch our webinar recording.

Changing parameters for a component using Kustomize overlays

Now, we're almost ready, but we do have one more problem.  While we're deploying our production system to a cloud provider that supports LoadBalancer, we're developing on our laptop so we need our services to be of type: NodePort.  Fortunately, we can solve this problem with Kustomize overlays.

Overlays enable us to take the base YAML and selectively change pieces of it.  For example, we're going to create a Kustomize overlay that includes a patch to change the Services to NodePort type services.

It's important that the overlay isn't in the same directory as the base files, so we'll create it in an adjacent directory, then add a dev subdirectory.

mkdir $DEV_HOME
Next we want to create the patch file, $DEV_HOME/localserv.yaml:
apiVersion: v1
kind: Service
  name: wordpress
  type: NodePort
apiVersion: v1
kind: Service
  name: mysql
  type: NodePort
Notice that we've included the bare minimum of information here; just enough to identify each service we want to change, and then specify the change that we want to make -- in this case, the type.

Now we need to create the $DEV_HOME/kustomization.yaml file to tie all of this together:

- ../../base
- localserv.yaml
Notice that this is really very simple; we're pointing at our original base directory, and specifying the Kustomize patch(es) that we want to add.

Now we can go ahead and build the original, and see that it's untouched:

kustomize build $BASE
You can see that we still have LoadBalancer services:
  - port: 3306
    app: my-wordpress
apiVersion: v1
kind: Service
    app: my-wordpress
  name: wordpress
  - port: 80
    app: my-wordpress
  type: LoadBalancer
apiVersion: apps/v1beta2
kind: Deployment
But if we build the overlay instead, we can see that we now have NodePort services:
$ kustomize build $DEV_HOME

...  name: mysql-pass type: Opaque --- apiVersion: v1 kind: Service metadata:  labels:    app: my-wordpress  name: mysql spec:  ports:  - port: 3306  selector:    app: my-wordpress  type: NodePort --- apiVersion: v1 kind: Service metadata:  labels:    app: my-wordpress  name: wordpress spec:  ports:  - port: 80  selector:    app: my-wordpress  type: NodePort --- apiVersion: apps/v1beta2 kind: Deployment metadata: ...
Notice that everything is unchanged by the patch except the type.  Now let's look at making use of these objects in kubectl.

Mirantis simplifies Kubernetes.

From the world’s most popular Kubernetes IDE to fully managed services and training, we can help you at every step of your K8s journey.

Connect with a Mirantis expert to learn how we can help you.

Contact Us

Using Kustomize with kubectl

Now, all of this is great, but saving it to a file then running the file seems like a little bit of overkill.  Fortunately there are two ways we can feed this in directly. One is to simply pipe it in, as you would do with any other Linux program:

kustomize build $DEV_HOME | kubectl apply -f -
Or if you're using Kubernetes 1.14 or above, you can simply use the -k parameter:
kubectl apply -k $DEV_HOME
secret "mysql-pass" created
service "mysql" created
service "wordpress" created
deployment.apps "mysql" created
deployment.apps "wordpress" created
This may not seem like a big deal, but consider this example from the documentation, showing the old way of doing things:
kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret/myregistrykey created.
Versus the new way, where we create a kustomization.yaml file:
- name: myregistrykey
 type: docker-registry
 - docker-username=DOCKER_USER
 - docker-password=DOCKER_PASSWORD
 - docker-email=DOCKER_EMAIL

Then simply reference it using the -k parameter:

$ kubectl apply -k .
secret/myregistrykey-66h7d4d986 created
Considering that kustomization.yaml files can be stored in repos and subject to version control, where they can be tracked and more easily managed, this provides a much cleaner way to manage your infrastructure as code.

There are, of course, other things you can do with Kustomize, including adding name prefixes, generating ConfigMaps, and passing down environment variables, but we'll leave that for another time.  (Let us know in the comments if you'd like to see that sooner rather than later.)

This webinar will bring you up to speed on new features in Kubernetes 1.14, including Kustomize built into kubectl.

Choose your cloud native journey.

Whatever your role, we’re here to help with open source tools and world-class support.


Subscribe to our bi-weekly newsletter for exclusive interviews, expert commentary, and thought leadership on topics shaping the cloud native world.