woodpecker/docs/versioned_docs/version-2.6/30-administration/22-backends/40-kubernetes.md
2024-06-13 19:31:54 +02:00

10 KiB

toc_max_heading_level
2

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 order to pull private container images defined in your pipeline YAML you must provide registry credentials in Kubernetes Secret. As the Secret is Agent-wide, it has to be placed in namespace defined by WOODPECKER_BACKEND_K8S_NAMESPACE. Besides, you need to provide the Secret name to Agent 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.

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: p3.8xlarge
        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. Assuming a PVC named woodpecker-cache exists, it can be referenced as follows in a step:

steps:
  - name: "Restore Cache"
    image: meltwater/drone-cache
    volumes:
      - woodpecker-cache:/woodpecker/src/cache
    settings:
      mount:
        - "woodpecker-cache"
    [...]

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 container's syscalls 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

:::note AppArmor syntax follows KEP-24. :::

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 fonfiguration 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.