Skip to content

Helm#

What Is Helm?#

  • Helm is a package manager for Kubernetes applications. It simplifies the process of defining, installing, and upgrading even the most complex Kubernetes applications. Helm uses a packaging format called "charts," which are a collection of pre-configured Kubernetes resources.

  • Here are the key components and concepts associated with Helm:

Concept Description
Helm A package manager for Kubernetes applications that simplifies application installation and management.
Charts Collections of pre-configured Kubernetes resources defining how to deploy specific applications.
Templates Helm chart components that include Kubernetes resource manifests with placeholders for customization.
Values Parameters allowing customization of Helm charts during installation without modifying the templates.
Release An instance of a Helm chart installed in a Kubernetes cluster, created with specific values.
Repository Storage for Helm charts, which can be public or private and are typically hosted on various services.
Dependency Management Helm supports specifying and managing dependencies between charts, enabling complex application composition.
  • Here's the workflow for using Helm presented as a table:
Step Description
1. Create or Obtain a Chart You can either create your own Helm charts for your applications or obtain pre-made charts from public or private repositories. Many popular applications and services offer Helm charts.
2. Customize Values Customize the configuration of a Helm chart by providing custom values. These values override the defaults defined in the chart.
3. Install the Chart Use the Helm CLI to install the chart into your Kubernetes cluster. Specify the release name and values file (if needed). Helm will create the necessary Kubernetes resources based on the chart and values.
4. Upgrade and Rollback Helm provides tools to easily upgrade a release to a new version of the chart or roll back to a previous version if issues arise during deployment or updates.
5. Uninstall When you're finished with an application, use Helm to uninstall the release. Helm will remove all associated resources, ensuring a clean removal.

Why Helm?#

  • In the Minikube Sample Project, we already knew the way to deploy a simple Spring Boot application and MongoDB with Kubernetes. However, what will we do if we need to clone this application setup to multiple environment like DEV, TEST, STG, etc. So, we have to create multiple yaml files for every environment and we have to apply every file manually right?. It really take many efforts and time to operate multiple environments and it makes us also hard to control all environments. So Helm will be the solution for us.
  • Imagine that we will have some template files which define the structure for deploying an application on Kubernetes as we did in Minikube Sample Project. However, we can map values from value files into these template files using Helm. so it means with a template set we can use it to deploy multi environments because every environment we will map with a value file. Let's see the image below.

 #zoom

Install Helm#

Helm Example#

  • In this example we will base on the Minikube Sample Project to continue clone two environment DEV, and TEST by using helm.

Create Helm Project#

  • After install Helm, we can use the command below to create a Helm project.
1
helm create <Name>
1
helm create sample
  • Then we will have some generated folder and files as below.
duc@duc-MS-7E01:~/study/kubernetes/helm/sample$ ls
charts/  Chart.yaml  templates/ values.yaml
File/Folder Purpose Usage
charts/ Folder for managing subcharts. Used to include and manage subcharts, which are nested Helm charts that can be used within the parent chart to modularize and reuse components.
Chart.yaml Metadata file for the Helm chart. Contains metadata about the chart, including its name, version, description, and other details. This information is used for tracking, searching, and managing chart releases.
templates/ Folder for Kubernetes resource templates. Contains YAML templates for Kubernetes resource manifests. These templates often include placeholders for values that can be customized during chart installation. Helm uses these templates to generate actual manifests.
values.yaml File for default configuration values. Specifies default configuration values for the chart. Users can override these defaults by providing their own values.yaml file during chart installation. This allows for easy customization without altering the chart's templates.
  • In this example, we just focus on creating resource templates and configuration value files because we just to deploy a simple application on multiple environments.

Creating Templates#

 #zoom

Configure Templates#

  • Let's start with the mongo-config.yaml , normally without using helm we will have the mongo-config.yaml with the content as below.
mongo-config.yaml
1
2
3
4
5
6
7
apiVersion: v1
kind: ConfigMap
metadata:
  name: mongo-config
data:
  mongo-url: mongo-service
  mongo-port: "27017"
  • We can see that the values of name, mongo-url and mongo-port are hard-coded. So we can't use this file for multiple environments because we can't change the values.
  • Now, let's update the content of the mongo-config.yaml in the templates folder as below.
