Free lesson · GenAI Platform Engineering

Deploy complete platform with Helm umbrella chart

Create a Helm umbrella chart that deploys all platform services (control plane, gateway, registry, eval, compliance, monitoring) as a single managed release.

Course: AI Developer Platform Engineering · Chapter 20 · AI Platform Capstone

Free to read — no subscription required.

Introduction

When you manage a multi-tenant AI platform, deploying a dozen microservices—control plane, LLM gateway, model registry, evaluation service, compliance engine—as individual Helm charts means every release becomes a coordination exercise across teams, versions, and configuration files that can drift apart. A Helm umbrella chart solves this by declaring all platform services as dependencies in a single Chart.yaml, giving operators one command to install or upgrade the entire stack. By the end of this lesson, you'll be able to author a Helm umbrella chart, generate its Chart.yaml programmatically, and build per-environment values files that propagate shared configuration to every sub-chart.

Key Terminology

  • Helm umbrella chart — a parent Helm chart whose Chart.yaml lists every platform service as a named dependency, allowing helm upgrade --install to deploy the entire stack as a single, versioned unit rather than coordinating individual chart releases.
  • Sub-chart dependency — an entry in the umbrella's dependencies list (modeled by HelmDependency) that names a child chart, pins it to a semantic version, and points to either a remote Helm repository or a local file:// path for development-time sub-charts.
  • Dependency condition — a dotted-key string in the condition field of a HelmDependency (e.g., llmGateway.enabled) that Helm evaluates against the active values file to enable or disable that sub-chart per environment without requiring separate chart definitions.
  • Values inheritance — the mechanism by which top-level keys in values-production.yaml or values-staging.yaml (PostgreSQL connection string, Redis endpoint, platform domain) automatically propagate into every sub-chart's own values namespace, avoiding duplicated configuration across services.
  • UmbrellaChartGenerator — the Python class in the walkthrough that accepts an UmbrellaChart model, accumulates HelmDependency entries via add_dependency(), and emits a valid Chart.yaml string through generate_chart_yaml() using yaml.dump with stable key ordering.
  • Semantic version constraint — the Field(pattern=r"^\d+\.\d+\.\d+$") validator on HelmDependency.version that enforces strict MAJOR.MINOR.PATCH format, preventing range specifiers or pre-release suffixes from entering the generated Chart.yaml.

Concepts

One Release Command for the Entire Platform

Deploying a multi-tenant AI platform one chart at a time—control plane, LLM gateway, model registry, evaluation service, compliance engine—forces release engineers to track which version of each service is compatible with every other, run helm upgrade across a dozen repositories, and manually verify that shared secrets and endpoints stay consistent. A single misconfigured image tag or a missed upgrade leaves the platform in a partially-updated state with no straightforward rollback boundary.

A Helm umbrella chart collapses all of that into a single artifact. The umbrella's Chart.yaml declares each platform service as a dependency entry; helm dependency update fetches or validates every sub-chart, and helm upgrade --install ai-platform . treats the entire stack as one atomic release. Rolling back to the previous platform version rolls back every sub-chart together. The umbrella chart itself carries a version that acts as the platform release number—teams can tag, promote, and audit it like any other versioned artifact.

Values Inheritance and Per-Environment Enablement

When an operator applies values-production.yaml, Helm merges those values into the umbrella's value tree before rendering any sub-chart templates. Any top-level key the sub-chart expects—such as a PostgreSQL connection string or an internal service hostname—can be defined once at the umbrella level and inherited automatically, eliminating the drift that accumulates when each sub-chart carries its own copy of shared configuration (see Code Walkthrough).

Per-environment enablement builds on the same mechanism. The condition field on each HelmDependency (e.g., controlPlane.enabled) maps to a boolean in the values file. Setting that key to false in values-staging.yaml instructs Helm to skip rendering that sub-chart's manifests entirely. This means the same umbrella chart definition describes both environments; you never maintain parallel chart hierarchies for staging versus production.

Loading diagram...

Programmatic Chart.yaml Generation

Hand-editing a Chart.yaml that lists fifteen services is fragile: a missing quote, an invalid version string, or a forgotten condition key is easy to overlook during review and breaks helm dependency update at deploy time with a cryptic parse error. The lesson's generator approach treats Chart.yaml content as structured data first and YAML second.

HelmDependency enforces the ^\d+\.\d+\.\d+$ version pattern at construction time, so invalid entries are caught in Python before they ever reach Helm. UmbrellaChart holds the top-level metadata, and UmbrellaChartGenerator.generate_chart_yaml() serializes the validated object graph into YAML with default_flow_style=False and sort_keys=False to produce human-readable, diff-friendly output. Infrastructure dependencies like postgresql reference public Bitnami repositories; platform-specific sub-charts use file:// paths locally and can be swapped to a private OCI registry URL for production without changing the rest of the generator logic. Before running helm upgrade --install, verifying both helm dependency update (dependency resolution) and helm template ai-platform . (manifest rendering) catches configuration errors without touching the cluster.

Code Walkthrough

Now that you understand how Helm resolves sub-chart dependencies and propagates shared configuration through values inheritance, you can build the umbrella chart that ties every platform service together.

The umbrella chart's Chart.yaml lists all platform services as dependencies. Helm downloads and installs them in dependency order, treating the umbrella as a single deployable unit. Shared values—PostgreSQL connection string, Redis endpoint, platform domain—are defined once at the umbrella level and flow into each sub-chart automatically.

Loading diagram...

