You’re probably familiar with the concept of packages.
Every time you install a new software using the apt-get or brew commands, the CLI downloads a package that includes everything you need to install the software you want on your operating system.
Kubernetes has a system to manage packages, and it’s called Helm.
It’s pretty clear why standard package formats like DEB or RPM are necessary, but with Kubernetes and Docker, it’s not so obvious.
Isn’t the whole idea of Docker is that it produces a self-contained application artifact?
If so, what’s included in Helm’s package and why we need it?
Scripted Approach To Deployment
Let’s assume for a moment that you have just migrated your SaaS application components to run on Kubernetes.
Each application has its own set of YAML configurations that you deploy into two separate environments: staging and production.
Since the configuration is slightly different between staging and production, your YAML files need to be adjusted before pushing a new update to each one of these environments.
One common example is the Mongo database URLs which are different between the environments. Before you deploy, you need to change the Mongo URL.
In most cases, people solve this problem by writing a simple script that will substitute the relevant configuration parameters before the deployment step in your deployment pipeline.
Pretty simple, huh?
Yes, and this workaround is great when your startup is just gaining traction and you have a small set of services that are running on Kubernetes.
Outgrowing The DIY Approach
While the approach described above will work in the most simple cases, here are a few issues and limitations that will become obvious down the road:
1. Discrepancies Between Environments
Kubernetes makes it easy to write and deploy new micro-services, but quite often, the number of services running in the system will increase.
Some of these services are needed for internal purposes and will only run on staging. Other services will deploy additional database containers in staging to replace the cloud provider’s options and reduce infrastructure costs.
In all these scenarios, it’s going to be very hard to quickly understand what is supposed to run in each environment and which services are dependent on which components.
The answers to these questions will be buried inside the deployment script we mentioned above, and believe me, even the author of the script won’t be always able to answer these questions for you.
2. Weak Template Substitution Approaches
One common way to substitute parameters in a template file is to use sed, envsubs or similar utilities.
In simple cases, when you don’t have many services and don’t manage much in the way of environment-specific configurations, substituting a few parameters based on ENV variables passed to the build job may be enough.
However, these tools aren’t powerful enough!
Kubernetes YAMLs can become very complicated, and with time you will discover that you need a much more powerful templating language to properly generate the per environment configuration. You’ll need to use if/else control structures or deal with repetition using partial support.
3. Versioning And Packaging For Distribution
Although staging and production environments are pretty common among all SaaS infrastructures, with time you may be required to add additional environments.
They might be a few managed environments you maintain for your premium customers—or a completely self-hosted version of your SaaS that you need to ship and update.
In these situations, you can’t just substitute and deploy your YAML configuration to remote Kubernetes clusters. You need to version each release and bundle it in a deployable package.
You also need to find a way to run software upgrades, which will usually require you to run sanity tests or migration tasks during or after the upgrade process.
Helm To The Rescue
By now you can probably see that I’m leaning toward an obvious conclusion: Helm solves many problems, including the three important ones I’ve mentioned above.
There are a few good examples online for how complex projects can be deployed using Helm, and you can find one of them at Openstack’s Helm repository.
Helm’s dependency management mechanisms, coupled with additional approaches for secret management, can provide a single point of truth on which services and configurations are running on your various environments.
Helm’s powerful templating language allows dealing with Kubernetes’ YAML hell with dignity.
And Helm’s repository support and package and release-related commands help bundling and versioning your application stacks for shipment and installation on remote environments.
While this isn’t an article about Helm features, I am planning to write one in a not so distant future, so stay tuned.
But to summarize — if you are starting to feel that your environment’s complexity is growing along with your custom deployment scripts, it might be a good time to review Helm as a potential solution that will replace your homegrown scripts.