Service workloads¶
Overview¶
Workloads describe the Kubernetes resources that Wodby manages for a service.
Use workloads to define:
- which Kubernetes controller Wodby should target
- which containers exist inside that controller
- which workload is considered primary
- where Wodby should inject workload- and container-level Helm values
For non-external services, workloads are normally required unless they are inherited from from.
External services do not define workloads.
Why workloads exist¶
A service is no longer treated as a single Deployment with a single container.
Charts can expose multiple resources, for example:
- a web workload and a daemon workload
- a Deployment plus a StatefulSet
- one workload with more than one container
Wodby uses workload definitions to resolve the correct target for:
- logs and shell
- endpoints
- cron jobs
- backups
- imports
- actions
- database actions
- container-scoped env vars and resources
Template¶
Workloads are defined under the workloads section in a service template.
Single-workload example¶
workloads:
- name: main
selector:
matchLabels:
app.kubernetes.io/instance: "{{helm.release}}"
kind: deployment
primary: true
helm:
labels: commonLabels
annotations: commonAnnotations
volumes: extraVolumes
sidecars: extraSidecars
containers:
- name: php
image: wodby/php
build: true
helm:
resources: resources
env: extraEnvVars
mounts: extraVolumeMounts
image:
repository: image.repository
tag: image.tag
registry: image.registry
pullPolicy: image.pullPolicy
Multi-workload example¶
workloads:
- name: webserver
selector:
matchLabels:
app.kubernetes.io/instance: "{{helm.release}}"
component: dagster-webserver
kind: deployment
primary: true
containers:
- name: dagster
image: dagster/dagster-celery-k8s
- name: daemon
selector:
matchLabels:
app.kubernetes.io/instance: "{{helm.release}}"
component: dagster-daemon
kind: deployment
containers:
- name: dagster
image: dagster/dagster-celery-k8s
Workload fields¶
Each workloads[] item supports:
name: required stable workload name used by stack, app, and GraphQL overrides.selector: required Kubernetes selector used by Wodby to find the rendered workload resource.kind: required workload kind. Allowed values:deployment,statefulset,daemonset.primary: optional boolean. Marks the default workload for runtime operations.helm: optional workload-level Helm mappings.containers: required list of containers for this workload.
Workload names¶
workloads[].name is a Wodby identifier, not the rendered Kubernetes workload resource name. It must still follow the general Kubernetes name rules, because Wodby also uses it in generated Kubernetes configuration.
Use it consistently in:
endpoints[].workloadcron[].workloadbackups[].workloadimports[].workloadactions[].workloaddatabase.actions[].workload- stack overrides
- app-level mutations that target a specific workload/container
Keep workload names stable once a service is published. Renaming or removing workloads can break existing stack and app data.
Selectors¶
selector.matchLabels must point to exactly one rendered workload of the declared kind.
Example:
selector:
matchLabels:
app.kubernetes.io/instance: "{{helm.release}}"
app.kubernetes.io/name: php
Selectors are preferred over resource names because they survive chart naming differences and helper logic.
For Wodby charts, use stable workload labels whenever possible. For third-party charts, use the labels that uniquely identify each workload in the rendered chart.
Resolvable selectors are also required for force deployments. During a forced app-service upgrade, Wodby uses these selectors to find each rendered Deployment, StatefulSet, or DaemonSet and update its pod template so Kubernetes starts a new rollout. If the selector contains unresolved tokens or does not point to the rendered workload, Wodby cannot force a restart for that workload.
Primary workload¶
One workload should be treated as primary.
If a service has only one workload, Wodby uses it as primary automatically.
If a service has multiple workloads, mark one with primary: true.
When no explicit workload is selected, Wodby falls back to the primary workload for:
- shell
- logs
- endpoints
- cron jobs
- backups
- imports
- actions
- database actions
Containers¶
Every workload must define at least one container.
Each workloads[].containers[] item supports:
name: required pod container nameimage: optional runtime image referencebuild: optional boolean for build target containershostname: optional container hostnameenv: optional container-scoped env varsresources: optional container-scoped resourceshelm: optional container-level Helm mappings
Container names must match the real container names created by the chart.
Build targets¶
Buildable services mark target containers with build: true.
- At least one container must be marked when the service defines
build. - Containers must not use
build: truewhen the service has nobuildsection. - Multiple containers can be marked only when they are intended to receive the same built image.
See also: Service build.
Helm mappings¶
Workload-level Helm mappings¶
workloads[].helm supports:
labelsannotationsvolumessidecars
These are Helm value paths used when Wodby injects workload-scoped data.
Container-level Helm mappings¶
workloads[].containers[].helm supports:
resourcesenvenvKVmountsimage
These are Helm value paths used when Wodby injects container-scoped data.
Container image Helm mappings¶
workloads[].containers[].helm.image supports:
repositorytagregistrypullPolicy
Defaults:
repository:image.repositorytag:image.tagregistry:image.registrypullPolicy:image.pullPolicy
By default, Wodby splits an image like registry.example.com/team/app:1.2.3 into:
registry:registry.example.comrepository:team/apptag:1.2.3
Set registry: "" when the chart expects the full image path to stay in repository instead of splitting registry and repository into separate values.
Example:
image:
repository: dagsterWebserver.image.repository
tag: dagsterWebserver.image.tag
registry: ""
With this configuration, Wodby writes the full repository path such as registry.example.com/team/app into
dagsterWebserver.image.repository and does not inject a separate registry value.
See also: Helm.
Validation rules¶
Service import validates workloads strictly.
- Workload names must be unique.
- Workload names and container names must follow the general Kubernetes name rules.
- One workload can be primary.
- Every workload must contain at least one container.
- Container names must be unique within a workload.
- Selectors must be structurally valid.
- When the chart can be rendered during validation, each selector must resolve to exactly one rendered workload of the declared kind.
- Workload references used by endpoints, cron jobs, backups, imports, actions, and database actions must point to existing workloads.
- In inherited services, overridden workloads and containers must already exist in the base service.