Skip to main content

Chart Dependencies

In Lessons 1-3, you built sophisticated Helm charts from scratch: advanced templating, named helpers, and multi-environment values management. But professional AI deployments rarely start with nothing. Your AI agent needs PostgreSQL for state storage, Redis for caching, and perhaps RabbitMQ for message queues.

Instead of writing database charts yourself, you'll use community charts maintained by Bitnami and others. Helm dependency management is how you compose these public charts into your custom chart—a single helm install deploys your agent, its database, and all supporting services together.

This lesson teaches how to declare, configure, and manage chart dependencies—transforming your custom chart into an orchestration layer that composes production infrastructure.


What You'll Learn

This lesson covers 9 concepts organized into three groups:

Concept GroupConceptsFocus
Dependency Declaration1-3Chart.yaml syntax, version constraints, fetching subcharts
Conditional Management4-5Enabling/disabling dependencies with conditions and tags
Configuration Patterns6-9Passing values, import-values, aliases, complete workflow

Prerequisites:

  • Lessons 1-3 completed (Chart.yaml structure, templates, values management)
  • Understanding of semantic versioning (MAJOR.MINOR.PATCH)
  • Familiarity with YAML nested structures

Time Estimate: 50 minutes

  • Concepts: 25 minutes
  • Exercises: 20 minutes
  • Try With AI: 5 minutes

Concept 1: Chart.yaml Dependencies Section

A Helm chart declares its dependencies in Chart.yaml using a dependencies: list. Each dependency specifies a repository, chart name, version, and optional metadata.

Basic Dependency Declaration

# my-agent-chart/Chart.yaml
apiVersion: v2
name: my-agent
version: 0.1.0
description: AI agent with PostgreSQL and Redis

dependencies:
- name: postgresql
version: "13.2.0"
repository: "https://charts.bitnami.com/bitnami"
- name: redis
version: "18.5.0"
repository: "https://charts.bitnami.com/bitnami"

Output:

When you run helm dependency list my-agent-chart, Helm displays:

NAME            VERSION         REPOSITORY
postgresql 13.2.0 https://charts.bitnami.com/bitnami
redis 18.5.0 https://charts.bitnami.com/bitnami

Each dependency entry tells Helm: "Find this chart at that repository with that version."


Concept 2: Subchart Resolution

Declaring a dependency is not enough—Helm must fetch the actual chart files. The helm dependency update command downloads subcharts and stores them in a charts/ directory.

Running Dependency Update

helm dependency update my-agent-chart

Output:

Getting updates for unmanaged Helm repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈

The charts/ Directory

After running helm dependency update, your chart structure becomes:

my-agent-chart/
├── Chart.yaml
├── values.yaml
├── charts/
│ ├── postgresql/
│ │ ├── Chart.yaml
│ │ ├── values.yaml
│ │ ├── templates/
│ │ └── ...
│ └── redis/
│ ├── Chart.yaml
│ ├── values.yaml
│ ├── templates/
│ └── ...
├── templates/
│ ├── deployment.yaml
│ └── ...
└── ...

The charts/ directory contains complete subcharts. Helm treats them as part of your chart when rendering and installing.


Concept 3: Version Constraints (Semantic Versioning)

Specifying exact versions ("13.2.0") is restrictive. Version constraints allow you to accept compatible updates automatically.

Semantic Versioning Rules

Helm uses standard semantic versioning constraints:

dependencies:
# Exact version only
- name: postgresql
version: "13.2.0"
repository: "https://charts.bitnami.com/bitnami"

# Caret: Compatible with this minor version (13.x.x)
- name: redis
version: "^18.5.0"
repository: "https://charts.bitnami.com/bitnami"

# Tilde: Compatible with this patch version (18.5.x)
- name: rabbitmq
version: "~11.1.0"
repository: "https://charts.bitnami.com/bitnami"

# Greater than or equal (allows any newer version)
- name: mongodb
version: ">=13.0.0"
repository: "https://charts.bitnami.com/bitnami"

# Range (version 12.x up to but not including 13.0.0)
- name: elasticsearch
version: ">=12.0.0,<13.0.0"
repository: "https://charts.bitnami.com/bitnami"

Output (helm dependency update behavior):

  • "13.2.0" → Always installs exactly 13.2.0 (no updates)
  • "^18.5.0" → Installs 18.5.0, but accepts 18.10.0 or 18.99.0 (minor/patch updates)
  • "~11.1.0" → Installs 11.1.0, but accepts 11.1.3 (patch updates only)
  • ">=13.0.0" → Installs 13.0.0 and accepts any newer version (risky in production)

For production AI services, use caret (^) constraints to get bug fixes without risking breaking changes.


