Kustomize Best Practices (Part 1)
Kubectl includes a very useful command called kustomize that allows a template-free way to customize Kubernetes application configuration¹.
You might already be using helm to achieve many of the same outcomes that you can achieve with kustomize. Although there certainly are some pros and cons to each, they aren’t necessarily mutually exclusive. Perhaps I’ll create a future article to compare and contrast helm and kustomize. This article, however, is intended to provide some best practices for those that are already using kustomize.
If something is the same between multiple overlays, consider putting it in your base
Imagine that you have an application that consists of a Deployment and a Service. You need to deploy 2 instances of your application: development and production.
What will be deployed is very similar between these two instances, but there are some differences. For example, perhaps the Namespace name needs to be different, and the replicas on the deployment in production is higher than the replicas on the deployment in development. To satisfy this requirement, you might create a structure that looks like the following:
/myapp
├── base
│ ├── deployment.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
├── dev
│ ├── deployment-patch.yaml
│ └── kustomization.yaml
└── prod
├── deployment-patch.yaml
└── kustomization.yaml
The kustomization.yaml in the dev and prod overlays specifies the namespace, and the deployment-patch.yaml files allow you to modify the replicas. Otherwise, most of the definition of the deployment and service could/should be in the base.
Use multiple bases to compose different application components
You may have application components that you want to share between multiple applications. For example, suppose that we wanted to add a MongoDB to the above example application. Rather than simply adding a statefulset.yaml to the base with appropriate patches in the overlays, you might consider creating a discrete base for Mongo:
/mongo
├── base
│ ├── statefulset.yaml
│ └── kustomization.yaml
/myapp
├── base
│ ├── deployment.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
├── dev
│ ├── deployment-patch.yaml
│ ├── statefulset-patch.yaml
│ └── kustomization.yaml
└── prod
├── deployment-patch.yaml
├── statefulset-patch.yaml
└── kustomization.yaml
This will make it easier to maintain the application going forward, as well as helping to position us to split accountability for the various aspects of the application to the subject matter experts.
Use remote bases
Taking the multiple base idea one step further, Kustomize allows the specification of remote base(s). This allows portions of your applications to be more easily maintained by different subject matter experts, while still allowing the application owner control over what they need (for example, what version of a base to use).
Your kustomization.yaml in the overlays above might look something like this:
resources:
- https://git.example.com/scm/mongo/myrepo.git//base?ref=v1.0.0
- https://git.example.com/scm/baseapi/somerepo.git//base?=v2.1.0patchesJson6902:
- ...
This way, theoretically an application framework team could be responsible for the baseapi, the database management team could be responsible for mongo, and the specific application team would simply have to maintain the overlays that compose the baseapi and mongo components together.
More kustomize best practices can be found in part 2.
¹ You can also get specific kustomize binaries outside of kubectl, especially if you need the “latest and greatest” functionality