Organize Charts with Dependencies
Learn to structure Helm charts with dependencies, enabling modular, reusable deployments. This hands-on lesson covers defining requirements, updating dependencies, and managing version constraints for organized Kubernetes applications.
Focus: organize charts with dependencies
You've built a few Helm charts by now — each one a standalone package of Kubernetes manifests. But real-world applications rarely live in isolation. A web app needs a database, a message queue, or a caching layer. Copying those manifests into every chart is a maintenance nightmare. Organizing charts with dependencies solves this: you declare what your chart needs, and Helm fetches, installs, and wires everything together. This lesson shows you how to define, update, and manage dependent charts — turning a tangled mess of YAML into a clean, reusable dependency tree.
The problem this lesson solves
Imagine you maintain a microservice that relies on PostgreSQL, Redis, and a sidecar logging agent. Without dependencies, you either:
- Copy the same
postgresqlDeployment, Service, and PVC YAML into every chart that needs a database — violating DRY principles and guaranteeing drift as versions diverge. - Expect developers to manually install prerequisites in the correct order, then pass connection strings via brittle scripts.
Both approaches fail at scale. Helm chart dependencies let you declare "this chart requires these subcharts" inside the parent chart. When you run helm install, Helm automatically:
- Resolves all dependencies
- Downloads them (or references them locally)
- Installs them in the correct order
- Exposes values for customisation
This keeps your chart focused on its own logic while reusing battle-tested subcharts from registries or local paths.
Core concept / mental model
Think of a Helm chart as an app module in a package manager — similar to package.json in npm or requirements.txt in Python. The file Chart.yaml gains an optional dependencies field, and you can also use a dedicated charts/ directory or a requirements.yaml (deprecated but still seen in older projects).
Definitions:
- Parent chart: The chart you're authoring — it consumes dependencies.
- Subchart: A child chart installed as part of the parent chart release. Subcharts are regular Helm charts; they have their own templates/, values.yaml, and Chart.yaml.
- Dependency resolution: helm dependency update reads your Chart.yaml dependencies, fetches them into charts/, and generates Chart.lock for reproducible builds.
Key mental model: A parent chart's values.yaml can override a subchart's default values by nesting keys under the subchart's name. This is the pattern that makes organizing charts with dependencies so powerful — centralised configuration, modular components.
How it works step by step
1. Declare dependencies in Chart.yaml
Add a dependencies block under apiVersion: v2:
# myapp/Chart.yaml
apiVersion: v2
name: myapp
description: A web app with dependencies
dependencies:
- name: postgresql
version: "~12.1.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
- name: redis
version: ">=17.0.0"
repository: "https://charts.bitnami.com/bitnami"
name,version,repositoryare mandatory.conditionties the subchart to a parent value — ifpostgresql.enabled: falsein your values, Helm skips installing that subchart.- Use semver ranges:
~12.1.0means>=12.1.0 <12.2.0;>=17.0.0means any 17.x or higher.
2. Run helm dependency update
cd myapp
helm dependency update
This:
- Downloads the subchart tarballs into charts/
- Generates Chart.lock with exact versions
- Removes outdated subcharts
3. Override subchart values
To set the PostgreSQL password and Redis port from the parent chart, add subchart-specific keys:
# myapp/values.yaml
postgresql:
enabled: true
auth:
password: "securepass123"
database: myapp_db
redis:
architecture: standalone
auth:
enabled: false
Helm merges these with the subchart's default values.yaml — the parent values win.
4. Install the parent chart
helm install myapp-release ./myapp
Helm deploys the parent chart's templates and all subcharts as a single release. You can see them with:
helm status myapp-release
helm get manifest myapp-release | grep -A5 'kind:'
Hands-on walkthrough
Let's build a chart called microblog that depends on Bitnami's PostgreSQL and a local subchart auth-svc.
Step 1: Scaffold the parent chart
helm create microblog
cd microblog
Delete the default templates/ contents — we'll focus on dependencies.
Step 2: Add PostgreSQL dependency
Edit Chart.yaml:
apiVersion: v2
name: microblog
description: A microblogging application
dependencies:
- name: postgresql
version: "~12.1.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
Step 3: Add a local subchart
Create a local chart:
helm create charts/auth-svc
# remove default manifests in auth-svc/templates — we'll keep it minimal
Add it as a dependency (Helm allows file:// URIs for local charts):
# Chart.yaml
- name: auth-svc
version: "0.1.0"
repository: "file://./charts/auth-svc"
Step 4: Update and inspect
helm dependency update
Output:
Getting updates for unmanaged Helm repositories...
…Successfully got an update from the "https://charts.bitnami.com/bitnami" chart repository
Update Complete. Preparing the update…
Downloading postgresql from repo https://charts.bitnami.com/bitnami
Save: charts/postgresql-12.1.0.tgz
Delete: charts/postgresql-12.1.0.tgz (re-downloaded)
Lock file charts/Chart.lock already exists. Overwrite?
Now ls charts/ shows both auth-svc/ directory and the downloaded postgresql-12.1.0.tgz.
Step 5: Override subchart values
Edit values.yaml:
postgresql:
enabled: true
auth:
database: microblog_db
username: microblog_user
password: changeme
auth-svc:
replicaCount: 2
Step 6: Install
helm install my-blog ./microblog
Check that the release includes subchart resources:
kubectl get pods -l app.kubernetes.io/instance=my-blog
You'll see my-blog-postgresql-0 and my-blog-auth-svc-xxx (naming: <release>-<chartname>).
Compare options / when to choose what
| Method | Use case | Pros | Cons |
|---|---|---|---|
| Repository dependency (Bitnami, stable) | Common infrastructure (DB, cache, message queue) | Version pinning, automatic updates | Requires network, registry access |
Local subchart (file:// path) |
Own microservices, proprietary components | No external registry; direct dev control | Must manage versioning yourself |
Simple charts/ copy (manual) |
Quick experiments, no version management | No dependency syntax needed | No automatic updates; manual sync errors |
requirements.yaml (Helm 2 legacy) |
Older projects not yet migrated | Already exists (don't break it) | Deprecated; avoid in new charts |
Recommendation: For any shared dependency (PostgreSQL, Redis, Prometheus), use a remote repository and pin the minor version. For your own team's services, use local subcharts in a monorepo until you graduate to a private chart repository.
Troubleshooting & edge cases
Error: no repository definition for ...
Add the repo first:
helm repo add bitnami https://charts.bitnami.com/bitnami
helm dependency update
Error: version ... not found
Check the available versions:
helm search repo bitnami/postgresql --versions
Adjust the version constraint in Chart.yaml.
Subchart values not applied
Ensure the parent values.yaml keys match the subchart name exactly — case-sensitive. If the subchart is named postgresql, the key is postgresql:. Use helm get values my-blog to see the merged output.
Duplicate resource names
Subcharts automatically prefix resources with the release name and subchart name. If you still get conflicts, avoid hardcoding metadata.name — use Helm's {{ include "<chart>.fullname" . }} template inside subcharts.
Circular dependencies
Helm errors if two charts depend on each other. Break the cycle by extracting shared logic into a third chart or using a conditional flag (condition) that one side disables when the other is active.
What you learned & what's next
You now know how to organize charts with dependencies — from declaring dependencies in Chart.yaml to updating them with helm dependency update and overriding subchart values. This modular approach keeps your charts clean, reusable, and aligned with the DRY principle. The mental model of parent/subchart is the foundation of Helm's dependency system.
Key takeaways:
- Dependencies live in Chart.yaml under the dependencies key
- Run helm dependency update to fetch subcharts into charts/
- Parent values override subchart defaults using the subchart name as a prefix
- Use semver constraints to control version ranges
- Local subcharts (file://) work well for internal microservices
- Avoid circular dependencies and always pin minor versions in production
Next up: Helm Testing with helm test — you'll learn to write hooks and run validation inside your charts, ensuring dependencies are actually healthy after deployment.
Practice recap
Create a new chart myapp that depends on the Bitnami Redis chart (version >=17.0.0) and a local subchart cache-sidecar (in charts/cache-sidecar). Run helm dependency update, override Redis to use standalone mode, and install the chart. Verify that both a Redis pod and your sidecar pod appear under the same release.
Common mistakes
- Forgetting to run
helm repo addfor external repositories beforehelm dependency update— Helm can't fetch from an unknown repo. - Overriding subchart values with wrong key names (e.g.,
PostgreSQLinstead ofpostgresql) — the key must match the subchart name exactly, case-sensitive. - Using a semver constraint that's too loose (e.g.,
*or>=0.0.0) — this can pull breaking changes on update. Always pin to at least minor version (e.g.,~12.1.0). - Not regenerating
Chart.lockafter changing dependency versions — leads to inconsistent installs across environments.
Variations
- You can maintain a monorepo with local subcharts and symlink them during development instead of using
file://paths for faster iteration. - For air-gapped environments, pre-download all subchart tarballs into
charts/and remove the repository reference fromChart.yaml— Helm then uses only cached files. - Helm 3 supports OCI-based registries; you can store dependencies in an OCI registry (e.g.,
oci://registry.example.com/helm-charts) using the same dependency syntax.
Real-world use cases
- A microservice chart depends on Bitnami's PostgreSQL subchart — when the microservice is deployed, PostgreSQL installs automatically with custom credentials.
- A CI/CD pipeline updates subchart versions via
helm dependency updateand builds the full application stack from multiple team-owned charts. - A production Helm chart depends on a local logging sidecar subchart from the same repository — updates to the sidecar are pulled in without copying manifests.
Key takeaways
- Helm chart dependencies declare required subcharts in
Chart.yaml, enabling modular and reusable deployments. - Run
helm dependency updateto download subcharts intocharts/and generate a reproducibleChart.lock. - Parent chart values override subchart defaults using the subchart name as a nested key — keep them case-sensitive.
- Use semver constraints (e.g.,
~12.1.0) to control version ranges without breaking on minor patches. - Local subcharts (
file://) are ideal for internal microservices; external ones from repositories suit shared infrastructure. - Avoid circular dependencies; always regenerate
Chart.lockafter modifying dependency versions.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.