Concept 4: Conditions for Optional Dependencies

Not every deployment needs every dependency. A developer environment might skip PostgreSQL (using SQLite instead), while production requires it. The condition: field gates whether a subchart is installed.

Conditional Dependency Declaration

# my-agent-chart/Chart.yaml
dependencies:
- name: postgresql
version: "^13.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled

- name: redis
version: "^18.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled

Controlling with Values

# my-agent-chart/values.yaml
postgresql:
enabled: true
auth:
username: agent
password: secretpassword
database: agent_db

redis:
enabled: false # Skip Redis in default config

Output (helm install with this values.yaml):

  • PostgreSQL subchart IS rendered and installed (condition: postgresql.enabled = true)
  • Redis subchart is NOT rendered (condition: redis.enabled = false)

To enable Redis:

helm install my-agent ./my-agent-chart --set redis.enabled=true

Concept 5: Tags for Grouping Dependencies

When you have many optional dependencies, managing them individually is tedious. The tags: field groups dependencies, so you can enable/disable groups with a single condition.

Tagging Dependencies

# my-agent-chart/Chart.yaml
dependencies:
# Database tier
- name: postgresql
version: "^13.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
tags:
- database

# Caching tier
- name: redis
version: "^18.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
tags:
- cache

# Message queue tier
- name: rabbitmq
version: "^12.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: rabbitmq.enabled
tags:
- messaging

Controlling with Tag Values

# my-agent-chart/values.yaml
tags:
database: true # Enable all dependencies tagged with "database"
cache: false # Disable all dependencies tagged with "cache"
messaging: false # Disable all dependencies tagged with "messaging"

postgresql:
enabled: null # Controlled by "database" tag
redis:
enabled: null
rabbitmq:
enabled: null

Output:

  • PostgreSQL is installed (because tags.database=true)
  • Redis and RabbitMQ are skipped (their tags are false)

To enable all data services:

helm install my-agent ./my-agent-chart --set tags.cache=true --set tags.messaging=true

Checkpoint: Dependency Declaration & Control

You've covered the fundamentals of dependency management. Here's a quick reference:

FeatureSyntaxPurposeExample
Basic dependencyname:, version:, repository:Declare subchart requirementpostgresql 13.2.0
Version constraint^, ~, >=, rangesAllow compatible updates^13.0.0 (minor/patch OK)
Conditioncondition: subchart.enabledOptional dependencyEnable/disable per environment
Tagstags: [database]Group dependenciesEnable all databases together
Fetch subchartshelm dependency updateDownload to charts/Creates local copies

Self-Check Questions:

  1. Version Constraints: If you declare version: "^18.5.0" for Redis, will Helm accept version 19.0.0?

    AnswerNo. Caret (^) allows minor and patch updates within the same major version (18.x.x), but not major version changes.

  2. Conditions vs Tags: When would you use condition: instead of tags:?

    AnswerUse condition: for individual dependency control. Use tags: when grouping related dependencies (like all caching services) for bulk enable/disable.

  3. Missing helm dependency update: What happens if you add a dependency to Chart.yaml but skip helm dependency update?

    AnswerHelm install will fail with a "dependency not found" error because the subchart files don't exist in charts/ yet.


Concept 6: import-values for Subchart Configuration

Subcharts have their own values.yaml files with configurations. You configure them through your parent values, but exposing subchart settings directly clutters your values file. The import-values: field re-exports selected subchart values to your parent namespace.

Standard Approach (No import-values)

Without import-values, subchart configuration is deeply nested:

# my-agent-chart/values.yaml
postgresql:
auth:
username: agent
password: secretpassword
database: agent_db
primary:
persistence:
size: 10Gi
metrics:
enabled: true

In your templates, you reference the full path: {{ .Values.postgresql.auth.username }}.

Simplifying with import-values

# my-agent-chart/Chart.yaml
dependencies:
- name: postgresql
version: "^13.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
import-values:
- child: auth
parent: postgresqlAuth
- child: primary.persistence
parent: postgresqlStorage

With this mapping, your values become:

# my-agent-chart/values.yaml
postgresqlAuth:
username: agent
password: secretpassword
database: agent_db

postgresqlStorage:
size: 10Gi

In templates: {{ .Values.postgresqlAuth.username }} (cleaner namespace).

Output:

When Helm renders, the import-values mapping translates postgresqlAuth back to the subchart's auth namespace, so PostgreSQL receives the correct configuration.


Concept 7: Passing Configuration to Subcharts

Subcharts inherit parent values using a specific naming convention. The subchart name becomes a key in the parent values.

Configuration Hierarchy

# my-agent-chart/values.yaml
# Direct subchart configuration
postgresql:
auth:
username: agent
password: secretpassword
primary:
persistence:
enabled: true
size: 20Gi

