tion charts via dependencies.
Implementation:
Create a library chart with type: library in Chart.yaml. This prevents accidental installation of the chart as a release.
# charts/common/Chart.yaml
apiVersion: v2
name: common
description: A Helm library chart for common Kubernetes resources
type: library
version: 1.2.0
appVersion: "1.0.0"
Define standardized helpers in templates/_helpers.tpl. These helpers enforce naming conventions, labels, and annotations.
{{/* common/templates/_helpers.tpl */}}
{{- define "common.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- define "common.labels" -}}
app.kubernetes.io/name: {{ include "common.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- with .Values.commonLabels }}
{{ toYaml . }}
{{- end }}
{{- end -}}
{{- define "common.selectorLabels" -}}
app.kubernetes.io/name: {{ include "common.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
2. Schema Validation with JSON Schema
Eliminate configuration drift and runtime errors by enforcing values.schema.json. This file validates user inputs against a strict contract before rendering.
Implementation:
Add values.schema.json to the root of the chart. Use JSON Schema Draft 07 for broad compatibility.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1,
"maximum": 10,
"description": "Number of replicas. Must be between 1 and 10."
},
"image": {
"type": "object",
"properties": {
"repository": { "type": "string" },
"tag": { "type": "string" },
"pullPolicy": {
"type": "string",
"enum": ["Always", "IfNotPresent", "Never"]
}
},
"required": ["repository", "tag"]
},
"service": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["ClusterIP", "NodePort", "LoadBalancer"]
},
"port": { "type": "integer", "minimum": 80, "maximum": 65535 }
},
"required": ["type", "port"]
}
},
"required": ["replicaCount", "image", "service"]
}
3. Composable Application Charts
Application charts should be thin wrappers that import the library chart and define application-specific values.
Implementation:
Reference the library in Chart.yaml dependencies.
# charts/my-service/Chart.yaml
apiVersion: v2
name: my-service
version: 0.1.0
dependencies:
- name: common
version: ">=1.0.0 <2.0.0"
repository: "file://../common"
Use the library helpers in templates.
# charts/my-service/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "common.name" . }}
labels: {{- include "common.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels: {{- include "common.selectorLabels" . | nindent 6 }}
template:
metadata:
labels: {{- include "common.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
4. Testing Strategy
Adopt helm-unittest for unit testing chart logic and chart-testing (CT) for linting and installation validation.
Unit Test Example:
# tests/deployment_test.yaml
suite: deployment
templates:
- deployment.yaml
tests:
- it: should set correct labels
set:
replicaCount: 3
asserts:
- isKind:
of: Deployment
- equal:
path: spec.replicas
value: 3
- matchRegex:
path: metadata.labels["app.kubernetes.io/name"]
pattern: "^my-service$"
Architecture Decisions
- Library vs. Subchart for Core Logic: Library charts are preferred for shared logic (labels, helpers) because they do not create a separate release context. This simplifies debugging and ensures all resources belong to the parent release. Subcharts are reserved for distinct components (e.g., PostgreSQL, Redis) that may have independent lifecycles.
- Schema Enforcement: JSON Schema is mandatory. It shifts error detection to the earliest possible point (CI/CD linting) rather than during
helm install.
- Dependency Pinning: Dependencies should use semver ranges (e.g.,
>=1.0.0 <2.0.0) to allow patch/minor updates while preventing breaking changes. Pinning to exact versions hinders security updates; using * introduces instability.
Pitfall Guide
-
Hardcoding Values in Templates:
- Mistake: Embedding image tags, resource limits, or domain names directly in YAML templates.
- Impact: Renders charts non-reusable. Requires forking or editing templates for different environments.
- Fix: Externalize all variable data to
values.yaml and validate via schema.
-
Ignoring values.schema.json:
- Mistake: Relying on documentation for value formats.
- Impact: Typos in values (e.g., string instead of integer) cause silent failures or malformed resources.
- Fix: Implement schema validation in CI pipelines using
helm lint --strict.
-
The "God Chart" Anti-Pattern:
- Mistake: Creating a single chart that deploys the entire application stack, including databases, caches, and sidecars.
- Impact: Upgrades become risky; scaling components independently is impossible; chart complexity explodes.
- Fix: Decompose into focused charts. Use subcharts for dependencies and library charts for shared patterns.
-
Breaking Changes in Minor Versions:
- Mistake: Changing the structure of
values.yaml or removing helpers in a minor chart version bump.
- Impact: Downstream consumers experience immediate breakage.
- Fix: Adhere strictly to SemVer. Major version bumps are required for breaking changes. Use deprecation warnings in templates before removal.
-
Template Logic Bloat:
- Mistake: Writing complex conditional logic inside templates to handle every edge case.
- Impact: Charts become unreadable and difficult to test.
- Fix: Simplify templates. Move complex logic to helper functions in the library chart. If logic is too complex, consider whether Helm is the right tool or if the chart needs decomposition.
-
Missing helm test Hooks:
- Mistake: Deploying without health checks or connectivity tests.
- Impact: False positives on deployment success; issues detected only by end-users.
- Fix: Implement
helm test pods that verify service availability and configuration correctness immediately after installation.
-
Assuming Cluster Context:
- Mistake: Charts that fail if CRDs are missing or if RBAC is not pre-configured.
- Impact: Poor user experience; charts fail in restricted environments.
- Fix: Document prerequisites clearly. Use
crd-install hooks for CRDs if appropriate, or recommend separate CRD management. Ensure RBAC templates are optional or configurable.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| New Microservice | Use Composable Library Chart | Ensures consistency with platform standards; reduces boilerplate by 60%. | Low initial setup; high long-term savings. |
| Legacy Chart Migration | Incremental Refactor to Library | Extract helpers and labels first; validate with schema; decompose over time. | Medium effort; reduces incident rate significantly. |
| Multi-Tenant SaaS | Library Chart + Namespace Overrides | Library enforces isolation patterns; values control tenant-specific config. | Low overhead; critical for security/compliance. |
| Platform Team vs. App Team | Platform owns Library; Apps own Wrappers | Decouples responsibilities; platform manages standards, apps manage logic. | Optimizes team velocity; reduces friction. |
| Complex Stateful App | Subchart for State + Library for App | Isolates state management; library handles app deployment patterns. | Higher complexity; necessary for reliability. |
Configuration Template
Skeleton Structure:
charts/
βββ common/ # Library Chart
β βββ Chart.yaml # type: library
β βββ values.yaml
β βββ values.schema.json
β βββ templates/
β βββ _helpers.tpl # Shared helpers
βββ my-app/ # Application Chart
β βββ Chart.yaml # dependencies: [common]
β βββ values.yaml
β βββ values.schema.json
β βββ templates/
β β βββ deployment.yaml
β β βββ service.yaml
β β βββ tests/
β β βββ test-connection.yaml
β βββ tests/
β βββ deployment_test.yaml
charts/common/Chart.yaml:
apiVersion: v2
name: common
description: Shared Helm library for Kubernetes resources
type: library
version: 1.0.0
appVersion: "1.0.0"
charts/my-app/Chart.yaml:
apiVersion: v2
name: my-app
version: 0.1.0
dependencies:
- name: common
version: ">=1.0.0 <2.0.0"
repository: "file://../common"
Quick Start Guide
- Create Library Chart: Run
helm create common and modify Chart.yaml to set type: library. Move generic helpers to common/templates/_helpers.tpl.
- Define Schema: Create
common/values.schema.json to define shared value structures (labels, annotations, image config).
- Create App Chart: Run
helm create my-app. Add common as a dependency in my-app/Chart.yaml.
- Refactor Templates: Replace hardcoded labels and selectors in
my-app/templates with {{ include "common.labels" . }}.
- Validate and Test: Run
helm lint my-app to verify schema and syntax. Add helm-unittest files and run helm unittest my-app. Commit changes.
Codcompass 2.0 ensures technical precision and actionable insights. This article provides the architectural foundation for scalable Helm chart management. Apply these patterns to reduce operational debt and increase deployment reliability.