Wilson Mar bio photo

Wilson Mar

Hello. Hire me!

Email me Calendar Skype call 310 320-7878

LinkedIn Twitter Gitter Instagram Youtube

Github Stackoverflow Pinterest

Package manager for Kubernetes

Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Cyrillic Russian   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean


This article is a hands-on introduction about using Helm Charts to group multiple Kubernetes objects into one unit used to stand up Kubernetes clusters.

helm.sh says helm is a package manager for Kubernets like Brew on macOS, Chocolately on Windows, apt on Debian/Ubuntu, yum on Red Hat, etc. Helm is is a cloud industry consortium composed of Google, Microsoft, Bitnami, and others.

Helm has become popular with cloud developers largely because it simplifies Kubernetes application management, the roll out of updates, and options to share applications. Package management features make it easier to:

  • search available packages -
  • provide information on packages
  • download and install packages, along with dependencies, creation of folders, and insertion of those folders in the system’s PATH variable
  • list installed packages
  • lint installed packages
  • update existing installed packages
  • delete packages

Helm works with “Charts” which are a set of files defined as curated applications for Kubernetes.

Helm is made of two components:

  1. Tiller server running inside your Kubernetes cluster to manage (install, upgrade, query, and remove) Kubernetes resources via calls to the Kubernetes API server.

  2. helm CLI client running on your local machine. It sends requests to Tiller. A CLI client is needed because operations such as rollback, running chart tests, etc. are done from the helm CLI client.


Helm CLI client

