Introduction to Helm

Helm is a powerful package manager for Kubernetes, analogous to apt for Debian-based systems or yum for Red Hat-based systems. It streamlines the deployment and management of applications on Kubernetes by packaging Kubernetes resources into reusable, configurable units called charts. Helm simplifies complex Kubernetes operations, enhances productivity, and fosters best practices in deploying applications.

Key Concepts in Helm

  1. Helm Chart: A Helm chart is a collection of files that describe a related set of Kubernetes resources. Charts contain all the necessary configuration to deploy an application, tool, or service inside a Kubernetes cluster.
  2. Chart Repository: A chart repository is a place where charts can be collected and shared. Helm uses repositories to distribute charts to users.
  3. Release: A release is a running instance of a chart, combined with configuration values. Each installation of a chart results in a unique release name.
  4. Values: Helm allows customization of charts through values. Values are parameters set by users to modify the behavior and configuration of the chart during deployment.
  5. Templates: Charts use Go templating to enable dynamic configuration of Kubernetes manifests based on the provided values.
  6. Helm CLI: The command-line interface used to interact with Helm, manage charts, repositories, and releases.

Helm Architecture

Helm consists of two main components:

  • Helm Client: The CLI tool used by developers to create, manage, and deploy charts.
  • Helm Repository: A storage for charts, often hosted on HTTP servers, cloud storage, or other accessible platforms.

In Helm 3, the server-side component called Tiller (present in Helm 2) was removed, simplifying security and architecture by having Helm interact directly with the Kubernetes API.

Installing and Setting Up Helm

Prerequisites

  • A Kubernetes cluster (local like Minikube, or cloud-based like GKE, EKS, AKS)
  • kubectl configured to communicate with your cluster
  • Helm installed on your local machine

Installation Steps

Install Helm CLI:
# For macOS using Homebrew

brew install helm

# For Windows using Chocolatey

choco install kubernetes-helm

# For Linux

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

Initialize Helm:
Helm 3 does not require initialization steps like Helm 2 did (no Tiller setup).

Add a Chart Repository:
By default, Helm adds the official stable repository.
helm repo add stable https://charts.helm.sh/stable

helm repo update

Helm Charts in Detail

Anatomy of a Helm Chart

A typical Helm chart has the following directory structure:

mychart/

  Chart.yaml          # Metadata about the chart

  values.yaml         # Default configuration values

  charts/             # Dependencies

  templates/          # Kubernetes resource templates

  README.md           # Documentation

  LICENSE             # License information

Chart.yaml: Contains information such as the chart name, version, description, and dependencies.
apiVersion: v2

name: mychart

description: A Helm chart for Kubernetes

version: 0.1.0

appVersion: "1.16.0"

values.yaml: Defines default values for the chart's templates, allowing users to override them during deployment.
replicaCount: 3

image:

  repository: nginx

  tag: stable

service:

  type: ClusterIP

  port: 80

templates/: Contains Kubernetes manifest templates with placeholders for dynamic values.
Example deployment.yaml template:
apiVersion: apps/v1

kind: Deployment

metadata:

  name: {{ include "mychart.fullname" . }}

  labels:

    app: {{ include "mychart.name" . }}

spec:

  replicas: {{ .Values.replicaCount }}

  selector:

    matchLabels:

      app: {{ include "mychart.name" . }}

  template:

    metadata:

      labels:

        app: {{ include "mychart.name" . }}

    spec:

      containers:

        – name: {{ .Chart.Name }}

          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

          ports:

            – containerPort: {{ .Values.service.port }}

  • charts/: Optional directory for chart dependencies. Helm can manage dependencies using requirements.yaml or Chart.yaml in Helm 3.

Creating a Helm Chart

Create a New Chart:
helm create mychart

This command scaffolds a new chart with the standard directory structure and example templates.

Customize Templates and Values:
Modify values.yaml and templates in the templates/ directory to fit your application's requirements.

Package the Chart:
helm package mychart

This command creates a .tgz package that can be shared or stored in a repository.

Publish the Chart:
Upload the packaged chart to a chart repository or a storage service accessible to your deployment environment.

Using Helm: Common Commands and Workflows

Installing a Chart

To install a chart from a repository:

helm install my-release stable/nginx

  • my-release is the name of the release.
  • stable/nginx specifies the chart from the stable repository.

Customizing Installation with Values

Override default values using the –values (-f) flag or –set flag:

# Using a custom values file

helm install my-release stable/nginx -f custom-values.yaml

# Using the –set flag for individual values

helm install my-release stable/nginx –set replicaCount=5

