Kubernetes backend
The Kubernetes backend executes steps inside standalone Pods. A temporary PVC is created for the lifetime of the pipeline to transfer files between steps.
Images from private registriesโ
In addition to registries specified in the UI, you may provide registry credentials in Kubernetes Secrets to pull private container images defined in your pipeline YAML.
Place these Secrets in namespace defined by WOODPECKER_BACKEND_K8S_NAMESPACE
and provide the Secret names to Agents via WOODPECKER_BACKEND_K8S_PULL_SECRET_NAMES
.
Job specific configurationโ
Resourcesโ
The Kubernetes backend also allows for specifying requests and limits on a per-step basic, most commonly for CPU and memory.
We recommend to add a resources
definition to all steps to ensure efficient scheduling.
Here is an example definition with an arbitrary resources
definition below the backend_options
section:
steps:
- name: 'My kubernetes step'
image: alpine
commands:
- echo "Hello world"
backend_options:
kubernetes:
resources:
requests:
memory: 200Mi
cpu: 100m
limits:
memory: 400Mi
cpu: 1000m
You can use Limit Ranges if you want to set the limits by per-namespace basis.
Runtime classโ
runtimeClassName
specifies the name of the RuntimeClass which will be used to run this Pod. If no runtimeClassName
is specified, the default RuntimeHandler will be used.
See the Kubernetes documentation for more information on specifying runtime classes.
Service accountโ
serviceAccountName
specifies the name of the ServiceAccount which the Pod will mount. This service account must be created externally.
See the Kubernetes documentation for more information on using service accounts.
steps:
- name: 'My kubernetes step'
image: alpine
commands:
- echo "Hello world"
backend_options:
kubernetes:
# Use the service account `default` in the current namespace.
# This usually the same as wherever woodpecker is deployed.
serviceAccountName: default
To give steps access to the Kubernetes API via service account, take a look at RBAC Authorization
Node selectorโ
nodeSelector
specifies the labels which are used to select the node on which the job will be executed.
Labels defined here will be appended to a list which already contains "kubernetes.io/arch"
.
By default "kubernetes.io/arch"
is inferred from the agents' platform. One can override it by setting that label in the nodeSelector
section of the backend_options
.
Without a manual overwrite, builds will be randomly assigned to the runners and inherit their respective architectures.
To overwrite this, one needs to set the label in the nodeSelector
section of the backend_options
.
A practical example for this is when running a matrix-build and delegating specific elements of the matrix to run on a specific architecture.
In this case, one must define an arbitrary key in the matrix section of the respective matrix element:
matrix:
include:
- NAME: runner1
ARCH: arm64
And then overwrite the nodeSelector
in the backend_options
section of the step(s) using the name of the respective env var:
[...]
backend_options:
kubernetes:
nodeSelector:
kubernetes.io/arch: "${ARCH}"
You can use WOODPECKER_BACKEND_K8S_POD_NODE_SELECTOR if you want to set the node selector per Agent or PodNodeSelector admission controller if you want to set the node selector by per-namespace basis.
Tolerationsโ
When you use nodeSelector
and the node pool is configured with Taints, you need to specify the Tolerations. Tolerations allow the scheduler to schedule Pods with matching taints.
See the Kubernetes documentation for more information on using tolerations.
Example pipeline configuration:
steps:
- name: build
image: golang
commands:
- go get
- go build
- go test
backend_options:
kubernetes:
serviceAccountName: 'my-service-account'
resources:
requests:
memory: 128Mi
cpu: 1000m
limits:
memory: 256Mi
nodeSelector:
beta.kubernetes.io/instance-type: Standard_D2_v3
tolerations:
- key: 'key1'
operator: 'Equal'
value: 'value1'
effect: 'NoSchedule'
tolerationSeconds: 3600
Volumesโ
To mount volumes a PersistentVolume (PV) and PersistentVolumeClaim (PVC) are needed on the cluster which can be referenced in steps via the volumes
option.
Persistent volumes must be created manually. Use the Kubernetes Persistent Volumes documentation as a reference.
If your PVC is not highly available or NFS-based, you may also need to integrate affinity settings to ensure that your steps are executed on the correct node.
NOTE: If you plan to use this volume in more than one workflow concurrently, make sure you have configured the PVC in RWX
mode. Keep in mind that this feature must be supported by the used CSI driver:
accessModes:
- ReadWriteMany
Assuming a PVC named woodpecker-cache
exists, it can be referenced as follows in a plugin step:
steps:
- name: "Restore Cache"
image: meltwater/drone-cache
volumes:
- woodpecker-cache:/woodpecker/src/cache
settings:
mount:
- "woodpecker-cache"
[...]
Or as follows when using a normal image:
steps:
- name: "Edit cache"
image: alpine:latest
volumes:
- woodpecker-cache:/woodpecker/src/cache
commands:
- echo "Hello World" > /woodpecker/src/cache/output.txt
[...]
Security contextโ
Use the following configuration to set the Security Context for the Pod/container running a given pipeline step:
steps:
- name: test
image: alpine
commands:
- echo Hello world
backend_options:
kubernetes:
securityContext:
runAsUser: 999
runAsGroup: 999
privileged: true
[...]
Note that the backend_options.kubernetes.securityContext
object allows you to set both Pod and container level security context options in one object.
By default, the properties will be set at the Pod level. Properties that are only supported on the container level will be set there instead. So, the
configuration shown above will result in something like the following Pod spec:
kind: Pod
spec:
securityContext:
runAsUser: 999
runAsGroup: 999
containers:
- name: wp-01hcd83q7be5ymh89k5accn3k6-0-step-0
image: alpine
securityContext:
privileged: true
[...]
You can also restrict a syscalls of containers with seccomp profile.
backend_options:
kubernetes:
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/audit.json
or restrict a container's access to resources by specifying AppArmor profile
backend_options:
kubernetes:
securityContext:
apparmorProfile:
type: Localhost
localhostProfile: k8s-apparmor-example-deny-write
The feature requires Kubernetes v1.30 or above.
Annotations and labelsโ
You can specify arbitrary annotations and labels to be set on the Pod definition for a given workflow step using the following configuration:
backend_options:
kubernetes:
annotations:
workflow-group: alpha
io.kubernetes.cri-o.Devices: /dev/fuse
labels:
environment: ci
app.kubernetes.io/name: builder
In order to enable this configuration you need to set the appropriate environment variables to true
on the woodpecker agent:
WOODPECKER_BACKEND_K8S_POD_ANNOTATIONS_ALLOW_FROM_STEP and/or WOODPECKER_BACKEND_K8S_POD_LABELS_ALLOW_FROM_STEP.
Tips and tricksโ
CRI-Oโ
CRI-O users currently need to configure the workspace for all workflows in order for them to run correctly. Add the following at the beginning of your configuration:
workspace:
base: '/woodpecker'
path: '/'
See this issue for more details.
KUBERNETES_SERVICE_HOST
environment variableโ
Like the below env vars used for configuration, this can be set in the environment for configuration of the agent. It configures the address of the Kubernetes API server to connect to.
If running the agent within Kubernetes, this will already be set and you don't have to add it manually.
Configurationโ
These env vars can be set in the env:
sections of the agent.
WOODPECKER_BACKEND_K8S_NAMESPACE
โ
Default:
woodpecker
The namespace to create worker Pods in.
WOODPECKER_BACKEND_K8S_VOLUME_SIZE
โ
Default:
10G
The volume size of the pipeline volume.
WOODPECKER_BACKEND_K8S_STORAGE_CLASS
โ
Default: empty
The storage class to use for the pipeline volume.
WOODPECKER_BACKEND_K8S_STORAGE_RWX
โ
Default:
true
Determines if RWX
should be used for the pipeline volume's access mode. If false, RWO
is used instead.
WOODPECKER_BACKEND_K8S_POD_LABELS
โ
Default: empty
Additional labels to apply to worker Pods. Must be a YAML object, e.g. {"example.com/test-label":"test-value"}
.
WOODPECKER_BACKEND_K8S_POD_LABELS_ALLOW_FROM_STEP
โ
Default:
false
Determines if additional Pod labels can be defined from a step's backend options.
WOODPECKER_BACKEND_K8S_POD_ANNOTATIONS
โ
Default: empty
Additional annotations to apply to worker Pods. Must be a YAML object, e.g. {"example.com/test-annotation":"test-value"}
.
WOODPECKER_BACKEND_K8S_POD_ANNOTATIONS_ALLOW_FROM_STEP
โ
Default:
false
Determines if Pod annotations can be defined from a step's backend options.
WOODPECKER_BACKEND_K8S_POD_NODE_SELECTOR
โ
Default: empty
Additional node selector to apply to worker pods. Must be a YAML object, e.g. {"topology.kubernetes.io/region":"eu-central-1"}
.
WOODPECKER_BACKEND_K8S_SECCTX_NONROOT
โ
Default:
false
Determines if containers must be required to run as non-root users.
WOODPECKER_BACKEND_K8S_PULL_SECRET_NAMES
โ
Default: empty
Secret names to pull images from private repositories. See, how to Pull an Image from a Private Registry.