Kubernetes, Helm, & Odoo

Setting up Kubernetes and Helm on GKE with Odoo as a sample application.


This is a practical introduction to setting up and using Kubernetes, which includes setting it up on Google Kubernetes Engine, installing Helm and Tiller with TLS, installing Nginx and Cert-Manager for TLS secured ingresses, and finally installing Odoo as an example application.

What This Tutorial Covers

What This Tutorial Covers
  1. Creating A Cluster On Google Kubernetes Engine
  2. Installing Helm and Tiller For Launching Applications On Kubernetes
  3. Installing Nginx and Cert-Manager For TLS Ingresses
  4. Installing Odoo As An Example

What You Need For This Tutorial

What You Need For This Tutorial

A Google Cloud Platform account

GKE: Google Kubernetes Engine

Google Kubernetes Engine makes launching clusters incredibly easy, but first you need to set up your computer to communicate with your Google Cloud Platform (GCP) account and Kubernetes. To communicate with Google, we'll install gcloud and to communicate with Kubernetes, we'll install kubectl.

Go here, and follow the instructions to install gcloud on your computer: https://cloud.google.com/sdk/install.

You can either install kubectl using gcloud, or using some other method, like a package manager or downloading a binary. All methods are listed here: https://kubernetes.io/docs/tasks/tools/install-kubectl/#install-kubectl. The command for using gcloud to install kubectl is:

gcloud components install kubectl

Run the command below to get credentials for accessing your GCP account.

gcloud auth application-default login

You need a Google project under which to create a cluster. You can do this using the GCP console online at https://console.cloud.google.com or using the command below. Btw, (maybe a duh moment, but...) you can always append --help to the command to learn about what flags and arguments are available for that command.

gcloud projects create ${PROJECT}

Now you need to set your default project and zone for gcloud. You can always override these in commands with the --project and --zone flags if you need. The zone is the geographic location of where you want your resources deployed (literally which Google server farm to use). You can get a list of available zones with: gcloud compute zones list.

gcloud config set project ${PROJECT}
gcloud config set compute/zone ${ZONE}

Okay, finally it's time to create a Kubernetes cluster. Again, you can either go to the GCP console, select "Kubernetes Engine", and create a cluster or you can enter the command below. You can also generate the command from the GCP console. I didn't see an option to enable autoscaling from the console, you may have to add the following arguments yourself: --enable-autoscaling --min-nodes 2 --max-nodes 5

The last thing to do is grab the credentials to send commands to your new cluster, as well as create a cluster role binding for your gcloud user to in your cluster.

gcloud container clusters get-credentials ${CLUSTER}

kubectl create clusterrolebinding cluster-admin-binding \
  --clusterrole cluster-admin --user $(gcloud config get-value account)


Now we're going to install Helm, which we'll use to deploy applications on a cluster. If you come from the Docker world, Helm is basically the equivalent of Docker Compose. Since an application is often built up of multiple resources, like deployments, services, ingresses, etc., a Helm "chart" contains the definition of all those resources and deploys them together so you don't have to do it one by one.

Install the helm client on your computer with:

curl https://raw.githubusercontent.com/helm/helm/master/scripts/get | bash

Create a service account and a cluster role binding for Tiller. Tiller is a service that deploys and manages your helm chart on your cluster. It's different from Helm, which is really just a command line tool for sending commands to Tiller.

kubectl create serviceaccount -n kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

It's really important to encrypt your helm charts with TLS when you send them to your cluster. To do that, we need to create a certificate authority and two certificates, one for Tiller and the other for Helm. I use the script to below to create my certificates. To use it, add it to a file named tls, place the file somewhere in your $PATH, and make it executable.

Now you can run the following commands:

tls -p secrets/ca -n ca -d ${DOMAIN} -e 3650 -a
tls -p secrets/tiller -n tiller -d tiller.${DOMAIN} -e 3650 -c secrets/ca/ca
tls -p secrets/helm -n helm -d helm.${DOMAIN} -e 3650 -c secrets/ca/ca

Now we can initialize Tiller with the following command:

