✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes Helm Chart Structure

Kubernetes Helm Chart Structure organizes application deployment in Kubernetes with templates, configs, and dependencies for scalable container orchestration.

Kubernetes Helm Chart Structure is the specific file and directory layout Helm requires and recognizes within a chart, covering the full Chart.yaml metadata schema, the special-purpose directories (crds/, templates/tests/, charts/), and the auxiliary files (values.schema.json, NOTES.txt, .helmignore) that give a chart validation, post-install messaging, and packaging exclusion behavior beyond the core templates.


Chart.yaml Metadata

The apiVersion v2 Schema

apiVersion: v2
name: mychart
description: A Helm chart for my application
type: application
version: 1.2.0
appVersion: "2.0.1"
kubeVersion: ">=1.25.0-0"
keywords:
  - web
  - api
maintainers:
  - name: Platform Team
    email: platform@example.com

apiVersion: v2 (as opposed to the legacy v1) is required for a chart to declare dependencies inline via the dependencies field rather than a separate requirements.yaml, and type: application versus type: library distinguishes a normally installable chart from a library chart that provides only reusable template helpers and produces no resources of its own when installed directly.

version appVersion

Dependencies Declaration

dependencies:
  - name: postgresql
    version: "12.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled

The condition field ties a dependency's inclusion to a boolean value path in the parent chart's own values, letting a subchart be toggled on or off per installation without removing the dependency declaration itself.


Special-Purpose Directories

The crds Directory

mychart/
  crds/
    postgrescluster-crd.yaml

Manifests placed in crds/ are installed once, on the first helm install, and are never templated (no {{ }} substitution occurs inside them) nor updated by subsequent helm upgrade calls, reflecting Helm's deliberate policy that CRD lifecycle management is too consequential (given that deleting a CRD deletes every instance cluster-wide) to be handled implicitly by a chart upgrade.

helm upgrade my-app ./mychart
# CRDs in crds/ are NOT updated by this command

templates/tests for helm test

# templates/tests/connection-test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ .Release.Name }}-test-connection"
  annotations:
    "helm.sh/hook": test
spec:
  containers:
    - name: wget
      image: busybox
      command: ["wget", "{{ .Release.Name }}-web:80"]
  restartPolicy: Never
helm test my-app

A Pod manifest annotated helm.sh/hook: test runs on demand via helm test, providing a chart-defined smoke test that verifies a release is actually functioning correctly post-install, distinct from the pre/post-install/upgrade hooks that run automatically as part of the install or upgrade action itself.

charts Directory for Vendored Dependencies

mychart/
  charts/
    postgresql-12.1.0.tgz

helm dependency update downloads each declared dependency and vendors it as a .tgz archive directly inside charts/, making the parent chart fully self-contained and installable without requiring network access to the dependency's repository at install time.


Values Schema Validation

values.schema.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1
    }
  },
  "required": ["replicaCount"]
}

A values.schema.json file, if present, is validated against the effective values (defaults merged with any user-supplied overrides) before templates are ever rendered, catching type errors and missing required fields with a clear validation message rather than allowing an invalid value to silently propagate into rendered YAML that might fail only much later, or in a confusing way, at kubectl apply time.

helm install my-app ./mychart --set replicaCount=notanumber
# Error: values don't meet the specifications of the schema(s)

Post-Install Messaging

NOTES.txt

{{- if .Values.ingress.enabled }}
Application is available at: https://{{ .Values.ingress.host }}
{{- else }}
Run: kubectl port-forward svc/{{ .Release.Name }}-web 8080:80
{{- end }}

templates/NOTES.txt, itself templated exactly like any other file in templates/, is rendered and printed to the user's terminal immediately after a successful install or upgrade, giving chart authors a place to surface contextual, conditional instructions specific to the values actually used for that particular installation.


Packaging Exclusions

.helmignore

.git/
*.md
tests/

.helmignore, following the same pattern as .gitignore, excludes matching files and directories from the packaged chart archive produced by helm package, keeping development-only files (documentation source, local test fixtures) out of the distributed artifact.


Relationship to the Helm Package Model and Composition

This file structure is the concrete filesystem realization of the template-values-render-release abstraction described under the Helm package model: Chart.yaml and values.schema.json govern what a chart declares and validates about itself, templates/ (including its tests/ subdirectory) and crds/ govern what gets installed and how, and charts/ is the mechanism that makes Helm's broader chart composition and dependency management, covered separately, possible by physically bundling subcharts inside a parent chart's own directory tree.

mychart/ Chart.yaml values.yaml templates/ crds/ charts/