Listing Releases

helm list

Upgrading a Release

To upgrade a release with new chart version or updated values:

helm upgrade my-release stable/nginx –set image.tag=1.17.0

Rolling Back a Release

If an upgrade causes issues, roll back to the previous release:

helm rollback my-release 1

Here, 1 is the revision number to roll back to.

Uninstalling a Release

helm uninstall my-release

Searching for Charts

helm search repo nginx

Adding and Removing Repositories

# Add a repository

helm repo add bitnami https://charts.bitnami.com/bitnami

# Remove a repository

helm repo remove bitnami

Advanced Helm Features

Dependencies Management

Helm charts can declare dependencies on other charts, allowing modular and reusable configurations.

Defining Dependencies: In Chart.yaml or requirements.yaml (Helm 3 uses Chart.yaml).
dependencies:

  – name: redis

    version: "14.8.8"

    repository: "https://charts.bitnami.com/bitnami"

Updating Dependencies:
helm dependency update mychart

Chart Hooks

Hooks allow charts to perform actions at certain points in the release lifecycle, such as pre-install, post-install, pre-upgrade, etc.

Example of a hook in a template:

apiVersion: batch/v1

kind: Job

metadata:

  name: "{{ .Release.Name }}-pre-install"

  annotations:

    "helm.sh/hook": pre-install

spec:

  template:

    spec:

      containers:

        – name: pre-install

          image: busybox

          command: ['sh', '-c', 'echo Pre-install hook']

      restartPolicy: Never

Helm Tests

Helm allows defining tests for your releases to validate deployments.

Defining a Test:
Create a test pod with the annotation helm.sh/hook: test.
apiVersion: v1

kind: Pod

metadata:

  name: "{{ .Release.Name }}-test"

  annotations:

    "helm.sh/hook": test

spec:

  containers:

    – name: test

      image: busybox

      command: ['sh', '-c', 'echo Test successful']

  restartPolicy: Never

Running Tests:
helm test my-release

Helm Plugins

Helm supports plugins to extend its functionality. Examples include:

  • Helm Diff: Shows a diff of what changes an upgrade would make.
  • Helm Secrets: Manages secrets within Helm charts.
  • Helm S3: Uses Amazon S3 as a chart repository.

Examples and Scenarios

Example 1: Deploying NGINX Using Helm

Scenario: Quickly deploy a web server for testing purposes.

Steps:

Add the Official Helm Repository:
helm repo add stable https://charts.helm.sh/stable

helm repo update

Install the NGINX Chart:
helm install my-nginx stable/nginx-ingress

Verify Installation:
kubectl get pods -l app.kubernetes.io/name=nginx-ingress

Accessing the NGINX Service:
Depending on the Kubernetes environment, access via LoadBalancer IP or NodePort.

Customizing Configuration:
helm upgrade my-nginx stable/nginx-ingress –set controller.replicaCount=2

Outcome: A scalable NGINX Ingress controller is deployed with two replicas, ensuring high availability.

Example 2: Creating a Custom Helm Chart for a Microservice

Scenario: Deploy a custom microservice with specific configurations.

Steps:

Create a New Chart:
helm create my-microservice

Customize values.yaml:
replicaCount: 2

image:

  repository: myregistry/my-microservice

  tag: "v1.0.0"

service:

  type: ClusterIP

  port: 8080

env:

  – name: ENVIRONMENT

    value: production

Modify Templates:
Update deployment.yaml to include environment variables:
env:

  {{- range .Values.env }}

  – name: {{ .name }}

    value: {{ .value | quote }}

  {{- end }}

Package and Deploy:
helm package my-microservice

helm install my-microservice-release ./my-microservice-0.1.0.tgz

Managing Upgrades:
Update the image tag and upgrade:
helm upgrade my-microservice-release ./my-microservice-0.1.1.tgz –set image.tag="v1.0.1"

Outcome: A custom microservice is deployed with versioned releases, environment-specific configurations, and easy upgrade paths.

Example 3: Managing Complex Applications with Dependencies

Scenario: Deploy a WordPress site with a MySQL database, leveraging Helm dependencies.

Steps:

Create a Parent Chart:
helm create wordpress

Define Dependencies in Chart.yaml:
dependencies:

  – name: mysql

    version: "8.5.1"

    repository: "https://charts.bitnami.com/bitnami"

  – name: wordpress

    version: "10.1.0"

    repository: "https://charts.bitnami.com/bitnami"

Update Dependencies:
helm dependency update wordpress

