Labels
The chart applies the Kubernetes recommended labels to every resource:
| Label | Source | Purpose |
|---|---|---|
app.kubernetes.io/name | nameOverride; falls back to release name when using standard directly | What is deployed: the application type |
app.kubernetes.io/instance | Helm release name | Which instance: unique per release |
app.kubernetes.io/version | version or appVersion | Application version |
app.kubernetes.io/managed-by | Helm | Always Helm |
helm.sh/chart | Chart name + version | Chart identity |
app.kubernetes.io/deployment | Deployment map key | Disambiguates selectors when multiple Deployments share a release |
These generated labels are chart-owned and cannot be overridden; user labels below never touch them. Annotations have their own page.
User labels
labels: targets the object's own metadata, podLabels: the pod template; both exist globally and per resource:
| Scope | Object metadata | Pod template |
|---|---|---|
| Global | labels | podLabels |
| Per resource | deployments.<name>.labels, same on services, ingresses, jobs, cronJobs, persistence, serviceAccount, and deployments.<name>.autoscaling (HPA) | deployments.<name>.podLabels, same on jobs and cronJobs |
labels: # on every resource's metadata
team: platform
podLabels: # on every pod template
sidecar.istio.io/inject: "true"
deployments:
app:
labels: # this Deployment only, merged on top
tier: frontendBoth channels follow the chart's merge order: global, then per-resource, then chart-generated. Two label-specific guarantees follow from the selector rules below:
- Selectors are built only from the generated selector labels and never see user input, so a
podLabelsentry overridingapp.kubernetes.io/nameis silently dropped rather than breaking the immutable selector match. - User metadata labels stay off pod templates, even with
rolloutOnVersionChangeenabled: pods carry the generated labels pluspodLabelsonly, so editing a global label does not roll every Deployment.
Setting nameOverride
nameOverride identifies what the application is. Set it once in the project's values.yaml:
nameOverride: backend # → app.kubernetes.io/name: backendIt affects both the label and the resource name suffix, which is what makes preview environments work cleanly:
| Scenario | release | nameOverride | Resource names | name label | instance label |
|---|---|---|---|---|---|
| Production | myapp | backend | myapp ¹ | backend | myapp |
| Preview branch | feat-xyz | backend | feat-xyz-backend | backend | feat-xyz |
| No override | myapp | (unset) | myapp | myapp | myapp |
¹ Deduplication: myapp-backend → myapp when release already contains nameOverride.
How this compares to the standard Helm convention
Most public charts (Bitnami, ingress-nginx, etc.) follow the same convention:
| Resource names | app.kubernetes.io/name | |
|---|---|---|
No overrides, chart standard | <release> ² | <release> ² |
No overrides, chart archivebox | <release>-archivebox | archivebox |
nameOverride: app | <release>-app ¹ | app |
fullnameOverride: app | app | app |
² When using the standard chart directly with no overrides, the chart name standard is treated as a transparent wrapper: resources are named after the release and the name label uses the release name rather than the meaningless value standard.
Preview and multi-instance deployments
Set nameOverride in the project's values.yaml and let the Helm release name (the branch slug in CI) handle uniqueness automatically:
# values.yaml: committed to the repo, set once
nameOverride: backend# CI pipeline
helm install feat-xyz hosst/standard --values values.yaml
# → Deployment: feat-xyz-backend
# → app.kubernetes.io/name: backend
# → app.kubernetes.io/instance: feat-xyzMultiple preview branches in the same namespace (preview-myapp) are automatically unique; no manual name construction needed:
| Release | Deployment name |
|---|---|
feat-xyz | feat-xyz-backend |
feat-abc | feat-abc-backend |
myapp (production) | myapp |
fullnameOverride is still available when you need a fully explicit resource name regardless of the release, but it bypasses the automatic uniqueness mechanism.
Selector immutability
app.kubernetes.io/name and app.kubernetes.io/instance are part of the Deployment's selector.matchLabels. Kubernetes enforces these as immutable after first deploy: changing them requires deleting and recreating the Deployment.
Consequences:
- Never change
nameOverrideon an existing release; usehelm uninstallfirst - Never change the release name of an existing installation; it changes
instance - For multi-deployment charts, never rename a key in the
deployments:map; it changes thedeploymentselector label