Helm and Package Management in Kubernetes

Package Management

Perhaps the most common package manager in all of IT is Debian’s APT (Advanced Package Tool). It gives you an easy way to install applications rather than downloading, unzipping, and placing them manually (plus a few additional steps). Instead of all of that, you simply run “apt-get install [PACKAGE_NAME],” perhaps add some options to the command, and let APT handle it for you.

This pattern has proliferated internet-based systems, such as the Apple App Store, Salesforce AppExchange, and the AWS Marketplace. The latter two examples are more direct, and items in those repositories are configured by their developers as templates, which take the buyer’s inputs and crank out an instance of the solution customized to the buyer’s liking.

While all of these tools are useful for accessing tool created by other companies, they can also be useful for organizing and making reusable code created by your own company. In Kubernetes, the package manager of choice is usually Helm, and it provides many of those same advantages to Kubernetes environments. Helm templates come as Charts, and can be used both for installing applications designed by others, and making your own Kubernetes configurations reusable.

Kubernetes YAML

When creating Kubernetes objects such as Services, Deployments, and PersistentVolumeClaims, you usually define them by writing YAML manifests. Here’s a simple example, a file called my-app.yaml with these contents:

apiVersion: v1

kind: Service

metadata:

name: my-nginx-svc

labels:

app: nginx

spec:

type: LoadBalancer

ports:

– port: 80

selector:

app: nginx

This system is amazing – YAML is very clean and easy to read, Kubernetes conventions are rational and explicit, and you can git control your configuration files to keep track of changes and easily switch between versions. Unlike JSON, YAML allows comments, which is critical for noting important aspects of your configuration.

But there’s a problem. There are no variables in Kubernetes YAML. If you have a bit of information that recurs throughout your manifests, there is no built-in way to abstract to a variables file. If you need to make a change, you’ll have to hunt that information down everywhere it occurs and change it one by one. Or if you have a common manifest used throughout your company by different teams, they’ll again have to change that information everywhere it occurs instead of just changing it once in a variables file.

By contrast, Terraform makes use of tfvars files for this very reason, to abstract away those common bits and not repeat yourself (be DRY). Similarly, Ansible lets you define and register variables for the same reason. Sadly, Kubernetes has no feature.

Helm YAML > K8s YAML

Fortunately, Helm fills in the gap, and provides variables, templating, and more for Kubernetes manifests. Instead of writing raw Kubernetes YAML, you prepare a Helm Chart which includes a YAML file. However, Helm YAML not only allows for variables, but even conditionals (if/else statements) and loops (like for each)!

Here’s some sample YAML from a Helm Chart (from Helm’s Github):

apiVersion: v1

kind: ConfigMap

metadata:

name: {{ .Release.Name }}-configmap

data:

myvalue: “Hello World”

drink: {{ .Values.favorite.drink | default “tea” | quote }}

food: {{ .Values.favorite.food | upper | quote }}

{{ if and .Values.favorite.drink (eq .Values.favorite.drink “coffee”) }}mug: true{{ end }}

Everything {{inside the double braces}} is functionality added by Helm. Most of these examples are calls to variables that would be defined in a separate file, but the last line also includes a conditional (if-statement).

Using Helm, you can follow programming best practices and repeat yourself less, easily share Charts within your company, and even share them publicly. To find or release public Helm Charts, see the Helm Charts Github.