redis:
auth:
enabled: true
password: cachepassword
replica:
replicaCount: 2

Output (how subcharts receive values):

When Helm renders the postgresql subchart, it has access to .Values.postgresql.* configuration. The subchart's templates reference its own .Values.auth.username, but the parent passes it via .Values.postgresql.auth.username.

Helm automatically translates the hierarchy: parent's postgresql: key becomes subchart's root values.


Concept 8: Aliases for Multiple Instances

Sometimes you need the same chart multiple times with different configurations (two PostgreSQL instances for different databases, or two Redis caches for different use cases). The alias: field enables this.

Multiple Instance Declaration

# my-agent-chart/Chart.yaml
dependencies:
# Primary database
- name: postgresql
version: "^13.0.0"
repository: "https://charts.bitnami.com/bitnami"
alias: postgresql-primary

# Secondary database for analytics
- name: postgresql
version: "^13.0.0"
repository: "https://charts.bitnami.com/bitnami"
alias: postgresql-analytics

Configuring Each Instance

# my-agent-chart/values.yaml
postgresql-primary:
auth:
database: agent_primary
primary:
persistence:
size: 50Gi

postgresql-analytics:
auth:
database: agent_analytics
primary:
persistence:
size: 100Gi # Larger for analytics data

Output:

Two independent PostgreSQL instances are deployed, each receiving its own configuration. The alias key determines which subchart configuration applies.


Concept 9: The Complete Dependency Workflow

Here's how all these pieces work together:

Step 1: Declare Dependencies in Chart.yaml

# my-agent-chart/Chart.yaml
apiVersion: v2
name: my-agent-chart
version: 1.0.0

dependencies:
- name: postgresql
version: "^13.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
tags:
- database

Step 2: Configure in values.yaml

# my-agent-chart/values.yaml
tags:
database: true

postgresql:
enabled: null # Controlled by tag
auth:
username: agent
password: mypassword
database: agentdb
primary:
persistence:
size: 10Gi

Step 3: Update Dependencies

cd my-agent-chart
helm dependency update

Output:

Getting updates for unmanaged Helm repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈

The charts/postgresql/ directory now exists.

Step 4: Reference Subchart Values in Templates

# my-agent-chart/templates/deployment.yaml
spec:
containers:
- name: agent
env:
- name: DATABASE_HOST
value: "{{ .Release.Name }}-postgresql"
- name: DATABASE_USER
value: "{{ .Values.postgresql.auth.username }}"
- name: DATABASE_NAME
value: "{{ .Values.postgresql.auth.database }}"

Step 5: Install Combined Chart

helm install my-agent ./my-agent-chart

Output:

NAME: my-agent
STATUS: deployed
REVISION: 1

Resources created:
- Deployment (my-agent)
- Service (my-agent)
- StatefulSet (my-agent-postgresql)
- Service (my-agent-postgresql)
- ConfigMap (my-agent-postgresql-config)
- Secret (my-agent-postgresql-password)
...

A single helm install command deployed your agent, its database, and all supporting infrastructure.


Common Mistakes

1. Forgetting helm dependency update After Changing Chart.yaml

# Added new dependency to Chart.yaml
dependencies:
- name: redis
version: "^18.0.0"
repository: "https://charts.bitnami.com/bitnami"
# Immediately run helm install without updating
helm install my-agent ./my-agent-chart
# ERROR: dependency "redis" not found

Fix: Always run helm dependency update after modifying the dependencies: section.

2. Using Exact Versions in Production

dependencies:
- name: postgresql
version: "13.2.0" # ❌ Locked to exact version, no security patches

Fix: Use semantic versioning constraints like ^13.2.0 to automatically receive patch and minor updates.

3. Conflicting Condition and Tag Settings

# Chart.yaml
dependencies:
- name: postgresql
condition: postgresql.enabled
tags:
- database
# values.yaml - CONFLICT
tags:
database: false # Tag says disable

postgresql:
enabled: true # Condition says enable

What happens: The condition: field takes precedence over tags:, so PostgreSQL WILL be installed (enabled=true wins).

Fix: When using both conditions and tags, set individual enabled: to null and control via tags only.

4. Incorrect import-values Mapping

# Chart.yaml - WRONG
import-values:
- child: auth
parent: postgresql.auth # ❌ Don't nest under subchart name

Fix: The parent: field creates a NEW top-level key in parent values:

import-values:
- child: auth
parent: postgresAuth # ✅ Top-level key

5. Forgetting to Configure Subchart Service Names

# Parent deployment.yaml - WRONG
env:
- name: DATABASE_HOST
value: "postgresql" # ❌ Missing release name prefix