Customize Values:
In values.yaml, configure MySQL and WordPress settings.
mysql:

  auth:

    rootPassword: "rootpassword"

    database: "wordpressdb"

    username: "wpuser"

    password: "wppassword"

wordpress:

  wordpressUsername: "admin"

  wordpressPassword: "adminpassword"

  wordpressEmail: "admin@example.com"

  wordpressBlogName: "My Blog"

Install the Parent Chart:
helm install my-wordpress ./wordpress

Verify Deployment:
kubectl get pods -l app.kubernetes.io/instance=my-wordpress

Outcome: A WordPress site is deployed with an embedded MySQL database, managed as a single Helm release with dependencies handled automatically.

Example 4: Integrating Helm with CI/CD Pipelines

Scenario: Automate Helm chart deployments using a CI/CD tool like Jenkins, GitLab CI, or GitHub Actions.

Steps:

Store Helm Charts in Version Control:
Keep chart definitions and values.yaml files in a Git repository.

Define CI/CD Pipeline:
Example using GitHub Actions:
name: Helm Deploy

on:

  push:

    branches:

      – main

jobs:

  deploy:

    runs-on: ubuntu-latest

    steps:

      – name: Checkout Code

        uses: actions/checkout@v2

      – name: Set up Helm

        uses: azure/setup-helm@v1

        with:

          version: '3.8.0'

      – name: Helm Lint

        run: helm lint ./mychart

      – name: Helm Upgrade

        env:

          KUBECONFIG: ${{ secrets.KUBECONFIG }}

        run: helm upgrade –install my-release ./mychart –values ./mychart/values.yaml

  1. Secure Kubernetes Credentials:
    Store KUBECONFIG or necessary credentials securely in the CI/CD tool's secrets management.
  2. Trigger Deployment on Code Changes:
    When changes are pushed to the main branch, the pipeline lints the chart and performs an upgrade or install.

Outcome: Continuous deployment of Helm charts ensures that application updates are automatically deployed to Kubernetes upon code changes, maintaining consistency and reducing manual intervention.

Best Practices for Using Helm

  1. Version Control Charts: Keep Helm charts in version control systems (e.g., Git) to track changes and facilitate collaboration.
  2. Semantic Versioning: Use semantic versioning for chart versions to manage dependencies and upgrades effectively.
  3. Parameterize Configurations: Leverage values.yaml and templates to make charts flexible and reusable across different environments.
  4. Secure Sensitive Data: Avoid storing sensitive information in values.yaml. Use tools like Helm Secrets or integrate with Kubernetes secrets management solutions.
  5. Modularize with Dependencies: Break down complex applications into smaller, manageable charts with dependencies, enhancing maintainability.
  6. Lint and Test Charts: Use helm lint and Helm tests to validate charts before deployment, ensuring reliability.
  7. Document Charts: Provide comprehensive README.md files and inline documentation to help users understand chart usage and configurations.
  8. Use Chart Repositories Wisely: Host internal chart repositories for proprietary applications while leveraging public repositories for common services.

Advanced Scenarios

Scenario 1: Blue-Green Deployments with Helm

Objective: Minimize downtime and mitigate risks during deployments by using blue-green strategies.

Approach:

Create Separate Releases:
Deploy two identical environments (blue and green) using separate Helm releases.

helm install myapp-blue ./myapp-chart

helm install myapp-green ./myapp-chart

Switch Traffic:
Use a load balancer or Ingress controller to route traffic to the active release.

# Example Ingress switching between blue and green services

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

  name: myapp-ingress

spec:

  rules:

    – host: myapp.example.com

      http:

        paths:

          – path: /

            pathType: Prefix

            backend:

              service:

                name: myapp-green

                port:

                  number: 80

Deploy Updates to Inactive Release:
Update the non-active release (e.g., green) with the new version.
helm upgrade myapp-green ./myapp-chart –set image.tag=new-version

Switch Traffic to Updated Release:
Update the Ingress to point to myapp-green.

Monitor and Rollback if Necessary:
Ensure the new release is functioning correctly. If issues arise, revert traffic to myapp-blue.

Outcome: Seamless transitions between application versions with minimal downtime and easy rollback capabilities.

Scenario 2: Multi-Tenant Deployments with Helm

Objective: Deploy applications for multiple tenants with isolated configurations using Helm.

Approach:

Use Values Files for Each Tenant:
Create separate values-tenant1.yaml, values-tenant2.yaml, etc., containing tenant-specific configurations.

Deploy Separate Releases:
Install the chart multiple times with different release names and values.
helm install tenant1-release ./myapp-chart -f values-tenant1.yaml

