Deployments
deployments renders one Deployment per key. Each key is a pod with one or more containers; a bare key produces a single container named after the key using the global image settings:
deployments:
myapp: # one container named "myapp", global image appliedFor a single-workload chart, the deployment: shorthand injects into the map under the release name so you don't have to repeat it:
deployment:
replicaCount: 2
containers:
app:
ports:
http:
containerPort: 8080See Conventions for the bare-key form and Naming for how myapp-<key> names are built.
Replicas and strategy
replicaCount sets the default for every deployment; override it per deployment. deploymentStrategy is passed through to spec.strategy:
replicaCount: 2 # default for all deployments
deployments:
api:
replicaCount: 3 # this deployment only
deploymentStrategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0Containers
Declare containers explicitly when a pod needs more than one, or to set container-level fields. Global defaults (image.*, imagePullPolicy, configure.*) cascade down, and pod-level fields like volumeMounts fall through to each container:
deployments:
web:
containers:
app:
image: myorg/app:1.4.0 # overrides the global image
ports:
http:
containerPort: 8080
command: ["/app/bin", "serve"]
args: ["--verbose"]
resources:
requests:
cpu: 100m
memory: 128MiInit and sidecar containers
initContainers and sidecarContainers are declared at the top level of your values, not inside a deployment, and both require an explicit image. Unlike the main containers, they are opt-in: every configure flag defaults to false, so they receive only what you give them. A busybox init container or a log-shipping sidecar has no reason to inherit the app's secrets and environment.
initContainers:
init-data:
image: busybox
command: ["sh", "-c", "chown -R 82:82 /data"]
configure:
persistence: true # opt in to the PVC mount for the chown
sidecarContainers:
socks-proxy:
image: socks-proxy/main:latest
env:
- name: PROXY_HOST
value: "10.1.2.3"Enable each feature a container actually needs (configure.variables, configure.secrets, configure.persistence, and so on). For one-off setup like database migrations, prefer a Job with a Helm hook over an init container, so it runs once per release rather than on every pod restart.
Health checks
healthChecks is passed through verbatim to the container, so it holds standard startupProbe, readinessProbe, and livenessProbe blocks:
deployments:
api:
containers:
api:
healthChecks:
readinessProbe:
httpGet:
port: http
path: /healthz/ready
livenessProbe:
periodSeconds: 60
httpGet:
port: http
path: /healthz/liveAutoscaling
Set autoscaling on a deployment to render a HorizontalPodAutoscaler. When it is enabled the chart omits replicas so the HPA owns the replica count. Use the shorthand targets or a full metrics list:
deployments:
api:
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80 # shorthand
targetMemoryUtilizationPercentage: 90Config, secrets, and volumes
Containers pick up the release's variables, secrets, mounted files, and PVCs automatically through the configure flags. Those inputs have their own pages: Config and Secrets.
Rolling on version change
By default the pod template carries selector labels only, so a chart or app version bump does not churn your workloads. Set rolloutOnVersionChange: true on a deployment to stamp the full labels (including helm.sh/chart and app.kubernetes.io/version) onto the pod template, which rolls the pods on every version bump:
deployments:
api:
rolloutOnVersionChange: trueChanges to variables, secrets, or mounted files always roll the pods through checksum annotations, independent of this flag. The chart writes these onto the pod template for you, one per input that is set:
template:
metadata:
annotations:
checksum/variables: d006fe122ff50434e6b8a8216f035895f5350cc04a605abfeb29b5c5125db001
checksum/secrets: 70f78f170573c54bf68c318d5f47b54903492850a1190a477cb5e3103e9cfba2They are a default annotation the chart owns; you never set them yourself.
Annotations and labels
Metadata annotations and labels come from the global annotations / labels values, with a per-deployment annotations / labels merged on top (yours win per key). The pod template has its own separate channel through podAnnotations / podLabels, since a Deployment's metadata does not propagate to its pods:
annotations: # every resource's metadata
meta.example.com/owner: platform
deployments:
api:
annotations: # this Deployment's metadata, merged over the global set
reloader.stakater.com/auto: "true"
podAnnotations: # this Deployment's pods
prometheus.io/scrape: "true"
prometheus.io/port: "8080"See Annotations and Labels for the merge order and the chart-generated keys that always win.
Disabling a deployment
Set enabled: false to keep a deployment in values but skip rendering it, which is useful for per-environment overrides:
deployments:
worker:
enabled: false # exists in values, renders nothing