# Helm Chart Reference & Advanced Patterns This document contains detailed explanations and advanced patterns for Helm chart development. ## 🏠 Resource Ownership **Every Kubernetes resource must have exactly one owner. Never duplicate.** - If a chart creates a resource (e.g. Traefik creates IngressClass), don't create it elsewhere - Before adding a template for a resource, verify no other chart/subchart already manages it ``` ❌ Wrong: subchart A creates IngressClass AND subchart B creates IngressClass βœ… Right: one chart owns IngressClass, others do not touch it ``` ## 🧹 values.yaml β€” Keep It Short and Identical Across Installations **values.yaml serves two purposes:** 1. **Static baseline** β€” identical for every installation. 2. **Umbrella glue** β€” wires subcharts into a coherent whole. Shared values like `global.domain` are defined once here. Installation-specific values go exclusively in `values..yaml` in the IaC/deployment repo. If a value varies between installations, it does not belong in the chart's `values.yaml`. **Forbidden in values.yaml:** - Empty string placeholders (`key: ""`) - Defaults for values that are hardcoded in templates - Installation-specific data of any kind (hostnames, credentials) | File | Location | Content | |---|---|---| | `values.yaml` | chart repo | minimal static baseline | | `values..yaml` | IaC repo | everything that varies per installation | ## βœ… required vs defaults When a template needs a value: **1. Sensible default** β€” hardcode it directly in the template. Do not add it to values.yaml. **2. Must come from deployer** β€” use `required`. Do not put any entry in values.yaml. `| default` in templates is forbidden. ```yaml # βœ… Sensible default replicas: 1 # βœ… Must vary per installation host: {{ required "global.domain is required" .Values.global.domain }} # ❌ Forbidden β€” default in values.yaml adds noise replicas: {{ .Values.replicas }} # values.yaml: replicas: 1 # ❌ Forbidden β€” hides missing config host: {{ .Values.global.domain | default "" }} ``` ## πŸ“„ Configuration Files over values.yaml **Prefer `files/` + ConfigMap over defining configuration in values.yaml.** 1. Put the config file in `files/` 2. Create a ConfigMap that reads it with `.AsConfig` + `tpl` 3. Use `{{ .Values.global.xxx }}` expressions inside the config file ```yaml # templates/configmap.yaml data: {{ (tpl (.Files.Glob "files/*").AsConfig . ) | nindent 2 }} ``` **Always use `.AsConfig` when the file contains template expressions or special characters.** ## πŸŽ‚ Umbrella Chart Pattern The standard structure is an umbrella chart that integrates multiple component charts. ``` my-umbrella/ β”œβ”€β”€ Chart.yaml ← declares component charts as dependencies β”œβ”€β”€ values.yaml ← static baseline: shared across all installations β”œβ”€β”€ templates/ ← only cross-cutting resources that no subchart owns └── charts/ ← built by helm dependency update ``` ## πŸ”— Glue Configuration When a subchart cannot use Helm templates in its values (e.g. it reads `values.` directly without templating), the umbrella `values.yaml` must coordinate the literal names. Example: Tempo reading MinIO host: ```yaml minio: fullnameOverride: "minio" # Forces service name to literal "minio" tempo: storage: s3: endpoint: "http://minio:9000" # Hardcoded literal match ``` ## ⚑ KISS β€” Start Minimal **Do not add knobs, flags, or options that aren’t needed right now.** - Start with hardcoded values in the template. - When parameterization is requested, expose it as `required` to `values..yaml`, not `values.yaml`. ## πŸ§ͺ Testing Templates Always test with at least two different release names and namespaces to verify independence. ```bash helm template app1 . --namespace default helm template app2 . --namespace production ``` ## πŸ› Interactive Infrastructure Debugging **When debugging live systems, act as an active operator:** - βœ… **Request network access:** Ask for `kubectl port-forward` if needed. - βœ… **Use read-only terminal tools:** Use `curl` to test endpoints, or `kubectl get/describe/logs` directly in the terminal. - ❌ **Never modify via terminal:** Do not use the terminal to edit files or apply changes.