values.yaml is the chart's interface: every key is a setting users may change, so keep it short, commented and grouped by component. BookNest's defaults reproduce the production manifests:
api:
image: { repository: localhost:33500/booknest-api, tag: "1.4" }
replicas: 2 # used only when autoscaling is off
autoscaling: { enabled: false, minReplicas: 2, maxReplicas: 6, cpu: 70 }
resources: { requests: { cpu: 50m, memory: 64Mi }, limits: { memory: 256Mi } }
web:
image: { repository: localhost:33500/booknest-web, tag: "1.3" }
replicas: 2
db:
host: "" # empty: the bundled postgres subchart, <release>-postgres
secret: "" # empty: <release>-db, generated on first install
name: booknest
user: booknest
migrations:
image: localhost:33500/postgres:18
postgres: # values for the postgres subchart
enabled: true
storageClass: booknest-data
size: 1GiAn environment supplies only its differences, in a file passed with -f or single keys with --set. Later sources win, merging key by key rather than replacing whole maps:
api:
image: { tag: "1.3" }
autoscaling: { enabled: true, minReplicas: 1, maxReplicas: 2 }
web: { replicas: 1 }helm template demo helm/booknest -f helm/staging.yaml --set web.replicas=3 \
| yq -N '[.kind, .metadata.name, .spec.replicas, .spec.minReplicas, .spec.maxReplicas,
.spec.template.spec.containers[0].image] | map(select(. != null) | to_string)
| join(" ")' \
| grep -E '^(Deployment|HorizontalPodAutoscaler)'Output
Deployment demo-api localhost:33500/booknest-api:1.3 Deployment demo-web 3 localhost:33500/booknest-web:1.3 HorizontalPodAutoscaler demo-api 1 2
The API took staging's tag and an autoscaler; the front end took --set's 3 over staging's 1. Precedence runs, lowest first: the chart's values.yaml, a parent chart's values for a subchart, each -f file, then --set. Keep lasting settings in files under version control (Helm Upgrades shows why), and add a values.schema.json to have Helm 29,435 validate every value.