Helm is a package manager for Kubernetes, simplifying the deployment and management of applications on Kubernetes clusters. It allows users to define, install, and upgrade even the most complex Kubernetes applications using customizable packages called charts.
Helm charts include all the necessary Kubernetes resources, making it easier to share and reproduce applications across different environments. Helm helps streamline the Kubernetes deployment process and enhances the scalability and maintainability of containerized applications.
Pre-requisites
Kubernetes Cluster:
- Have a functional Kubernetes cluster for deploying applications.
Helm Installation:
- Install Helm on your local workstation to manage Kubernetes applications effectively.
Kubernetes Knowledge:
- Understand basic Kubernetes concepts for effective chart customization.
YAML Proficiency:
- Be familiar with YAML syntax, crucial for defining Kubernetes resources and Helm charts.
n the context of deploying a basic website frontend using Nginx on Kubernetes, consider the following scenario:
Project Environments:
- Dev, QA, Staging, and Prod represent distinct environments within the project.
Environment-Specific Parameters:
Each environment requires different parameters for Nginx deployment:
Dev and QA need only one replica.
Staging and Prod involve more replicas with pod autoscaling.
Ingress routing rules vary for each environment.
Configurations and secrets differ across environments.
Deployment File Management:
Managing different Nginx deployment files for each environment can become cumbersome.
Writing custom scripts to replace values in a single deployment file based on the environment is not a scalable approach.
Introduction of Helm Chart:
Helm charts provide a solution by offering a templated and parameterized structure.
With Helm, a single chart can be customized for different environments, reducing the need for separate deployment files.
Parameters in Helm charts allow dynamic configuration based on environment, enhancing scalability and maintainability.
Helm charts are packaged combinations of Kubernetes YAML manifest templates and Helm-specific files, simplifying application deployment on Kubernetes clusters. The templating functionality, powered by the Go templating engine, enables dynamic and reusable charts. Rather than maintaining separate charts for each environment, a single Helm chart can be customized using a values file, reducing redundancy and simplifying deployment parameter adjustments. This approach significantly streamlines the deployment process, enhancing efficiency and manageability across different Kubernetes environments. Practical examples in subsequent sections will provide hands-on experience with Helm Charts.
Helm Chart Structure
1. Purpose:
- Helm charts streamline Kubernetes deployments. For Nginx deployment, traditional YAML files are organized into a structured Helm chart.
nginx-deployment:
nginx-deployment
├── configmap.yaml
├── deployment.yaml
├── ingress.yaml
└── service.yaml
Helm Structure would look like:
nginx-chart/
|-- Chart.yaml
|-- charts
|-- templates
| |-- NOTES.txt
| |-- _helpers.tpl
| |-- deployment.yaml
| |-- configmap.yaml
| |-- ingress.yaml
| |-- service.yaml
| `-- tests
| `-- test-connection.yaml
`-- values.yaml
2. Directory Structure:
nginx-deployment:
- Contains separate YAML files for Nginx deployment.
nginx-chart:
- Helm chart directory structure containing essential files and folders.
3. Files and Directories:
.helmignore:
- Lists files excluded from the Helm chart, functioning like .gitignore.
Chart.yaml:
- Holds chart metadata such as version and description.
values.yaml:
- Defines values for YAML templates, facilitating customization for different environments.
charts:
- Directory for potential dependencies, typically left empty in this example.
templates:
Contains Kubernetes manifest files templated to access values from values.yaml.
NOTES.txt:
- A plaintext file printed post-deployment, offering additional information.
_helpers.tpl:
- Contains methods and sub-templates available for use in other chart templates.
tests/:
- Allows defining tests to validate chart functionality during installation.
4. Customization:
Values.yaml changes for environment-specific configurations.
Override values dynamically or during installation using --values or --set commands.
Helm Chart Tutorial GitHub Repo
- The Helm Chart Tutorial provides an example Helm chart and manifests.
git clone https://github.com/Gatete-Bruno/helm-101.git
Helm Chart From Scratch
- To create a Helm chart from scratch for Nginx deployment, use the following command
helm create nginx-chart
Output:
nginx-chart
│ ├── Chart.yaml
│ ├── charts
│ ├── templates
│ │ ├── NOTES.txt
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ ├── hpa.yaml
│ │ ├── ingress.yaml
│ │ ├── service.yaml
│ │ ├── serviceaccount.yaml
│ │ └── tests
│ │ └── test-connection.yaml
│ └── values.yaml
I have customized the directory to look like:
kato@master1:~/helm-101/nginx-chart$ tree
.
├── Chart.yaml
├── templates
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── helpers.tpl
│ └── service.yaml
└── values.yaml
1 directory, 6 files
Let us breakdown what we have:
- Chart.yaml
apiVersion: v2
name: nginx-chart
description: A Helm chart for deploying Nginx on Kubernetes
type: application
version: 0.1.0
appVersion: "1.0"
This YAML snippet represents the metadata configuration for a Helm chart.
apiVersion: v2:
- Specifies the Helm chart API version in use (version 2).
name: nginx-chart:
- Defines the name of the Helm chart as "nginx-chart."
description: A Helm chart for deploying Nginx on Kubernetes:
- Provides a brief description of the purpose of the Helm chart.
type: application:
- Specifies the type of the Helm chart, indicating that it's designed for deploying applications.
version: 0.1.0:
- Assigns a version number (0.1.0) to the Helm chart.
appVersion: "1.0":
- Specifies the application version (1.0) associated with the Helm chart.
Now let us look at what we have in the templates dir
├── templates
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── helpers.tpl
│ └── service.yaml
└── values.yaml
for the configmap.yaml file
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "nginx-chart.fullname" . }}-configmap
namespace: {{ .Release.Namespace }}
data:
index.html: |
<html>
<h1>Welcome</h1>
</br>
<h1>Hi! I got deployed in dev Environment using Helm Chart </h1>
</html>
apiVersion: v1:
- Specifies the Kubernetes API version for the ConfigMap.
kind: ConfigMap:
- Declares the type of Kubernetes resource as a ConfigMap.
metadata:
Contains metadata details for the ConfigMap, such as its name and namespace.
name: {{ include "nginx-chart.fullname" . }}-configmap:
- Dynamically generates the ConfigMap name using the "nginx-chart.fullname" template function.
namespace: {{ .Release.Namespace }}:
- Retrieves the namespace from the Helm release configuration.
data:
Defines key-value pairs for the ConfigMap data.
index.html: | ... :
- Provides HTML content to be stored in the ConfigMap, representing a simple web page.
for deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-nginx
labels:
app: nginx
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
apiVersion: apps/v1:
- Specifies the Kubernetes API version for the Deployment.
kind: Deployment:
- Declares the type of Kubernetes resource as a Deployment.
metadata:
Contains metadata details for the Deployment, including its name and labels.
name: {{ .Release.Name }}-nginx:
- Dynamically generates the Deployment name based on the Helm release.
labels: app: nginx:
- Assigns a label to the Deployment for better identification.
spec:
Describes the desired state for the Deployment, including the number of replicas.
replicas: {{ .Values.replicaCount }}:
- Retrieves the replica count from the Helm chart values.
selector:
- Specifies the labels used to select which pods are controlled by the Deployment.
template:
Defines the pod template for the Deployment.
metadata: labels: app: nginx:
- Assigns labels to the pod template for proper identification.
spec: containers: ...:
- Specifies the containers running in the pod, including details like image, ports, and pull policy.
for service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "nginx-chart.fullname" . }}-service
spec:
selector:
app.kubernetes.io/instance: {{ .Release.Name }}
type: ClusterIP
ports:
- protocol: TCP
port: 80
targetPort: 80
apiVersion: v1:
- Specifies the Kubernetes API version for the Service.
kind: Service:
- Declares the type of Kubernetes resource as a Service.
metadata:
Contains metadata details for the Service, including its name.
name: {{ include "nginx-chart.fullname" . }}-service:
- Dynamically generates the Service name using the "nginx-chart.fullname" template function.
spec:
Describes the desired state for the Service.
selector: app.kubernetes.io/instance: {{ .Release.Name }}:
- Selects pods with a matching label, associating them with the Service.
type: ClusterIP:
- Specifies that the Service is of type ClusterIP, allowing internal cluster communication.
ports:
Configures port mappings for the Service.
protocol: TCP:
- Defines the protocol used for the port.
port: 80:
- Specifies the port on which the Service is accessible.
targetPort: 80:
- Directs incoming traffic on the specified port to the target port on the associated pods.
For our values.yaml file
replicaCount: 2
image:
repository: nginx
tag: "1.16.0"
pullPolicy: IfNotPresent
service:
name: nginx-service
type: ClusterIP
port: 80
targetPort: 9000
env:
name: dev
replicaCount: 2:
- Specifies the desired number of replicas for a Kubernetes Deployment. In this case, it's set to 2, indicating two replica pods.
image:
Describes the container image configuration.
repository: nginx:
- Specifies the Docker image repository as "nginx."
tag: "1.16.0":
- Specifies the Docker image tag as version "1.16.0."
pullPolicy: IfNotPresent:
- Defines the policy for pulling the Docker image. In this case, it pulls the image only if it's not present locally.
service:
Configures the Kubernetes Service associated with the application.
name: nginx-service:
- Specifies the name of the Service as "nginx-service."
type: ClusterIP:
- Sets the Service type to ClusterIP, allowing internal cluster communication.
port: 80:
- Defines the port on which the Service is accessible.
targetPort: 9000:
- Specifies the target port on the associated pods, directing incoming traffic.
env:
Configures an environment variable.
name: dev:
- Sets an environment variable named "name" with the value "dev."
This is our final output
kato@master1:~/helm-101/nginx-chart$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
kato@master1:~/helm-101/nginx-chart$
kato@master1:~/helm-101/nginx-chart$
The command helm lint .
is used to check the validity of a Helm chart and ensure that all indentations and configurations are correct. It performs a series of checks and provides feedback on potential issues.
The helm install --dry-run
command is a useful way to simulate the installation of a Helm chart without actually deploying it to the cluster. It helps in validating the chart's correctness and identifying potential issues before a real deployment.
helm install --dry-run my-release nginx-chart:
The helm install
command is used to deploy a Helm chart to a Kubernetes cluster. In your case:
helm install my-nginx nginx-chart-0.1.0.tgz
kato@master1:~/helm-101/nginx-chart$ helm install my-nginx nginx-chart-0.1.0.tgz
NAME: my-nginx
LAST DEPLOYED: Sun Mar 10 11:21:34 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
kato@master1:~/helm-101/nginx-chart$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
my-nginx default 1 2024-03-10 11:21:34.733862264 +0000 UTC deployed nginx-chart-0.1.0 1.0
to check for everything deployed on your cluster
kato@master1:~/helm-101/nginx-chart$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
my-nginx-nginx 0/2 2 0 25s
kato@master1:~/helm-101/nginx-chart$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.233.0.1 <none> 443/TCP 15h
my-nginx-nginx-chart-service ClusterIP 10.233.9.190 <none> 80/TCP 25s
kato@master1:~/helm-101/nginx-chart$ kubectl get configmap
NAME DATA AGE
kube-root-ca.crt 1 15h
my-nginx-nginx-chart-configmap 1 25s
Now with Helm we can deploy kubernetes objects and reduce complexity . check out my github for the source code
https://github.com/Gatete-Bruno/helm-101
Cheers 🍻