Because large platforms involve many services and manual YAML editing is error-prone, you can generate Chart.yaml programmatically. HelmDependency validates each sub-chart reference—enforcing semantic versioning format and capturing the condition field that controls per-environment enablement. UmbrellaChart holds the top-level metadata, and UmbrellaChartGenerator.generate_chart_yaml() produces the YAML content Helm reads during helm dependency update.

Code snippetpython
1from pydantic import BaseModel, Field 2import yaml 3 4class HelmDependency(BaseModel): 5 name: str 6 version: str = Field(pattern=r"^\d+\.\d+\.\d+$") 7 repository: str 8 condition: str | None = None 9 tags: list[str] = Field(default_factory=list) 10 11class UmbrellaChart(BaseModel): 12 api_version: str = "v2" 13 name: str = "ai-platform" 14 description: str = "AI Developer Platform - Complete Stack" 15 chart_type: str = "application" 16 version: str = "1.0.0" 17 app_version: str = "1.0.0" 18 dependencies: list[HelmDependency] = Field(default_factory=list) 19 20class UmbrellaChartGenerator: 21 def __init__(self, chart: UmbrellaChart) -> None: 22 self.chart = chart 23 24 def add_dependency(self, dep: HelmDependency) -> None: 25 self.chart.dependencies.append(dep) 26 27 def generate_chart_yaml(self) -> str: 28 chart_dict = { 29 "apiVersion": self.chart.api_version, 30 "name": self.chart.name, 31 "description": self.chart.description, 32 "type": self.chart.chart_type, 33 "version": self.chart.version, 34 "appVersion": self.chart.app_version, 35 "dependencies": [], 36 } 37 for dep in self.chart.dependencies: 38 dep_dict = {"name": dep.name, "version": dep.version, "repository": dep.repository} 39 if dep.condition: 40 dep_dict["condition"] = dep.condition 41 if dep.tags: 42 dep_dict["tags"] = dep.tags 43 chart_dict["dependencies"].append(dep_dict) 44 return yaml.dump(chart_dict, default_flow_style=False, sort_keys=False) 45 46umbrella = UmbrellaChart() 47generator = UmbrellaChartGenerator(chart=umbrella) 48 49generator.add_dependency(HelmDependency( 50 name="postgresql", version="12.1.0", 51 repository="https://charts.bitnami.com/bitnami", 52 tags=["database"], 53)) 54generator.add_dependency(HelmDependency( 55 name="control-plane", version="1.0.0", 56 repository="file://../charts/control-plane", 57 condition="controlPlane.enabled", 58)) 59generator.add_dependency(HelmDependency( 60 name="llm-gateway", version="1.0.0", 61 repository="file://../charts/llm-gateway", 62 condition="llmGateway.enabled", 63)) 64 65print(generator.generate_chart_yaml())

The condition field on each dependency maps to a key in values-production.yaml or values-staging.yaml, letting you enable or disable individual platform services per environment without maintaining separate chart definitions. Infrastructure dependencies like PostgreSQL reference public Helm repositories, while platform-specific sub-charts use local file:// references during development and a private OCI registry in production.

Confirm that helm dependency update completes without errors and that helm template ai-platform . renders manifests for every enabled sub-chart before you run helm upgrade --install.

Do's and Don'ts

Building on the umbrella chart structure and discipline-specific framing above, the following practices keep your platform-wide releases predictable as the dependency list grows.

Do's

  1. Do use the condition field on every platform sub-chart dependency — mapping it to a per-environment key like controlPlane.enabled or llmGateway.enabled lets you enable or disable individual services in values-production.yaml vs. values-staging.yaml without maintaining separate umbrella chart definitions for each environment.
  2. Do define shared infrastructure values—PostgreSQL connection string, Redis endpoint, platform domain—once at the umbrella level — these propagate automatically into every sub-chart through Helm's values inheritance, preventing configuration drift across control-plane, LLM gateway, model registry, and other services that all depend on the same backing resources.
  3. Do run helm dependency update and helm template ai-platform . before helm upgrade --installhelm dependency update fetches and locks all sub-chart versions declared in Chart.yaml, and helm template renders manifests for every enabled sub-chart so you can catch missing dependencies or misconfigured conditions before they reach the cluster.

Don'ts

  1. Don't hand-edit Chart.yaml dependency entries for large platform stacks — manually maintaining version strings across control-plane, llm-gateway, model-registry, eval-service, compliance-engine, and monitoring-stack is error-prone; use UmbrellaChartGenerator.generate_chart_yaml() with HelmDependency validation (including the ^\d+\.\d+\.\d+$ version pattern) to produce the file programmatically and catch malformed entries at generation time.
  2. Don't use the same values.yaml file for production and staging environments — omitting per-environment values files forces you to either ship disabled services to production or enable experimental services in staging by toggling chart-level defaults, defeating the condition-based enablement model the umbrella chart is built around.
  3. Don't mix file:// local references and public repository URLs in a production Chart.yaml without a private OCI registry fallback — local file://../charts/control-plane references work during development but break in CI and GitOps pipelines where the umbrella chart is applied from a runner that has no access to the local filesystem layout; platform-specific sub-charts must be pushed to a private OCI registry before the umbrella chart is used outside a developer workstation.

This lesson is free to read. Its 3 hands-on labs — real code, in a cloud IDE — are part of the GenAI Platform Engineering subscription.

From · cancel anytime

More free lessons in AI Developer Platform Engineering

All free lessons in GenAI Platform Engineering