Umbrella Charts
MATIH uses umbrella charts to orchestrate the deployment of multiple related services as a single Helm release. The two primary umbrella charts -- matih-control-plane and matih-data-plane -- aggregate all services within their respective architectural tiers, enabling coordinated deployments, shared dependency management, and consistent value propagation.
What Are Umbrella Charts?
An umbrella chart is a Helm chart whose primary purpose is to declare dependencies on other charts (subcharts) and coordinate their deployment. The umbrella chart itself typically contains minimal templates of its own -- its value lies in aggregating subcharts and providing a unified values surface.
matih-control-plane/ # Umbrella chart
Chart.yaml # Declares 10+ service subcharts
values.yaml # Unified values for all subcharts
values-auth.yaml # Auth-specific overrides
templates/ # Minimal templates (namespace, RBAC)
_helpers.tplmatih-control-plane Umbrella Chart
The control plane umbrella chart deploys all services that manage the multi-tenant platform.
Chart.yaml
apiVersion: v2
name: matih-control-plane
description: Matih Platform - Control Plane Services
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- matih
- control-plane
- multi-tenant
- enterprise
home: https://github.com/matih/matih-platform
sources:
- https://github.com/matih/matih-platform
maintainers:
- name: Matih Platform Team
email: platform@matih.ai
annotations:
artifacthub.io/license: Apache-2.0
artifacthub.io/category: platform
dependencies:
# Application services
- name: iam-service
version: "1.x.x"
repository: "file://../iam-service"
condition: iam-service.enabled
- name: tenant-service
version: "1.x.x"
repository: "file://../tenant-service"
condition: tenant-service.enabled
- name: config-service
version: "1.x.x"
repository: "file://../config-service"
condition: config-service.enabled
- name: audit-service
version: "1.x.x"
repository: "file://../audit-service"
condition: audit-service.enabled
- name: notification-service
version: "1.x.x"
repository: "file://../notification-service"
condition: notification-service.enabled
# Shared infrastructure
- name: postgresql
version: "13.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
- name: redis
version: "18.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
- name: kafka
version: "26.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: kafka.enabledDependency Types
The control plane umbrella references two types of dependencies:
| Type | Repository | Example | Purpose |
|---|---|---|---|
| Local file | file://../<service> | iam-service, tenant-service | MATIH application services |
| Remote registry | https://charts.bitnami.com/bitnami | postgresql, redis, kafka | Third-party infrastructure |
Local file references use relative paths from the umbrella chart directory. This means the umbrella and its subchart directories must be siblings:
infrastructure/helm/
matih-control-plane/ # Umbrella chart
iam-service/ # Subchart (file://../iam-service)
tenant-service/ # Subchart (file://../tenant-service)
config-service/ # Subchart (file://../config-service)
...Control Plane Values
The umbrella chart's values.yaml controls which subcharts are enabled and provides service-level overrides:
# Enable/disable individual services
iam-service:
enabled: true
replicaCount: 2
image:
tag: "" # Set by CD pipeline
tenant-service:
enabled: true
replicaCount: 2
image:
tag: ""
config-service:
enabled: true
replicaCount: 2
image:
tag: ""
audit-service:
enabled: true
replicaCount: 2
image:
tag: ""
notification-service:
enabled: true
replicaCount: 2
image:
tag: ""
# Shared PostgreSQL for control plane
postgresql:
enabled: true
auth:
existingSecret: "matih-cp-postgresql"
secretKeys:
adminPasswordKey: "postgres-password"
primary:
persistence:
enabled: true
size: 50Gi
storageClass: matih-premium-ssd
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2000m
memory: 4Gi
# Shared Redis for control plane
redis:
enabled: true
architecture: standalone
auth:
enabled: true
existingSecret: "matih-cp-redis"
master:
persistence:
enabled: true
size: 10Gi
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# Shared Kafka for control plane events
kafka:
enabled: false # Using Strimzi in data planematih-data-plane Umbrella Chart
The data plane umbrella chart is larger, deploying all services that power analytics, AI, ML, and data processing.
Chart.yaml
apiVersion: v2
name: matih-data-plane
description: MATIH Data Plane umbrella chart - deploys all data plane services
type: application
version: 1.0.0
appVersion: "1.0.0"
home: https://github.com/matih/matih-prototype
icon: https://matih.ai/logo.png
keywords:
- matih
- data-platform
- analytics
- ai
- ml
maintainers:
- name: MATIH Engineering
email: engineering@matih.ai
dependencies:
- name: query-engine
version: ">=0.1.0"
repository: "file://../query-engine"
condition: query-engine.enabled
- name: catalog-service
version: ">=0.1.0"
repository: "file://../catalog-service"
condition: catalog-service.enabled
- name: pipeline-service
version: ">=0.1.0"
repository: "file://../pipeline-service"
condition: pipeline-service.enabled
- name: semantic-layer
version: ">=0.1.0"
repository: "file://../semantic-layer"
condition: semantic-layer.enabled
- name: bi-service
version: ">=0.1.0"
repository: "file://../bi-service"
condition: bi-service.enabled
- name: ai-service
version: ">=0.1.0"
repository: "file://../ai-service"
condition: ai-service.enabled
- name: data-plane-agent
version: ">=0.1.0"
repository: "file://../data-plane-agent"
condition: data-plane-agent.enabled
- name: ml-service
version: ">=0.1.0"
repository: "file://../ml-service"
condition: ml-service.enabled
- name: data-quality-service
version: ">=0.1.0"
repository: "file://../data-quality-service"
condition: data-quality-service.enabled
- name: render-service
version: ">=0.1.0"
repository: "file://../render-service"
condition: render-service.enabled
- name: ops-agent-service
version: ">=0.1.0"
repository: "file://../data-plane/ops-agent-service"
condition: ops-agent-service.enabled
annotations:
category: Data Platform
licenses: Apache-2.0Data Plane Service Matrix
| Service | Technology | Port | Default Replicas | HPA Enabled |
|---|---|---|---|---|
| query-engine | Java/Spring Boot | 8080 | 2 | Yes |
| catalog-service | Java/Spring Boot | 8086 | 2 | Yes |
| pipeline-service | Java/Spring Boot | 8092 | 2 | Yes |
| semantic-layer | Java/Spring Boot | 8086 | 2 | Yes |
| bi-service | Java/Spring Boot | 8084 | 2 | Yes |
| ai-service | Python/FastAPI | 8000 | 2 | Yes |
| data-plane-agent | Java/Spring Boot | 8085 | 2 | No |
| ml-service | Python/FastAPI | 8000 | 2 | Yes |
| data-quality-service | Python/FastAPI | 8000 | 2 | Yes |
| render-service | Node.js | 8098 | 2 | Yes |
| ops-agent-service | Python/FastAPI | 8080 | 1 | No |
Helm Deep Merge Behavior
Understanding Helm's deep merge is critical when working with umbrella charts. Helm merges override files into the base values using these rules:
Merge Rules
| Data Type | Behavior | Example |
|---|---|---|
| Scalar (string, int, bool) | Override replaces base | replicaCount: 1 replaces replicaCount: 2 |
| Map/Object | Keys merge recursively | Base securityContext.runAsUser: 1000 + override securityContext.readOnlyRootFilesystem: false = both keys present |
| Array/List | Override replaces base entirely | Override tolerations: [] replaces any base tolerations |
The Deep Merge Trap
Consider this scenario:
# values.yaml (base)
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# values-dev.yaml (override)
securityContext:
runAsUser: 0 # Run as root for debuggingThe merged result is:
# Merged result (UNEXPECTED)
securityContext:
runAsNonRoot: true # LEAKED from base - conflicts with runAsUser: 0!
runAsUser: 0 # From override
runAsGroup: 1000 # LEAKED from base
readOnlyRootFilesystem: true # LEAKED from base
capabilities:
drop:
- ALL # LEAKED from baseThe runAsNonRoot: true leaked from the base and conflicts with runAsUser: 0, causing a container creation error.
The Correct Approach
Always override ALL keys in a section when any key changes:
# values-dev.yaml (CORRECT)
securityContext:
runAsNonRoot: false
runAsUser: 0
runAsGroup: 0
readOnlyRootFilesystem: false
capabilities:
drop: []Deep Dive: The deep merge behavior is especially dangerous with umbrella charts because values flow through two levels: the umbrella chart merges its values with the subchart defaults. If the umbrella chart sets
ai-service.securityContext.runAsUser: 0but the subchart'svalues.yamlhassecurityContext.runAsGroup: 1000, the merged result will contain both -- potentially creating an invalid configuration.
Dependency Management
Building Dependencies
Before deploying an umbrella chart, dependencies must be resolved:
# Download and package all dependencies
helm dependency build infrastructure/helm/matih-control-plane
# Update dependencies (fetches latest matching versions)
helm dependency update infrastructure/helm/matih-data-planeThis creates .tgz archives in the charts/ directory for remote dependencies and symlinks for local file dependencies.
Dependency Conditions
Each dependency has a condition field that controls whether the subchart is deployed:
dependencies:
- name: ai-service
condition: ai-service.enabled # Only deployed if ai-service.enabled = trueIn the umbrella values:
# Enable all services
ai-service:
enabled: true
# Disable a service during maintenance
pipeline-service:
enabled: falseSelective Deployment
During development or troubleshooting, you can deploy a subset of services:
# values-minimal.yaml - Deploy only core services
ai-service:
enabled: true
query-engine:
enabled: true
catalog-service:
enabled: true
semantic-layer:
enabled: true
# Disable non-essential services
bi-service:
enabled: false
ml-service:
enabled: false
data-quality-service:
enabled: false
render-service:
enabled: false
ops-agent-service:
enabled: false
pipeline-service:
enabled: falseDeployment Workflow
Full Deployment
# Build dependencies
helm dependency build infrastructure/helm/matih-data-plane
# Deploy with environment overlay
helm upgrade --install matih-data-plane \
infrastructure/helm/matih-data-plane \
-f infrastructure/helm/matih-data-plane/values.yaml \
--namespace matih-data-plane \
--create-namespace \
--timeout 10m \
--waitRolling Updates via Image Tags
The CD pipeline updates services by setting image tags:
helm upgrade --install matih-data-plane \
infrastructure/helm/matih-data-plane \
-f infrastructure/helm/matih-data-plane/values.yaml \
--namespace matih-data-plane \
--set ai-service.image.tag=1.0.0-abc1234 \
--set query-engine.image.tag=1.0.0-def5678 \
--set catalog-service.image.tag=1.0.0-ghi9012 \
--timeout 10m \
--waitRollback
# View release history
helm history matih-data-plane --namespace matih-data-plane
# Rollback to previous revision
helm rollback matih-data-plane 3 --namespace matih-data-plane --timeout 5mSubchart Value Propagation
Values in the umbrella chart propagate to subcharts using the subchart name as a key prefix:
# Umbrella values.yaml
# Global values (available to all subcharts via .Values.global)
global:
environment: production
imageRegistry: matihlabsacr.azurecr.io
# Subchart-specific values (passed to ai-service subchart)
ai-service:
enabled: true
replicaCount: 2
image:
registry: matihlabsacr.azurecr.io
repository: matih/ai-service
tag: "1.0.0"
resources:
requests:
cpu: 500m
memory: 1Gi
# Another subchart
query-engine:
enabled: true
replicaCount: 3
image:
registry: matihlabsacr.azurecr.io
repository: matih/query-engine
tag: "1.0.0"Inside the ai-service subchart templates, these values are accessed normally:
# The subchart sees .Values.replicaCount = 2
# The subchart sees .Values.image.tag = "1.0.0"
# The subchart sees .Values.global.environment = "production"
replicas: {{ .Values.replicaCount }}Umbrella Chart vs Individual Charts
MATIH supports both deployment modes:
| Aspect | Umbrella Chart | Individual Charts |
|---|---|---|
| Deployment unit | All services in one release | One service per release |
| Rollback granularity | All services roll back together | Per-service rollback |
| Deployment speed | Slower (all services) | Faster (single service) |
| Use case | Initial deployment, full upgrades | Hotfixes, single-service updates |
| CD pipeline stage | services stage | service-build-deploy.sh |
| Value management | Centralized in umbrella | Per-chart values |
In practice, MATIH uses umbrella charts for initial deployment and coordinated releases, while individual charts are used for targeted service updates via scripts/tools/service-build-deploy.sh.
Troubleshooting
Common Umbrella Chart Issues
| Issue | Cause | Resolution |
|---|---|---|
Error: chart requires kubeVersion | Subchart version mismatch | Run helm dependency update |
| Subchart not deploying | enabled: false in values | Check <subchart>.enabled value |
| Values not reaching subchart | Wrong key nesting | Values must be under <subchart-name>: key |
cannot load Chart.lock | Stale lock file | Delete Chart.lock and run helm dependency build |
| Subchart resource conflicts | Duplicate resource names | Check fullnameOverride in subchart values |
| Old subchart still deploying | Stale .tgz in charts/ | Delete charts/ directory and rebuild |
Next Steps
- Next: Data Infrastructure
- Previous: Helm Chart Structure