mongo-config.yaml
1
2
3
4
5
6
7
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.mongo.config.name }}
data:
  mongo-url: {{ .Values.mongo.app.name }}
  mongo-port: "{{ .Values.mongo.containers.port }}"
  • Now, the values of values of name, mongo-url and mongo-port can be mapped from a values file by using the template expression, so with multiple environments, we just need to define multiple values file.
  • The template expression can be explained as below. Ex: we have {{ .Values.mongo.config.name }}

    • {{ ... }}: Double curly braces denote the start and end of a template expression. Everything inside these braces is evaluated as a template.
    • .: The period . represents the current context within the template. In the context of a Helm chart, this often refers to the root context, which includes values, templates, and other chart-related data.
    • Values: In Helm charts, .Values is a special object that contains all the values defined in the values.yaml file or provided by the user during chart installation. It's a way to access and interpolate these values into templates.
    • mongo: This is a key within the .Values object. It indicates that you are accessing a value nested under the mongo key.
    • config: Similarly, config is another key nested within the mongo key.
    • name: Finally, name is the specific value being accessed under the config key.
  • Then in the values.yaml we will have the configuration for {{ .Values.mongo.config.name }} as below:

values.yaml
1
2
3
mongo:
  config:
    name: mongo-config-dev
  • With this approach, we can make any field in the template to be configurable and in the values.yaml file we can also structure the configuration as we expect.

  • So, we will apply this way for other resource template files. Let's update resource templates for MongoDB with the following yaml files as below.

mongo-config.yaml
1
2
3
4
5
6
7
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.mongo.config.name }}
data:
  mongo-url: {{ .Values.mongo.app.name }}
  mongo-port: "{{ .Values.mongo.containers.port }}"
mongo-pvc.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: {{ .Values.mongo.pvc.name }}
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: {{ .Values.mongo.pvc.storage }}
mongo-secret.yaml
1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Values.mongo.secret.name }}
type: Opaque
data:
  mongo-user: {{ .Values.mongo.secret.data.mongoUser }}
  mongo-password: {{ .Values.mongo.secret.data.mongoPassword }}
mongo-deployment.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.mongo.app.name }}
  labels:
    app: {{ .Values.mongo.app.name }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: {{ .Values.mongo.app.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.mongo.app.name }}
    spec:
      containers:
      - name: {{ .Values.mongo.containers.name }}
        image: {{ .Values.mongo.containers.image }}
        ports:
        - containerPort: {{ .Values.mongo.containers.port }}
        env:
        - name: MONGO_INITDB_ROOT_USERNAME
          valueFrom:
            secretKeyRef:
              name: {{ .Values.mongo.secret.name }}
              key: mongo-user
        - name: MONGO_INITDB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Values.mongo.secret.name }}
              key: mongo-password
        volumeMounts:
        - name: mongo-storage
          mountPath: /data/db
      volumes:
      - name: mongo-storage
        persistentVolumeClaim:    
          claimName: {{ .Values.mongo.pvc.name }}
mongo-service.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.mongo.app.name }}
spec:
  selector:
    app: {{ .Values.mongo.app.name }}
  ports:
    - protocol: TCP
      name: mongo-port
      port: {{ .Values.mongo.containers.port }}
      targetPort: {{ .Values.mongo.containers.port }}
  • With the MongoDB template files above, we will have the configurations in the values.yaml for DEV environment as below.
values.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
mongo:
  app:
    name: mongo-app-dev
  containers:
    name: mongo-dev
    image: mongo
    port: 27017
  pvc:
    name: mongo-pvc-dev
    storage: 512Mi
  config:
    name: mongo-config-dev
  secret:
    name: mongo-secret-dev
    data:
      mongoUser: cm9vdA==
      mongoPassword: ZXhhbXBsZQ==
  • Next, we will continue to map the content for the resource template files of the Spring Boot application as below.
springboot-config.yaml
1
2
3
4
5
6
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.springboot.config.name }}
data:
  env: {{ .Values.springboot.config.data.env }}
spring-boot-deployment.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Values.springboot.app.name }}
  labels:
    app: {{ .Values.springboot.app.name }}
spec:
  replicas: 1
  selector:
    matchLabels:
      app: {{ .Values.springboot.app.name }}
  template:
    metadata:
      labels:
        app: {{ .Values.springboot.app.name }}
    spec:
      containers:
      - name: {{ .Values.springboot.containers.name }}
        image: {{ .Values.springboot.containers.image }}
        imagePullPolicy: Never
        ports:
        - containerPort: {{ .Values.springboot.containers.port }}
        env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: {{ .Values.mongo.secret.name }}
              key: mongo-user
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Values.mongo.secret.name }}
              key: mongo-password
        - name: DB_URL
          valueFrom:
            configMapKeyRef:
              name: {{ .Values.mongo.config.name }}
              key: mongo-url
        - name: PORT
          valueFrom:
            configMapKeyRef:
              name: {{ .Values.mongo.config.name }}
              key: mongo-port
        - name: ENV
          valueFrom:
            configMapKeyRef:
              name: {{ .Values.springboot.config.name }}
              key: env
