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.
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 overlays.
Overlays enable us to take the base YAML and selectively change pieces of it. For example, we’re going to create an 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.
OVERLAY_HOME=$BASE/../overlays mkdir $OVERLAY_HOME DEV_HOME=$OVERLAY_HOME/dev mkdir $DEV_HOME cd $DEV_HOME
Next we want to create the patch file, $DEV_HOME/localserv.yaml:
apiVersion: v1 kind: Service metadata: name: wordpress spec: type: NodePort --- apiVersion: v1 kind: Service metadata: name: mysql spec: 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:
bases: - ../../base patchesStrategicMerge: - localserv.yaml
Notice that this is really very simple; we’re pointing at our original base directory, and specifying the 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:
... spec: ports: - port: 3306 selector: app: my-wordpress --- apiVersion: v1 kind: Service metadata: labels: app: my-wordpress name: wordpress spec: ports: - port: 80 selector: app: my-wordpress type: LoadBalancer --- apiVersion: apps/v1beta2 kind: Deployment metadata: labels: ...
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.
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:
secretGenerator: - name: myregistrykey type: docker-registry literals: - docker-server=DOCKER_REGISTRY_SERVER - docker-username=DOCKER_USER - docker-password=DOCKER_PASSWORD - docker-email=DOCKER_EMAIL EOF
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.)