On your Terminal on any folder:

  1. See whether you already have it installed:

    minikube version

    If you see something like this, you already have it installed:

    minikube version: v1.3.0
    commit: 43969594266d77b555a207b0f3e9b3fa1dc92b1f
  2. What is the latest Kubernetes minikube CLI client for macOS?

    brew info minikube

    Response at time of writing:

    Found a cask named "minikube" instead.
    minikube: 1.4.0
    /usr/local/Caskroom/minikube/1.3.0 (54.1MB)
    From: https://github.com/Homebrew/homebrew-cask/blob/master/Casks/minikube.rb
    ==> Name
    ==> Artifacts
    minikube-darwin-amd64 -> minikube (Binary)

    PROTIP: Brew commands need to contain “cask” for GUI packages.

  3. To install Kubernetes minikube CLI client for the first time:

    brew cask install minikube

    To upgrade Kubernetes minikube CLI client (if brew info returned a version):

    brew cask upgrade minikube

    Sample response:

    ==> Downloading https://storage.googleapis.com/minikube/releases/v1.4.0/minikube-darwin-amd64

    Obtain the version again after an upgrade, such as:

    minikube version: v1.4.0
    commit: 7969c25a98a018b94ea87d949350f3271e9d64b6
  4. You may need to:

    brew link --overwrite kubernetes-cli


    Linking /usr/local/Cellar/kubernetes-cli/1.15.2... 229 symlinks created
  5. Get started:

    minikube start

    On Windows, add <pre>–vm-driver hyperkit</pre>

    Example response:

    😄  minikube v1.4.0 on Darwin 10.14.6
    👍  Upgrading from Kubernetes 1.15.2 to 1.16.0
    💿  Downloading VM boot image ...
     > minikube-v1.4.0.iso.sha256: 65 B / 65 B [--------------] 100.00% ? p/s 0s
     > minikube-v1.4.0.iso: 135.73 MiB / 135.73 MiB [-] 100.00% 27.63 MiB p/s 5s

    If you also see:

    💣  Unable to start VM: Error getting state for host: exit status 126
    😿  Sorry that minikube crashed. If this was unexpected, we would love to hear from you:
    👉  https://github.com/kubernetes/minikube/issues/new/choose
  6. Get the status:

    minikube service list

    Sample response:

    Get dial tcp getsockopt: no route to host
    Check that minikube is running and that you have specified the correct namespace (-n flag) if required.
  7. Get the status:

    minikube status

    If you get “💣 Error getting host status: state: exit status 126”

    The expected response is like this:

    minikube: Running
    cluster: Running
    kubectl: Correctly Configured: pointing to minikube-vm at

    PROTIP: IP address is used by docker-machine.

    See https://www.jhipster.tech/tips/020_tip_using_docker_containers_as_localhost_on_mac_and_windows.html

    docker-machine stop default


  8. Verify:

    kubectl version

    Example response:

    Client Version: version.Info{Major:”1”, Minor:”15”, GitVersion:”v1.15.2”, GitCommit:”f6278300bebbb750328ac16ee6dd3aa7d3549568”, GitTreeState:”clean”, BuildDate:”2019-08-05T16:54:35Z”, GoVersion:”go1.12.7”, Compiler:”gc”, Platform:”darwin/amd64”}

    If you also see “Unable to connect to the server: dial tcp i/o timeout” ???

  9. On any folder, install Helm CLI client on MacOS:

  10. Confirm the helm release installed:

    helm version


    # Client: &version.Version{SemVer:"v2.14.3", 
    # GitCommit:"0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085", GitTreeState:"clean"}
  11. Set the IP randomly:

    minikube update-context

  12. Establish the context:

    kubectl config current-context

    On macOS the response is a single-node Kubernetes cluster running locally:


    See https://kubernetes.io/docs/setup/learning-environment/minikube/

    NOTE: The Helm RBAC guide at https://github.com/helm/helm/blob/master/docs/rbac.md has more secure and advanced RBAC configurations.

    Alternately, on Google, Azure, AWS ….

    Tip: eksctl is a useful CLI for setting up Kubernetes clusters on Amazon EKS

    Once minikube is installed, start minikube with the kubeadm bootstrapper. The kubeadm toolkit helps to easily bootstrap a cluster so that appropriate privileges are granted for performing read-write operations on Kubernetes authentication and authorization (RBAC) resources.

    minikube start --vm-driver=virtualbox --bootstrapper=kubeadm --memory 4096
  13. Optionally, enable Ingress on minikube with this command

    minikube addons enable ingress
  14. Be in a folder where the sample can be created.

    • Navigate to or create a folder to create a repo.
    • Remove the previous folder “hellos” to begin new.
    • Create folder “hellos”.

  15. Verify whether the Kubernetes cluster is running and accessible through kubectl for Helm to use:

    kubectl cluster-info

    This can take several minutes and return:

    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    Unable to connect to the server: dial tcp i/o timeout
    kubectl get nodes
  16. Verify the Kubernetes cluster is empty.

    kubectl get deployments,pods,services

    Helm init

  17. install tiller with the helm init command of the CLI tool: ??? *

    kubectl config use-context docker-for-desktop
  18. Initialize helm by installing a Tiller deployment to Kubernetes clusters and communicates via gRPC:

    helm init


    $HELM_HOME has been configured at /Users/wilsonmar/.helm.

    PROTIP: v2 of Helm gives full administrative rights to Tiller - which is a risk if somebody gets unauthorized access to the cluster. V3 of Helm is tillerless. See https://rimusz.net/tillerless-helm about the “Tillerless” Helm v2 plugin for helm tiller start

    Search throu Helm repos

    As of this writing, 2,307 contributors submitted Charts into the community-curated repository at https://github.com/helm/charts.

    Charts there are stored in one of two folders. Charts begin under incubator and get moved to stable.

    Examples in the stable folder:

    • https://github.com/helm/charts/tree/master/stable/distributed-jmeter
    • https://github.com/helm/charts/tree/master/stable/influxdb
    • https://github.com/helm/charts/tree/master/stable/jenkins
    • https://github.com/helm/charts/tree/master/stable/magento
    • https://github.com/helm/charts/tree/master/stable/mariadb

    Other Helm Charts repositories include:

    But the Helm Workspace is the default:

  19. Search for ???

    helm search xxxx

    The default scope is only the stable folder.

  20. Add charts in the incubator folder for your local client, run helm repo add:

    helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/

    Response: “incubator” has been added to your repositories


  21. Create a simple built-in helm Chart:

    helm create xxxx
    cd xxxx

    Alternately, a real one would be like:

    helm install stable/hello --name hello1 --namespace hellos

    https://www.youtube.com/watch?v=9cwjtN3gkD4 https://matthewpalmer.net/kubernetes-app-developer/ 105 pages

  22. Lint it:

    helm lint ./hello-world
  23. Look inside:

    cd hello-world
  24. List folders and files created:

     |-- Chart.yaml
     |-- charts
     |-- templates
     |   |-- NOTES.txt
     |   |-- _helpers.tpl
     |   |-- deployment.yaml
     |   |-- ingress.yaml
     |   |-- service.yaml
     |   `-- tests
     |       `-- test-connection.yaml
     `-- values.yaml
    4 directories, 8 files

    NOTE: Folders and file names must be names shown.

    Chart.yaml - contains metadata about folders and files in the Chart, such as its name, version, keywords. Notice the file name begins with a capital C.

    PROTIP: A running instance of a Chart with a specific config is called a release.

    templates directory where Kubernetes resources are defined, as templates which contain variables defined in Go template format.

    values.yaml contains keys and default values used to generate the release in your Cluster. These values are replaced in resource manifests.

    • https://helm.sh/docs/chart_template_guide/#built-in-objects
    • https://helm.sh/docs/chart_template_guide/#variables

    configMap.yaml contains database configuration.

    secrets.yaml stores database passwords as secrets.

    charts is an optional directory. It may contain sub-charts.

    .helmignore defines patterns to ignore when packaging (like .gitignore)

  25. Add a README.md file for attributions, version info, and such.

  26. Look in the template directory for sample templates for common Kubernetes resources:

    • deployment.yaml
    • service.yaml
    • ingress.yaml

  27. Render the template locally:

    helm template ./hello-world
  28. Check if the server is available:

    kubectl get deployments --namespace hellos

    https://hub.kubeapps.com/charts/stable/gocd (managed by Bitnami) provides a

gocd-helm-648x257 [5]

A. Install GoCD as a Kubernetes native application with an officially supported helm chart B. Scale GoCD agents seamlessly with the new ElasticAgent plugin that spins up agents on the fly in response to build workload C. Design Docker-based build workflows as Docker in Docker

kubectl config current-context
   # "minikube" on macOS or "my-cluster"
helm init
   # $HELM_HOME has been configured at /Users/$($username)/.helm.
kubectl get pods --namespace kube-system --selector=app=helm
   # Error: error installing: Post 
   # dial tcp i/o timeout

   # tiller-deploy STATUS Running
helm search gocd  # in hub.helm
   # stable/gocd
helm install stable/gocd --name gocd-live-demo --namespace gocd-live-demo
helm list
helm status gocd  # pre-baked
   # From post-install instructions:
echo "GoCD server public IP: http://$(kubectl get ingress gocd-server --namespace=gocd -0 jasonpath='{.status.loadBalancer ingress [0].ip}')"

References and Learning Resources

[1] In the Kubernetes Blog: Helm Charts: making it simple to package and deploy common applications on Kubernetes October 10, 2016

https://www.katacoda.com/courses/kubernetes/helm-package-manager Helm Package Manager

curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.8.2-linux-amd64.tar.gz pwd = /root helm init helm repo update helm search redis helm inspect stable/redis helm install stable/redis

To get your password run:

export REDIS_PASSWORD=$(kubectl get secret --namespace default alliterating-lightningbug-redis -o jsonpath="{.data.redis-password}" | base64 --decode)

To connect to your Redis server:

  1. Run a Redis pod that you can use as a client:

    kubectl run –namespace default alliterating-lightningbug-redis-client –rm –tty -i –restart=’Never’ \ –env REDIS_PASSWORD=$REDIS_PASSWORD \ –image docker.io/bitnami/redis:5.0.5-debian-9-r95 – bash

  2. Connect using the Redis CLI: redis-cli -h alliterating-lightningbug-redis-master -a $REDIS_PASSWORD redis-cli -h alliterating-lightningbug-redis-slave -a $REDIS_PASSWORD

To connect to your database from outside the cluster execute the following commands:

kubectl port-forward --namespace default svc/alliterating-lightningbug-redis 6379:6379&
redis-cli -h -p 6379 -a $REDIS_PASSWORD

helm ls # If you receive an error that Helm could not find a ready tiller pod, it means that helm is still deploying. Wait a few moments for the tiller Docker Image to finish downloading.

  1. Find out what was deployed: kubectl get all

  2. Wait until a Persistent Volume is available: kubectl apply -f pv.yaml # statefulset.apps/illmannered-grizzly-redis-master 0/1 94s # statefulset.apps/illmannered-grizzly-redis-slave 0/2 94s # persistentvolume/pv-volume1 created
  3. Give Redis permissions to write: chmod 777 -R /mnt/data*
  4. Provide helm with a more friendly name, such as: helm install –name my-release stable/redis

[8] Continuous Delivery with Docker and Kubernetes Aug 20, 2018 [10:36] by Ken Mugrage

https://www.digitalocean.com/community/tutorials/an-introduction-to-helm-the-package-manager-for-kubernetes An Introduction to Helm, the Package Manager for Kubernetes</a> August 6, 2018 by Brian Boucheron


“Helm Package Manager” on Qwiklabs covers installation and configure a Chart (based in MySQL) on GCP.

gcloud container clusters create my-cluster –scopes “https://www.googleapis.com/auth/projecthosting,storage-rw”

kubectl config current-context # gke_qwiklabs-gcp-0286d80b4438f082_us-central1-f_my-cluster

  1. For some more detailed information about the cluster: kubectl cluster-info


Helmsman Desired State Configurator

Open-sourced at https://github.com/Praqma/helmsman, Helmsman from Praqma (by SAMI ALAJRAMI and others) provides an “autopilot” for Kubernetes clusters which automates the lifecycle management of Helm Charts using declarative (desired state) configuration files (DSF) to create, delete, upgrade, and move Kubernetes objects to different namespaces. This approach makes it easier to replicate a CI pipeline. This also takes care of secrets passing (from environment variables to Charts).


The desired state approach achieves idempotentcy - executing Helmsman several times gets the same result, and continues from failures.


[3] CNCF Webinar Series – Getting Helm to be Enterprise-ready Apr 3, 2018

More on DevOps

This is one of a series on DevOps:

  1. DevOps_2.0
  2. ci-cd (Continuous Integration and Continuous Delivery)
  3. User Stories for DevOps

  4. Git and GitHub vs File Archival
  5. Git Commands and Statuses
  6. Git Commit, Tag, Push
  7. Git Utilities
  8. Data Security GitHub
  9. GitHub API
  10. TFS vs. GitHub

  11. Choices for DevOps Technologies
  12. Java DevOps Workflow
  13. AWS DevOps (CodeCommit, CodePipeline, CodeDeploy)
  14. AWS server deployment options

  15. Cloud services comparisons (across vendors)
  16. Cloud regions (across vendors)
  17. AWS Virtual Private Cloud

  18. Azure Cloud Onramp
  19. Azure Cloud
  20. Azure Cloud Powershell
  21. Bash Windows using Microsoft’s WSL (Windows Subystem for Linux)

  22. Digital Ocean
  23. Cloud Foundry

  24. Packer automation to build Vagrant images
  25. Terraform multi-cloud provisioning automation
  26. Hashicorp Vault and Consul to generate and hold secrets

  27. Powershell Ecosystem
  28. Powershell on MacOS
  29. Powershell Desired System Configuration

  30. Jenkins Server Setup
  31. Jenkins Plug-ins
  32. Jenkins Freestyle jobs
  33. Jenkins2 Pipeline jobs using Groovy code in Jenkinsfile

  34. Docker (Glossary, Ecosystem, Certification)
  35. Docker Setup
  36. Dockerize apps
  37. Docker Registry

  38. Maven on MacOSX

  39. Ansible

  40. MySQL Setup

  41. SonarQube static code scan

  42. API Management Microsoft
  43. API Management Amazon

  44. Scenarios for load