Managing Kubernetes manifests for anything beyond a toy project gets messy fast. Helm is the package manager for Kubernetes — it lets you template your YAML, version it, and deploy it with a single command. There's a learning curve but it's worth it.
Fair warning: this is Helm 2, which means Tiller. Tiller is a server-side component that runs inside your cluster and handles releases on Helm's behalf. It has some security implications (cluster-admin by default) but for internal/dev clusters it's fine and it's what everyone's using right now.
Installing Helm and Tiller
Download the Helm client from the releases page and put it in your PATH:
$ helm version
Client: &version.Version{SemVer:"v2.5.1", ...}
Error: cannot connect to Tiller
Right, we need Tiller. Install it into the cluster:
$ helm init
$HELM_HOME has been configured at /Users/marie/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Happy Helming!
If you're on a cluster with RBAC enabled (Kubernetes 1.6+), you'll need to create a service account for Tiller first:
$ kubectl create serviceaccount tiller --namespace kube-system
$ kubectl create clusterrolebinding tiller-cluster-rule \
--clusterrole=cluster-admin \
--serviceaccount=kube-system:tiller
$ helm init --service-account tiller
Verify both sides are talking:
$ helm version
Client: &version.Version{SemVer:"v2.5.1", GitCommit:"...", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.5.1", GitCommit:"...", GitTreeState:"clean"}
Versions should match. If they don't, run helm init --upgrade.
Adding a chart repository
The stable repo is included by default but run an update to get the latest chart list:
$ helm repo add stable https://kubernetes-charts.storage.googleapis.com/
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. Happy Helming!
Installing a chart
Let's install nginx-ingress as a real example. First, look at what the chart exposes:
$ helm inspect stable/nginx-ingress | head -40
Or just look at the default values:
$ helm inspect values stable/nginx-ingress
There are a lot of values. For a basic install on a cloud provider:
$ helm install stable/nginx-ingress \
--name nginx-ingress \
--namespace kube-system \
--set controller.replicaCount=2 \
--set controller.service.type=LoadBalancer
Output:
NAME: nginx-ingress
LAST DEPLOYED: Tue Mar 14 10:23:41 2017
NAMESPACE: kube-system
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-controller 10.100.200.50 <pending> 80:32080/TCP,443:32443/TCP 1s
nginx-ingress-default-backend 10.100.200.51 <none> 80/TCP 1s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-ingress-controller 2 2 2 0 1s
nginx-ingress-default-backend 1 1 1 0 1s
Using a values file
--set works for a few overrides but gets unwieldy fast. Use a values file instead:
# nginx-ingress-values.yaml
controller:
replicaCount: 2
service:
type: LoadBalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-internal: "0.0.0.0/0"
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
$ helm install stable/nginx-ingress \
--name nginx-ingress \
--namespace kube-system \
-f nginx-ingress-values.yaml
Commit that values file to your repo. Now your Helm deployment is reproducible.
Upgrading a release
Changed your values? Upgrade the release in place:
$ helm upgrade nginx-ingress stable/nginx-ingress -f nginx-ingress-values.yaml
Helm tracks revisions, so if something goes wrong:
$ helm rollback nginx-ingress 1
Rollback was a success! Happy Helming!
1 is the revision number. Check history with:
$ helm history nginx-ingress
REVISION STATUS CHART DESCRIPTION
1 SUPERSEDED nginx-ingress-0.8.9 Install complete
2 DEPLOYED nginx-ingress-0.8.9 Upgrade complete
Listing and deleting releases
$ helm list
NAME REVISION STATUS CHART NAMESPACE
nginx-ingress 2 DEPLOYED nginx-ingress-0.8.9 kube-system
Delete a release (keeps history):
$ helm delete nginx-ingress
release "nginx-ingress" deleted
Delete and purge (removes history, frees the name):
$ helm delete nginx-ingress --purge
Once you start using Helm you won't want to go back to managing raw manifests for anything with more than a handful of resources. The templating alone is worth it — parameterizing image tags for your CI/CD pipeline is trivial once everything's a chart.