spring-boot-service.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
  name: {{ .Values.springboot.app.name }}
spec:
  type: NodePort
  selector:
    app: {{ .Values.springboot.app.name }}
  ports:
    - protocol: TCP
      name: spring-boot-port
      port: {{ .Values.springboot.containers.port }}
      targetPort: {{ .Values.springboot.containers.port }}
      nodePort: {{ .Values.springboot.app.nodePort }}
  • So with these Spring Boot application template files. We will update the values.yaml for deploying Spring Boot application as below.
values.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
mongo:
  app:
    name: mongo-app-dev
  containers:
    name: mongo-dev
    image: mongo
    port: 27017
  pvc:
    name: mongo-pvc-dev
    storage: 512Mi
  config:
    name: mongo-config-dev
  secret:
    name: mongo-secret-dev
    data:
      mongoUser: cm9vdA==
      mongoPassword: ZXhhbXBsZQ==

springboot:
  app:
    name: spring-boot-app-dev
    nodePort: 31000
  containers:
    name: spring-boot-app-dev
    image: json-schema-validator:0.0.1-SNAPSHOT
    port: 8080
  config:
    name: spring-boot-config-dev
    data:
      env: dev
  • Now, we have just finished creating deployment templates and repair configurations for DEV deployment in the values.yaml file. So, to repair deployment for TEST environment, we just need to create another values file, let's call it as values-test.yaml with the configuration as below.
values-test.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
mongo:
  app:
    name: mongo-app-test
  containers:
    name: mongo-test
    image: mongo
    port: 27017
  pvc:
    name: mongo-pvc-test
    storage: 512Mi
  config:
    name: mongo-config-test
  secret:
    name: mongo-secret-test
    data:
      mongoUser: cm9vdA==
      mongoPassword: cGFzc3dvcmQ=

springboot:
  app:
    name: spring-boot-app-test
    nodePort: 32000
  containers:
    name: spring-boot-app-test
    image: json-schema-validator:0.0.1-SNAPSHOT
    port: 8080
  config:
    name: spring-boot-config-test
    data:
      env: test

Deployment Rollout#

  • Now, to apply helm for deploying DEV and TEST environments, we will run commands below.
1
helm install -f <path to values file> <name of helm chart release> <path to helm chart>
1
helm install -f helm/sample/values.yaml my-sample-dev helm/sample/
Command Explanation
helm install Installs a Helm chart in a Kubernetes cluster.
-f helm/sample/values.yaml Specifies a values file to customize the chart's configuration.
my-sample-dev Names the release created by the installation.
helm/sample/ Indicates the path to the Helm chart to be installed.
  • After executing the command above for deploying DEV environment, we can see the results below.

 #zoom

 #zoom

  • As you can see, in the values.yaml which is used for DEV deployment, we configured exporting node port 31000, so we can check the DEV application through some api calls with postman.
  • The ip address in the api is the ip address of minikube instance, we can get it by running the command.
1
minikube ip
  • Now, to deploy TEST environment, we also will run the command as we did for DEV with different values file and helm chart release name.
1
helm install -f helm/sample/values-test.yaml my-sample-test helm/sample/
  • Then we can see the result as below.

 #zoom

 #zoom

  • As you can see, in the values-test.yaml which is used for TEST deployment, we configured exporting node port 32000, so we can check the TEST application through some api calls with postman.

  • So we have finished deployment for 2 environments DEV and TEST by using Helm. We can see that Helm helps us saving time a lots and maybe in future if we need to create new environment, we just need to create new values file and update the configuration values.

  • Last but not least, if we have changed some values in the values.yaml or values-test.yaml. We can use the command below to update the helm chart.

1
helm upgrade -f <path to values file> <name of helm chart release> <path to helm chart>
1
helm upgrade -f helm/sample/values.yaml my-sample-dev helm/sample/
Command Explanation
helm upgrade Updates an existing Helm release with new configurations or a new version of the chart.
-f helm/sample/values.yaml Specifies a values file to customize the updated chart's configuration.
my-sample-dev Names the release to be upgraded.
helm/sample/ Indicates the path to the updated Helm chart. Helm will look in this directory for the new chart version.
  • Then in the case, we want to remove a environment deployment, we can run command below.
1
helm uninstall my-sample-dev
  • Then the DEV environment will be removed which included all deployment, secret, configMap, pvc of mongo and spring boot services also.

See Also#

References#