helm init \
  --tiller-tls \
  --tiller-tls-cert secrets/tiller/tiller.crt \
  --tiller-tls-key secrets/tiller/tiller.key \
  --tiller-tls-verify \
  --tls-ca-cert secrets/ca/ca.crt \
  --service-account tiller \

Check that Tiller is running and that you can connect with Helm:

kubectl get --all-namespaces pods -n kube-system
helm ls --tls \
  --tls-ca-cert secrets/ca/ca.crt \
  --tls-cert secrets/helm/helm.crt \
  --tls-key secrets/helm/helm.key

So that we don't have to specify the location of our secrets all the time, copy them into your the home directory of Helm:

cp secrets/ca/ca.crt $(helm home)/ca.pem
cp secrets/helm/helm.crt $(helm home)/cert.pem
cp secrets/helm/helm.key $(helm home)/key.pem 

Now you should be able to connect with just helm ls --tls. Finally, update your helm repos (this basically like the update command in most package managers):

helm repo update


Nginx is a common and simple proxy server for directing web traffic to a service on your cluster. Installing it is now incredibly simple with Helm. We're going to add it to the namespace "odoo" since we're going to use it for that application.

helm install --tls \
  --name nginx \
  --namespace odoo \


Cert-Manager is for creating TLS certificates that Nginx will use to enable HTTPS connections. Again, super simple to install with Helm. The first command is to create Custom Resource Definitions that Cert Manager uses.

kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.6/deploy/manifests/00-crds.yaml
helm install --tls \
  --name cert-manager \
  --namespace odoo \

Now we need to create a Cluster Issuer, which is essentially a service that will create and manage our certificates. In order for the Cluster Issuer to verify that you have control over the domain names you want to create certificates for, we need to create a GCP IAM service account that can access our Cloud DNS. To do this, follow these steps:

  1. Go to the GCP cloud console and click "IAM", then "Service accounts".
  2. Click on "+ Create Service Account"
  3. On part 1, give it the name "kube-cert-sa"
  4. On part 2, when assigning permissions, give it the role of "DNS Administrator" under the "DNS" category.
  5. On part 3, choose "Create Key"
  6. Copy the contents of the key into a file named kube-cert-sa.key.json in a local folder called secrets

Now, create the following yml files. They define Cluster Issuers for Google Cloud Platform. Although we'll only use the staging Cluster Issuer for testing, I'm including the production version in case you need it. Make sure you add your own email and project name.

Now create them by applying the manifests:

kubectl apply -f clusterIssuerStaging.yml
kubectl apply -f clusterIssuerProduction.yml

With the Cluster Issuers installed, we won't have to create certificates manually. Instead, they'll watch for specific annotatations, and when they exist, they'll auto-generate your certificates.


Odoo is an open source suite of business tools. For businesses wanting a low cost, self-hosted solution, you can launch Odoo on your own Kubernetes cluster. First create the following file with the name odoo.yml in a directory called odoo. Make sure you replace the variables in the file:

Now we'll create Odoo in our cluster using that configuration file:

helm install --tls \
  --name odoo \
  -f odoo/odoo.yml \

It might take a little while for all of the Odoo services to deploy. The final step is to create an ingress to make Odoo accessible from the internet. Create the following file with the name odoo-Ingress.yml in your odoo directory. Make sure you add your own domain, the one you created a DNS entry for (probably odoo.${DOMAIN}). The "tls", "hosts" annotation should automatically be detected by Cert-Manager and it should create the appropriate TLS certificate for it.

And finally, create the ingress by applying it:

kubectl apply -f odoo/odoo-Ingress.yml

Important! You need to create a DNS entry that routes the domain you want to use to Odoo. So for instance, you need to create an A record that points odoo.${DOMAIN} to the IP address that is assigned to your Odoo ingress. You can figure that out through the GCP console or by using the kubectl describe command on your ingress.

Now when you go to your Odoo domain. You should see the log in screen. If you don't see it. You can check on the status of Odoo with the following command:

helm status --tls odoo


That's a quick run through of how to set up Kubernetes with Helm on GKE, along with an example of what launching applications looks like. In the near future, I'll be adding blog entries for the following topics:

So keep in touch!