Fix: Subchart service names are prefixed with the release name:

env:
- name: DATABASE_HOST
value: "{{ .Release.Name }}-postgresql" # ✅ Full service name

Exercise 4.1: Add PostgreSQL Dependency

Add Bitnami PostgreSQL to your chart with version constraint ^13.0.0.

Instructions:

  1. Open your my-agent-chart/Chart.yaml
  2. Add a dependencies: section after description:
  3. Add PostgreSQL with repository https://charts.bitnami.com/bitnami

Expected outcome: You should be able to run helm dependency list my-agent-chart and see PostgreSQL listed.


Exercise 4.2: Add Condition for Optional PostgreSQL

Make PostgreSQL optional using the condition: postgresql.enabled field, then set the condition in values.yaml.

Instructions:

  1. Update Chart.yaml to add condition: postgresql.enabled to the PostgreSQL dependency
  2. Update values.yaml to add:
    postgresql:
    enabled: true

Expected outcome: PostgreSQL should only render when postgresql.enabled: true.


Exercise 4.3: Configure PostgreSQL via Parent Values

Set PostgreSQL username, password, and database through parent values.

Instructions:

  1. Update values.yaml:

    postgresql:
    enabled: true
    auth:
    username: agent
    password: secretpassword123
    database: myagentdb
    primary:
    persistence:
    enabled: true
    size: 10Gi
  2. Verify the structure matches PostgreSQL subchart expectations

Expected outcome: When you run helm template my-agent-chart, the PostgreSQL StatefulSet should have these auth values rendered.


Exercise 4.4: Use import-values to Expose PostgreSQL Configuration

Simplify parent values using import-values mapping.

Instructions:

  1. Update Chart.yaml:

    dependencies:
    - name: postgresql
    version: "^13.0.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
    import-values:
    - child: auth
    parent: postgresAuth
  2. Refactor values.yaml:

    postgresAuth:
    username: agent
    password: secretpassword123
    database: myagentdb

    postgresql:
    enabled: true
    primary:
    persistence:
    enabled: true
    size: 10Gi

Expected outcome: The import-values mapping automatically translates postgresAuth to PostgreSQL's auth namespace.


Exercise 4.5: Run helm dependency update and Verify charts/ Directory

Download subcharts and verify they're stored in charts/.

Instructions:

  1. Run: helm dependency update my-agent-chart
  2. List the contents: ls -la my-agent-chart/charts/
  3. Check PostgreSQL was downloaded: ls my-agent-chart/charts/postgresql/

Expected outcome: The charts/postgresql/ directory exists with a complete subchart.


Exercise 4.6: Create Environment-Specific Values File

Create a values-nodedb.yaml that disables PostgreSQL but enables a Redis cache for development.

Instructions:

  1. Create my-agent-chart/values-nodedb.yaml:

    postgresql:
    enabled: false

    redis:
    enabled: true
    auth:
    enabled: false # No password in dev
  2. Test rendering: helm template my-agent-chart -f my-agent-chart/values-nodedb.yaml

Expected outcome: PostgreSQL StatefulSet should NOT appear, but Redis Deployment should.


Try With AI

Part 1: Challenge Description

You're building a production chart for an AI model serving service that needs:

  • PostgreSQL for inference result caching
  • Redis for request deduplication
  • Optional RabbitMQ for async task queues

Set up a chart with these three dependencies, but make RabbitMQ optional (disabled by default).

Part 2: Initial Setup

Ask AI to generate the Chart.yaml with proper dependency declarations using the patterns you learned:

"I'm building a Helm chart for an AI model server. Create Chart.yaml with three dependencies: PostgreSQL (^13.0.0), Redis (^18.0.0), and RabbitMQ (^12.0.0) from Bitnami. Make RabbitMQ optional with condition: rabbitmq.enabled. Use semantic versioning constraints to allow patch updates."

Part 3: Configuration Review

Review the generated Chart.yaml and ask:

  • Are the repository URLs correct?
  • Are the version constraints appropriate for production?
  • Is the condition field properly formatted?

If the output is missing the condition: field for RabbitMQ or uses exact versions, request corrections.

Part 4: Values Configuration

Ask AI to generate matching values.yaml:

"Generate values.yaml for this chart with: postgresql.enabled=true, redis.enabled=true, rabbitmq.enabled=false. Include basic auth configuration for PostgreSQL (username: agent, database: agentdb)."

Part 5: Verification

Compare your AI-generated files against the requirements:

  • Does the condition: field on RabbitMQ prevent installation when not explicitly enabled?
  • Can you override these conditions with --set rabbitmq.enabled=true?
  • Does the values structure match the subchart expectations?

If all match → You've successfully composed a production multi-dependency chart.