Getting Started with Using Helm to Deploy Apps on Kubernetes
Tyler Britten
Helm is a tool to help you define, install, and upgrade applications running on Kubernetes. For more information, be sure to check out Helm: What Is It?
In this guide you’ll deploy a simple application using Helm to a Kubernetes cluster.
Before You Begin
There are a few things you need to do before getting started with Helm:
-
Have access to a Kubernetes cluster. If you don’t, you can use local options like Docker Desktop or Minikube.
-
Check out Getting Started with Kubernetes on KubeAcademy, particularly if you’ve never worked with Kubernetes before.
-
Follow the documentation for installing Helm.
Helm leverages your local Kubernetes context to operate, so it will have whatever permissions the account you’re using for kubectl
does.
If you read about Helm and come across references to tiller
, previous versions (before version 3) required an extra component installed on the Kubernetes cluster.
Initial Helm Setup
You’re going to need a chart to deploy with Helm, so the easiest thing is to connect to a chart repository with the helm repo
command.
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Now that you have a repo connected, you need to see which charts you have available to deploy.
$ helm search repo bitnami
NAME CHART VERSION APP VERSION DESCRIPTION
bitnami/bitnami-common 0.0.8 0.0.8 Chart with custom templates used in Bitnami cha...
bitnami/airflow 5.0.3 1.10.9 Apache Airflow is a platform to programmaticall...
bitnami/apache 7.3.9 2.4.41 Chart for Apache HTTP Server
---- Truncated ----
You can see a whole list of charts, but the output above shows the first three. It shows the name of the chart, the versions, and the descriptions. As you’ll see, there’s both a chart version and an app version. That’s because a chart may be updated and changed separately from the underlying application it is deploying.
Time to Deploy a Chart (Create a Release)
Now that you have Helm configured with a repo, you can deploy a chart. In Helm lingo that’s called creating a release. In this example, you’ll deploy a pretty simple one, like nginx. You can supply a name for your app like you’re going to do here (my app) or you can use the --generate-name
CLI option to have Helm generate one for you.
$ helm install my-app bitnami/nginx
NAME: my-app
LAST DEPLOYED: Mon Mar 9 07:37:28 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get the NGINX URL:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace default -w my-app-nginx'
export SERVICE_IP=$(kubectl get svc --namespace default my-app-nginx --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
echo "NGINX URL: http://$SERVICE_IP/"
After your release is successfully created, you’ll see an output like this with the name, namespace, status, etc. The NOTES
section has specific information about your install; that’s because it’s generated by Helm using a template, too.
You can see what was deployed by using kubectl
.
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/my-app-nginx-655b5cfc8c-mfhcb 1/1 Running 0 2m38s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-app-nginx LoadBalancer 10.0.2.51 104.197.x.x 80:30291/TCP,443:31827/TCP 2m38s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app-nginx 1/1 1 1 2m38s
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-app-nginx-655b5cfc8c 1 1 1 2m38s
You can see the external IP of your application listed, but if you follow the instructions in the notes, you should see the same as well.
$ export SERVICE_IP=$(kubectl get svc --namespace default my-app-nginx --template "{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}")
$ echo "NGINX URL: http://$SERVICE_IP/"
NGINX URL: http://104.197.x.x/
$ curl $SERVICE_IP
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
You can see which releases are deployed using helm list
.
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-app default 1 2020-03-09 08:07:53.54657 -0400 EDT deployed nginx-5.1.9 1.16.1
It shows all the relevant information. Anytime you update a release, the revision number will increment.
You can clean up by removing the app with uninstall.
$ helm uninstall my-app
release "my-app" uninstalled
Changing the Values
Now you have a working nginx app, but maybe you don’t want it exposed externally via a load balancer. You can delete this app and redeploy it with ClusterIP
instead of LoadBalancer
.
Helm charts have a set of default values; the ones for this chart can be seen in its GitHub repository. If you look there, you’ll see the value you want to change is service.type
. You can now install that same chart using the --set
flag to configure it.
$ helm install my-app bitnami/nginx --set service.type=ClusterIP
NAME: my-app
LAST DEPLOYED: Mon Mar 9 08:07:53 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get the NGINX URL:
echo "NGINX URL: http://127.0.0.1:8080/"
kubectl port-forward --namespace blog svc/my-app-nginx 8080:80
Notice how the NOTES
section changed? It’s a template, too. You can see here that changing the service type changed the output.
In this instance you supplied the value via the CLI, but you could have also put it into a values.yaml
file and used the --values
CLI option. This is a common practice for when you want to supply numerous values to the chart, and/or you want to keep track of what you’re deploying by checking the file into a version control system. The easiest way to get started with your values file is to download the default one from the chart repository, like this one for the nginx chart you deployed. Any value you aren’t changing can be deleted from the file as it will be supplied by the default values.
If you wanted to do that to get the same results as above you’d create a my-app-values.yaml
file with these contents:
## NGINX Service properties
##
service:
## Service type
##
type: ClusterIP
The command to create the release would then be:
$ helm install my-app bitnami/nginx --values my-app-values.yaml
Upgrading a Release
Anytime you want to change anything about a release—be it a configuration value for the chart, an upgrade to the chart itself, or the application version—you’ll run helm upgrade
.
For your nginx chart, you can try this by changing a configuration value. Currently the default image pullPolicy
for this chart is IfNotPresent
. You can change that to Always
via an upgrade.
$ helm upgrade my-app bitnami/nginx --set service.type=ClusterIP,image.pullPolicy=Always
Release "my-app" has been upgraded. Happy Helming!
NAME: my-app
LAST DEPLOYED: Wed Mar 11 13:50:05 2020
NAMESPACE: blog
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
Get the NGINX URL:
echo "NGINX URL: http://127.0.0.1:8080/"
kubectl port-forward --namespace blog svc/my-app-nginx 8080:80
You can see the revision has been incremented. If you get the nginx pod you can see the change of configuration:
$ kubectl get pod my-app-nginx-5bd7878597-pc8jp -o yaml
spec:
containers:
- image: docker.io/bitnami/nginx:1.16.1-debian-10-r46
imagePullPolicy: Always
Why did you have to supply both service.type
and image.pullPolicy
? Because if you hadn’t supplied both, the service type would have tried to revert to the default.
Rollback
What happens if you didn’t want that change or it didn’t work the way you expected? Remember the revision of the releases? You can rollback to a previous revision with helm rollback
. If you want, you can do a --dry-run
first to see if the rollback would even work.
$ helm rollback my-app 1 --dry-run
Rollback was a success! Happy Helming!
$ helm rollback my-app 1
Rollback was a success! Happy Helming!
If you check the pod again, you’ll see pullPolicy
is set back to IfNotPreset
.
Get Helming
If you’re ready to start trying to deploy more charts, there are a whole bunch of charts available in a number of different repositories. A current list of repositories in a Helm install might look like this:
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
jetstack https://charts.jetstack.io
elastic https://helm.elastic.co
bitnami https://charts.bitnami.com/bitnami
Happy Helming!