Skip to main content

Getting Started with Helm

Written on January 25, 2018 by Ron Rivera.

5 min read
––– views

In my previous post I shared how to setup a Kubernetes cluster using Kubespray. Now that it is up and running, how do we run and manage applications on it?

Deploying an application in Kubernetes can involve creating multiple resources such pods, deployments and services with each requiring a handcrafted YAML manifest file. This is no fun and wasn't really maintanable in the long term.

This post illustrates how to setup and configure Helm to easily perform key operations for managing applications such as install, upgrade or delete onto a Kubernetes cluster.

Install and Configure Helm

Helm is comprised of two components: helm (client) and tiller (server). Let's go through the steps to install and configure them.

Install helm

curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh
Helm v2.12.1 is available. Changing from version v2.7.2.
Downloading https://kubernetes-helm.storage.googleapis.com/helm-v2.12.1-darwin-amd64.tar.gz
Preparing to install helm and tiller into /usr/local/bin
Password:
helm installed into /usr/local/bin/helm
tiller installed into /usr/local/bin/tiller
Run 'helm init' to configure helm.

Initialize helm and tiller

$ helm init
$HELM_HOME has been configured at /Users/ron/.helm.
 
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
 
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

To confirm helm is installed correctly, run helm version.

Deploy a Chart

Let's first make sure we have the latest list of charts.

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete.  Happy Helming!⎈

Install the Ghost chart

$ helm install --name myghost stable/ghost
NAME:   myghost
LAST DEPLOYED: Thu Jan 25 00:25:09 2018
NAMESPACE: default
STATUS: DEPLOYED
 
RESOURCES:
==> v1/Service
NAME             TYPE          CLUSTER-IP    EXTERNAL-IP  PORT(S)       AGE
myghost-mariadb  ClusterIP     10.108.78.96  <none>       3306/TCP      1s
myghost          LoadBalancer  10.98.84.189  <pending>    80:32234/TCP  1s
 
==> v1beta1/StatefulSet
NAME             DESIRED  CURRENT  AGE
myghost-mariadb  1        1        1s
 
==> v1/Pod(related)
NAME               READY  STATUS   RESTARTS  AGE
myghost-mariadb-0  0/1    Pending  0         0s
 
==> v1/Secret
NAME             TYPE    DATA  AGE
myghost-mariadb  Opaque  2     1s
myghost          Opaque  1     1s
 
==> v1/ConfigMap
NAME                   DATA  AGE
myghost-mariadb        1     1s
myghost-mariadb-tests  1     1s
 
==> v1/PersistentVolumeClaim
NAME     STATUS  VOLUME                                    CAPACITY  ACCESS MODES  STORAGECLASS  AGE
myghost  Bound   pvc-fcf13dfa-1411-11e9-a7fd-080027d05461  8Gi       RWO           standard      1s
 
 
NOTES:
###############################################################################
### ERROR: You did not provide an external host in your 'helm install' call ###
###############################################################################
 
This deployment will be incomplete until you configure Ghost with a resolvable
host. To configure Ghost with the URL of your service:
 
1. Get the Ghost URL by running:
 
  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w myghost'
 
  export APP_HOST=$(kubectl get svc --namespace default myghost --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
  export APP_PASSWORD=$(kubectl get secret --namespace default myghost -o jsonpath="{.data.ghost-password}" | base64 --decode)
  export APP_DATABASE_PASSWORD=$(kubectl get secret --namespace default myghost-mariadb -o jsonpath="{.data.mariadb-password}" | base64 --decode)
 
2. Complete your Ghost deployment by running:
 
  helm upgrade myghost stable/ghost\
    --set service.type=LoadBalancer,ghostHost=$APP_HOST,ghostPassword=$APP_PASSWORD,mariadb.db.password=$APP_DATABASE_PASSWORD

Releases

A release is created each time a chart is installed.

Display existing releases

$ helm ls
NAME   	REVISION	UPDATED                 	STATUS  	CHART      	APP VERSION	NAMESPACE
myghost	1       	Thu Jan 25 00:25:09 2018	DEPLOYED	ghost-6.2.0	2.9.1      	default

Upgrade an existing release

$ helm upgrade myghost stable/ghost
Release "myghost" has been upgraded. Happy Helming!
LAST DEPLOYED: Thu Jan 25 00:28:19 2018
NAMESPACE: default
STATUS: DEPLOYED
 
RESOURCES:
==> v1/Secret
NAME             TYPE    DATA  AGE
myghost-mariadb  Opaque  2     3m10s
myghost          Opaque  1     3m10s
 
==> v1/ConfigMap
NAME                   DATA  AGE
myghost-mariadb        1     3m10s
myghost-mariadb-tests  1     3m10s
 
==> v1/PersistentVolumeClaim
NAME     STATUS  VOLUME                                    CAPACITY  ACCESS MODES  STORAGECLASS  AGE
myghost  Bound   pvc-fcf13dfa-1411-11e9-a7fd-080027d05461  8Gi       RWO           standard      3m10s
 
==> v1/Service
NAME             TYPE          CLUSTER-IP    EXTERNAL-IP  PORT(S)       AGE
myghost-mariadb  ClusterIP     10.108.78.96  <none>       3306/TCP      3m10s
myghost          LoadBalancer  10.98.84.189  <pending>    80:32234/TCP  3m10s
 
==> v1beta1/StatefulSet
NAME             DESIRED  CURRENT  AGE
myghost-mariadb  1        1        3m10s
 
==> v1/Pod(related)
NAME               READY  STATUS   RESTARTS  AGE
myghost-mariadb-0  1/1    Running  0         3m9s
 
 
NOTES:
###############################################################################
### ERROR: You did not provide an external host in your 'helm install' call ###
###############################################################################
 
This deployment will be incomplete until you configure Ghost with a resolvable
host. To configure Ghost with the URL of your service:
 
1. Get the Ghost URL by running:
 
  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        Watch the status with: 'kubectl get svc --namespace default -w myghost'
 
  export APP_HOST=$(kubectl get svc --namespace default myghost --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
  export APP_PASSWORD=$(kubectl get secret --namespace default myghost -o jsonpath="{.data.ghost-password}" | base64 --decode)
  export APP_DATABASE_PASSWORD=$(kubectl get secret --namespace default myghost-mariadb -o jsonpath="{.data.mariadb-password}" | base64 --decode)
 
2. Complete your Ghost deployment by running:
 
  helm upgrade myghost stable/ghost\
    --set service.type=LoadBalancer,ghostHost=$APP_HOST,ghostPassword=$APP_PASSWORD,mariadb.db.password=$APP_DATABASE_PASSWORD
 
$ helm ls
NAME   	REVISION	UPDATED                 	STATUS  	CHART      	APP VERSION	NAMESPACE
myghost	2       	Thu Jan 25 00:28:19 2018	DEPLOYED	ghost-6.2.0	2.9.1      	default

Uninstall a release

$ helm delete myghost
release "myghost" deleted
Tweet this article

Join my newsletter

Get notified whenever I post, 100% no spam.

Subscribe Now