Upgrade & Secure Your Future with DevOps, SRE, DevSecOps, MLOps!
We spend hours scrolling social media and waste money on things we forget, but won’t spend 30 minutes a day earning certifications that can change our lives.
Master in DevOps, SRE, DevSecOps & MLOps by DevOps School!
Learn from Guru Rajesh Kumar and double your salary in just one year.
Introduction to Helmfile
Helmfile is a declarative tool for deploying and managing multiple Helm charts (Kubernetes applications) as code. It allows you to:
- Define all releases, configurations, and environments in a single YAML file (
helmfile.yaml
) - Version-control your infrastructure and apply CI/CD best practices
- Manage complex, multi-environment, and multi-release deployments with ease
Real-world use cases:
- Coordinating deployment of microservices across dev, staging, and prod
- Keeping environment-specific configurations DRY and manageable
- Automating upgrades, rollbacks, and dependency management for multiple charts
Installation and Setup
Prerequisites
- Kubernetes cluster (local or cloud)
- kubectl installed and configured
- Helm (v3+) installed (
helm version
) - Helmfile installed
Installing Helmfile
macOS:
textbrew install helmfile
Linux:
textwget https://github.com/helmfile/helmfile/releases/download/v<version>/helmfile_linux_amd64
chmod +x helmfile_linux_amd64
mv helmfile_linux_amd64 /usr/local/bin/helmfile
Windows (Scoop):
textscoop install helmfile
Docker:
textdocker run --rm -it -v $PWD:/wd -w /wd ghcr.io/helmfile/helmfile:v0.156.0 helmfile sync
Helm must be installed and available in your PATH, as Helmfile delegates to Helm for actual deployments.
helmfile.yaml Structure and Syntax
A typical helmfile.yaml
consists of:
- repositories: List of Helm chart repositories
- environments: Environment-specific settings and values
- releases: List of Helm releases, each with chart, version, namespace, and values
Example:
textrepositories:
- name: bitnami
url: https://charts.bitnami.com/bitnami
environments:
dev:
values:
- values-dev.yaml
prod:
values:
- values-prod.yaml
releases:
- name: my-app
chart: bitnami/nginx
namespace: web
version: 13.2.18
values:
- common-values.yaml
- "values-{{ .Environment.Name }}.yaml"
- Templating: Use
{{ .Environment.Name }}
to inject environment names dynamically.
Managing Single and Multiple Helm Releases
Single release:
textreleases:
- name: redis
chart: bitnami/redis
namespace: cache
values:
- redis-values.yaml
Multiple releases:
textreleases:
- name: frontend
chart: bitnami/nginx
namespace: web
values: [frontend-values.yaml]
- name: backend
chart: bitnami/postgresql
namespace: db
values: [backend-values.yaml]
Each release can have its own chart, version, namespace, and values.
Organizing and Templating Values Files
- Common values: Place shared config in
common-values.yaml
- Environment-specific values: Use
values-dev.yaml
,values-prod.yaml
, etc.
Best practice: List files in order of precedence (last overrides previous):
textvalues:
- common-values.yaml
- "values-{{ .Environment.Name }}.yaml"
This allows you to override only what’s necessary for each environment.
Using Environment Variables and Secret Management
- Environment variables: Use Go templating in values files: text
image: tag: {{ requiredEnv "IMAGE_TAG" }}
Run with: textIMAGE_TAG=1.2.3 helmfile apply
- Secrets: Use the plugin for encrypted secrets, or fetch secrets from remote stores (Vault, AWS SSM) using
fetchSecretValue
: textvalues: - secrets.yaml # secrets.yaml db_password: ref+vault://db/#password
In your release: textvalues: - db_password: {{ .Values.db_password | fetchSecretValue | quote }}
This will fetch and inject the secret at runtime.
Handling Dependencies and Release Ordering
- Use the
needs
field to specify dependencies between releases: textreleases: - name: db chart: bitnami/postgresql namespace: db - name: app chart: mycompany/app namespace: web needs: - db
- Helmfile builds a DAG (Directed Acyclic Graph) and deploys releases in the correct order, executing releases in each group in parallel.
Grouping Releases and Using Selectors
- Labels: Add labels to releases for grouping and filtering: text
releases: - name: app labels: tier: frontend - name: db labels: tier: backend
- Selectors: Deploy only specific groups: text
helmfile -l tier=frontend apply
This applies only releases with thetier=frontend
label.
Advanced Templating Features
- Go templating: All YAML files (including values) support Go templates and Sprig functions.
- Dynamic values: Use functions like
readFile
,requiredEnv
, and more. - .gotmpl files: Use
.gotmpl
extension for values files to enable templating. text# values-dev.yaml.gotmpl replicaCount: {{ if eq .Environment.Name "prod" }}3{{ else }}1{{ end }}
Best Practices for Multi-Environment Management
- Use the
environments
block to define environment-specific values and settings insidehelmfile.yaml
: textenvironments: dev: values: [values-dev.yaml] prod: values: [values-prod.yaml]
- Directory structure: text
. ├── helmfile.yaml ├── values-dev.yaml ├── values-prod.yaml └── common-values.yaml
- Override only what’s different in each environment’s values file.
Integrating Helmfile into GitOps and CI/CD Pipelines
- Store all Helmfile configs and values in Git
- Typical CI/CD pipeline: text
helmfile -e dev apply
- With ArgoCD: Use Helmfile to bootstrap ArgoCD or manage its configuration.
- In GitHub Actions: text
- uses: azure/setup-helm@v3 - run: helmfile -e staging apply
Troubleshooting, Debugging, and Optimization
- Dry-run and diff: text
helmfile -e dev diff helmfile -e dev apply --dry-run
- Debug logs: text
HELMFILE_LOG_LEVEL=debug helmfile apply
- Helm troubleshooting: Use
helm lint
,helm template --debug
, andhelm install --dry-run --debug
for underlying chart issues. - Optimize by modularizing your helmfiles (split into
helmfile.d/*.yaml
), and use labels/selectors for targeted deployments.
Real-World Examples, Sample Configs, and Pro Tips
Multi-environment setup:
textenvironments:
dev:
values: [values/dev.yaml]
prod:
values: [values/prod.yaml]
releases:
- name: my-app
chart: stable/my-app
namespace: default
values:
- common.yaml
- "values/{{ .Environment.Name }}.yaml"
Directory structure for modular Helmfiles:
text.
├── helmfile.yaml
├── helmfile.d/
│ ├── frontend.yaml
│ ├── backend.yaml
├── values/
│ ├── dev/
│ ├── prod/
Pro tips:
- Use
needs
for complex dependency ordering - Use
.gotmpl
for dynamic templating - Use selectors and labels for targeted deployments
- Use
helmfile sync
for idempotent, always-up-to-date deployments
Comparison: Helmfile vs. Helmsman vs. Helmwave
Feature | Helmfile | Helmsman | Helmwave |
---|---|---|---|
Syntax | YAML + sprig | TOML/YAML | YAML + sprig/gomplate |
Parallel Deployments | Yes | Limited | Yes |
Dependency Management | needs | Priority | depends_on |
Advanced Templating | Sprig | None | Sprig, Gomplate |
Secret Management | helm-secrets, custom | ? | Via gomplate |
Live Resource Tracking | No | No | Yes (kubedog) |
Planfile Support | No | No | Yes |
Multi-environment Support | Strong | Basic | Strong |
Summary:
- Helmfile is the most widely adopted, flexible, and integrates deeply with Helm and CI/CD workflows.
- Helmsman is simpler, focused on basic declarative deployments.
- Helmwave is newer, offers advanced templating and live tracking, and bundles Helm internally for easier portability.
Helmfile empowers you to manage complex Kubernetes deployments declaratively, reproducibly, and at scale. With its modularity, templating, and environment management, it’s a cornerstone for modern GitOps and CI/CD workflows.