helm install tenant2-release ./myapp-chart -f values-tenant2.yaml

Isolate Resources:
Utilize Kubernetes namespaces to isolate tenant resources.

kubectl create namespace tenant1

kubectl create namespace tenant2

helm install tenant1-release ./myapp-chart -f values-tenant1.yaml –namespace tenant1

helm install tenant2-release ./myapp-chart -f values-tenant2.yaml –namespace tenant2

Manage Tenant Upgrades Independently:
Each release can be upgraded, rolled back, or configured separately without affecting others.

Outcome: Efficiently manage multi-tenant applications with isolated environments, ensuring security and customization per tenant.

Scenario 3: Hybrid Deployments with Helm

Objective: Manage deployments across multiple Kubernetes clusters using Helm.

Approach:

Configure Helm for Multiple Clusters:
Set up kubectl contexts for each cluster.
kubectl config get-contexts

kubectl config use-context cluster1

Deploy to Each Cluster:
Use Helm to install or upgrade releases in different contexts.
# Deploy to cluster1

kubectl config use-context cluster1

helm install release-cluster1 ./mychart -f values-cluster1.yaml

# Deploy to cluster2

kubectl config use-context cluster2

helm install release-cluster2 ./mychart -f values-cluster2.yaml

Automate with Scripts or CI/CD:
Create scripts or pipeline steps that switch contexts and perform Helm operations for each cluster.

Outcome: Streamlined management of applications across multiple Kubernetes environments, supporting hybrid cloud or multi-cloud strategies.

Scenario 4: Helm in GitOps Workflows

Objective: Implement GitOps principles by managing Helm releases through Git repositories.

Approach:

Store Helm Charts and Configurations in Git:
Maintain Helm charts and their values.yaml files in a Git repository.

Use GitOps Tools:
Integrate with tools like Argo CD or Flux that monitor Git repositories and reconcile Kubernetes clusters accordingly.

Automate Deployments:
When changes are pushed to the Git repository, the GitOps tool automatically applies Helm releases to the cluster.


Example with Argo CD:

apiVersion: argoproj.io/v1alpha1

kind: Application

metadata:

  name: myapp

spec:

  project: default

  source:

    repoURL: https://github.com/myorg/myapp-helm-charts

    targetRevision: main

    path: mychart

  destination:

    server: https://kubernetes.default.svc

    namespace: default

  syncPolicy:

    automated:

      prune: true

      selfHeal: true

Track Changes and Rollbacks:
Use Git history to track changes and enable rollbacks by reverting commits.

Outcome: Enhanced visibility, auditability, and reliability in deployments through Git-centric management of Helm releases.

Helm Best Practices and Tips

  1. Keep Charts DRY (Don't Repeat Yourself):
    Use templates and helper functions to minimize repetition within your charts.
  2. Use Semantic Versioning:
    Align chart versions with semantic versioning to manage compatibility and dependencies effectively.
  3. Leverage Helm Hooks Judiciously:
    Utilize hooks for necessary lifecycle events but avoid overusing them to prevent complexity.
  4. Secure Sensitive Data:
    Integrate with Kubernetes Secrets or external secret management systems instead of embedding sensitive data in charts.
  5. Test Charts Thoroughly:
    Use Helm's built-in testing framework and CI pipelines to ensure charts behave as expected before deployment.
  6. Modularize Large Applications:
    Break down monolithic charts into smaller, manageable sub-charts with clear dependencies.
  7. Document Your Charts:
    Provide comprehensive documentation within the chart repository to assist users in deployment and customization.
  8. Use Values Files for Environment Configurations:
    Maintain separate values files for different environments (e.g., development, staging, production) to manage configurations efficiently.
  9. Validate Charts:
    Regularly use helm lint and other validation tools to catch errors early in the development process.
  10. Monitor Helm Releases:
    Implement monitoring and alerting for Helm releases to detect and respond to deployment issues promptly.

Conclusion

Helm significantly enhances the Kubernetes ecosystem by providing a standardized, efficient, and scalable way to manage application deployments. Its chart-based architecture simplifies complex configurations, promotes reuse, and integrates seamlessly with CI/CD pipelines and GitOps workflows. By leveraging Helm's capabilities and adhering to best practices, organizations can achieve consistent, reliable, and maintainable deployments across diverse Kubernetes environments.

Whether deploying simple services or managing intricate, multi-component applications, Helm serves as an indispensable tool for Kubernetes operators and developers alike, fostering agility and operational excellence in cloud-native deployments.

Leave a Reply