Helm is really a very powerful tool for managing Kubernetes
objects and is widely adopted across various organizations. It is truly a game changer on how Kubernetes objects are being managed.
With a single command, we can install or upgrade multiple related Kubernetes entities together, we need not to worry about how the resources will be created, Helm will do all the heavy lifting for us.
$ helm install [RELEASE_NAME] [REPO]/[CHART]
But the below post is not about the basics of helm or how to install or upgrade a chart, etc. It's about some new ways of getting charts deployed.
Let's say you have a requirement for getting more than 100 charts installed on a specific Kubernetes cluster, what would you do in this scenario?
On top of my head, I can think of a couple of approaches:
Prerequisites:
- A running Kubernetes cluster with proper permissions, here I have used minikube.
- kubectl and helm installed on your machine to interact with the Kubernetes cluster.
Approach 1:
Club inter-related charts into one, as in getting a parent/wrapper chart created which will in turn have the related child charts as dependency. Which mean if we install the parent/wrapper chart it will get all the Kubernetes resources of all the child charts deployed (provided they are marked as enabled in Chart.yaml).
Below is a quick example, wherein I have a 3-Tier application named app01.
- If you notice the output of both the commands in the parent's Chart.yaml I have all three charts listed as dependencies and in the other one, individual charts have their own Kubernetes resources.
$ cat Chart.yaml
apiVersion: v2
name: app01
description: A Helm chart for app01 which contains FE, BE, DB.
version: 0.1.0
appVersion: 1.0.0
dependencies:
- name: webapp
version: "0.1.0"
repository: "file://./charts/webapp"
enabled: true
- name: backend
version: "0.1.0"
repository: "file://./charts/backend"
enabled: true
- name: database
version: "0.1.0"
repository: "file://./charts/database"
enabled: true
$ tree
.
├── Chart.yaml
├── charts
│ ├── backend
│ │ ├── Chart.yaml
│ │ ├── charts
│ │ ├── templates
│ │ │ ├── _helpers.tpl
│ │ │ ├── deployment.yaml
│ │ │ ├── hpa.yaml
│ │ │ ├── ingress.yaml
│ │ │ ├── service.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── values.yaml
│ ├── database
│ │ ├── Chart.yaml
│ │ ├── charts
│ │ ├── templates
│ │ │ ├── _helpers.tpl
│ │ │ ├── deployment.yaml
│ │ │ ├── hpa.yaml
│ │ │ ├── ingress.yaml
│ │ │ ├── service.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── values.yaml
│ └── webapp
│ ├── Chart.yaml
│ ├── charts
│ ├── templates
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ ├── hpa.yaml
│ │ ├── ingress.yaml
│ │ ├── service.yaml
│ │ └── serviceaccount.yaml
│ └── values.yaml
└── values.yaml
10 directories, 26 files
- When we install the parent chart it will get all the Kubernetes resources deployed.
$ helm install app01 ./app01/
NAME: app01
LAST DEPLOYED: Sat Dec 2 00:14:50 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
$ helm list -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
app01 default 1 2023-12-02 00:14:50.075444065 +0530 IST deployed app01-0.1.0 1.0.0
$ k get all
NAME READY STATUS RESTARTS AGE
pod/app01-backend-965cb9b5b-q7gqv 1/1 Running 0 17m
pod/app01-database-56bdbcd49c-bh4s2 1/1 Running 0 17m
pod/app01-webapp-5b67db8bdf-m6psg 1/1 Running 0 17m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/app01-backend ClusterIP 10.107.53.8 <none> 8080/TCP 17m
service/app01-database ClusterIP 10.104.173.124 <none> 3306/TCP 17m
service/app01-webapp ClusterIP 10.111.168.18 <none> 80/TCP 17m
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/app01-backend 1/1 1 1 17m
deployment.apps/app01-database 1/1 1 1 17m
deployment.apps/app01-webapp 1/1 1 1 17m
NAME DESIRED CURRENT READY AGE
replicaset.apps/app01-backend-965cb9b5b 1 1 1 17m
replicaset.apps/app01-database-56bdbcd49c 1 1 1 17m
replicaset.apps/app01-webapp-5b67db8bdf 1 1 1 17m
- Another thing to note here is now we have 4 values.yaml files (one for each child chart and one for the parent helm chart).
- And the good part here is using just one parent's values.yaml file we can manage all 3 of them.
- Make sure in parent's values.yaml, the child chart's values are indented correctly, and they are indented under specific chart name as mentioned in Chart.yaml under
.dependencies[*].name
$ cat values.yaml
webapp:
replicaCount: 2
database:
replicaCount: 1
backend:
replicaCount: 3
- Here we are just updating the replicaCount of all child charts and are upgrading the release.
$ helm upgrade --install app01 ./app01/
Release "app01" has been upgraded. Happy Helming!
NAME: app01
LAST DEPLOYED: Sat Dec 2 01:21:56 2023
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
- As specified in parent chart values.yaml, the replicaCount is now increased to 2,3 respectively.
$ k get deploy; k get pods
NAME READY UP-TO-DATE AVAILABLE AGE
app01-backend 3/3 3 3 105m
app01-database 1/1 1 1 105m
app01-webapp 2/2 2 2 105m
NAME READY STATUS RESTARTS AGE
app01-backend-965cb9b5b-dg6gq 1/1 Running 0 38m
app01-backend-965cb9b5b-q7gqv 1/1 Running 0 105m
app01-backend-965cb9b5b-z92c8 1/1 Running 0 38m
app01-database-56bdbcd49c-bh4s2 1/1 Running 0 105m
app01-webapp-5b67db8bdf-c25kc 1/1 Running 0 38m
app01-webapp-5b67db8bdf-m6psg 1/1 Running 0 105m
- As you see here with a single command, we deployed multiple helm charts and using a single values.yaml file we have the ability to manage all of them.
Approach 2:
Using helmfile.
Approach 3:
Using bash or any other scripting language (I am planning to write a simple utility to accomplish this).
Further, I am in the process of writing another article around Approach 2 and 3, plus there can be multiple other approaches for getting this accomplished (feel free to share your thoughts and comments).
Happy learning :)
PS: The cover image is created using canva.
Top comments (4)
Here goes approach 3:
Here goes approach 2:
For the Chart.yaml inside the dependencies, do I need to specify the dependency too? e.g. in backend's Chart.yaml, dependencies is database and frontend
nice article