Enabling GitOps in k8s with Helm Controller (CRD).
A couple of months ago I was trying to run k8s on a raspberry pi @ home, that was when I first met k3s, and their neat way to deploy helm charts completely fascinated me. They called it helm-controller. It was so simple, so…… tiller-less. Back then helm v3 was not around so that was a game changer then. Currently the tiller is no longer a problem, how ever when you try to automate chart deployments with a pipeline you still need to maintain some state.
If you are not familiar with what rancher’s k3s or helm-controller I would suggest you go take a look at this article first and then (once you are amazed) come back and continue reading this piece.
So now that I knew this was possible I wanted to deploy everywhere in this fashion, but not all k8s flavors come with a “helm-controller“ right out-of-the-box.
The solution was simple go and that deployed in my k8s cluster and enjoy it. How ever simple not necessarily means easy. I had to work it a little bit to get that running on my cluster.
Here is how I did it. Note that these steps will deploy RBAC settings, the CRD and the deployment that watches the CRD in the helm-controller namespace. You probably will need to adjust some settings to your environment.
In this example, I will be deploying bitnami’s nginx chart.
First deploy the CRD, RBAC and helm-controller deployment.
$ kubectl apply -f https://raw.githubusercontent.com/iotops/helm-controller/master/manifests/deploy-namespaced.yamlnamespace/helm-controller created
customresourcedefinition.apiextensions.k8s.io/helmcharts.helm.cattle.io created
deployment.apps/helm-controller created
clusterrole.rbac.authorization.k8s.io/helm-controller created
clusterrolebinding.rbac.authorization.k8s.io/helm-controller created
Verify everything is there.
$ kubectl get all -n helm-controller
NAME READY STATUS RESTARTS AGE
pod/helm-controller-86dd4bc695-jjj28 1/1 Running 0 12mNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/helm-controller 1/1 1 1 12mNAME DESIRED CURRENT READY AGE
replicaset.apps/helm-controller-86dd4bc695 1 1 1 12m$ kubectl api-resources | grep -i helm
helmcharts helm.cattle.io true HelmChart
With the helm controller installed lets deploy the following manifest.
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: nginx
namespace: helm-controller
spec:
chart: https://charts.bitnami.com/bitnami/nginx-5.1.4.tgz
targetNamespace: default
This manifest can be download, git cloned or simply deployed from the web as follows.
$ kubectl apply -f https://raw.githubusercontent.com/iotops/helm-controller/master/manifests/example-helmchart.yamlhelmchart.helm.cattle.io/nginx created
Lets check nginx was deployed.
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-d58c4d75d-lbhkd 1/1 Running 0 94sNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 27m
service/nginx LoadBalancer 100.70.186.15 a54156bcaa24642e48c398d99b8e8b07-143731831.us-east-2.elb.amazonaws.com 80:31948/TCP,443:30058/TCP 94sNAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 1/1 1 1 95sNAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-d58c4d75d 1 1 1 95s
Let's open that elb address on a web browser.
The chart can easily be updated and deleted with the same manifest, it can also be patched and edited with regular kubectl magic.
Lest remove the chart now.
$ kubectl delete -f https://raw.githubusercontent.com/iotops/helm-controller/master/manifests/example-helmchart.yamlhelmchart.helm.cattle.io "nginx" deleted$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 100.64.0.1 <none> 443/TCP 34m
With the helm-controller charts can be easily installed in a gitops approach with out maintaining states in the deployer's host. The manifest also allows to overwrite default chart's values individually or by a whole different values.yaml file.
I hope you enjoyed this article.