Kubernetes PodSpec
Using the kubernetes
plugin allows you to specify a PodSpec
Kubernetes API resource that will be used in a Kubernetes Job
.
Kubernetes PodSpec generation
The Agent Stack for Kubernetes controller allows you to define some or all of the Kubernetes PodSpec
from the following locations:
- Controller configuration:
pod-spec-patch
. - Buildkite job, using the
kubernetes
plugin:podSpec
,podSpecPatch
.
With multiple PodSpec
inputs provided, here is how the Agent Stack for Kubernetes controller generates a Kubernetes PodSpec
:
-
Create a simple
PodSpec
containing a single container with theImage
defined in the controller's configuration and the value of the Buildkite job's command (BUILDKITE_COMMAND
).If the
kubernetes
plugin is present in the Buildkite job's plugins and contains apodSpec
, use this as the startingPodSpec
instead. Apply the
/workspace
Volume.Apply any
extra-volume-mounts
defined by thekubernetes
plugin.Modify any
containers
defined by thekubernetes
plugin, overriding thecommand
andargs
.Add the
agent
container to thePodSpec
.Add the
checkout
container to thePodSpec
(ifskip.checkout
is set tofalse
).Add
init
containers for theimagecheck-#
containers, based on the number of unique images defined in thePodSpec
.Apply
pod-spec-patch
from the controller's configuration, using a strategic merge patch in the controller.Apply
podSpecPatch
from thekubernetes
plugin, using a strategic merge patch in the controller.Ensure the a
checkout
container in not present after applying patching viapod-spec-patch
,podSpecPatch
(ifskip.checkout
is set totrue
).Remove any duplicate
VolumeMounts
present inPodSpec
after patching.Create a Kubernetes Job with the final
PodSpec
.
PodSpec command and interpretation of arguments
In a podSpec
, command
must be a list of strings, since it is defined by Kubernetes. However, the Buildkite Agent Stack for Kubernetes controller runs the Buildkite Agent instead of the container's default entrypoint.
To run a command, the controller must re-interpret command
into input for the Buildkite Agent. By default, the controller treats command
as a sequence of multiple commands, similar to steps and commands in a pipeline.yaml
file which is different to the interpretation of command
(as an entrypoint vector run without a shell as a single command) in Kubernetes.
This interposer behavior can be changed using commandParams/interposer
, which can have one of the following values:
-
buildkite
is the default, in which the Agent Stack for Kubernetes controller treatscommand
as a sequence of multiple commands, andargs
as extra arguments added to the end of the last command, which are then typically interpreted by the shell. -
vector
emulates the Kubernetes' interpretation in whichcommand
andargs
specify components of a single command intended to be run directly. -
legacy
is the behavior of the Agent Stack for Kubernetes controller version 0.14.0 and earlier, wherecommand
andargs
are joined directly into a single command with spaces.
An example using buildkite
interposer behavior:
steps:
- label: Hello World!
agents:
queue: kubernetes
plugins:
- kubernetes:
commandParams:
interposer: buildkite # This is the default, and can be omitted
podSpec:
containers:
- image: alpine:latest
command:
- set -euo pipefail
- |- # <-- YAML block scalars work too
echo Hello World! > hello.txt
cat hello.txt | buildkite-agent annotate
If you have a multi-line command
, specifying the args
could lead to confusion. Therefore, it is recommended to just use command
.
An example using vector
interposer behavior:
steps:
- label: Hello World!
agents:
queue: kubernetes
plugins:
- kubernetes:
commandParams:
interposer: vector
podSpec:
containers:
- image: alpine:latest
command: ['sh']
args:
- '-c'
- |-
set -eu
echo Hello World! > hello.txt
cat hello.txt | buildkite-agent annotate
Custom images
Almost any container image may be used, but the image must have a POSIX shell available to be executed at /bin/sh
.
You can specify a different image to use for a step in a step level podSpecPatch
. Previously this could be done with a step level podSpec
.
# pipelines.yaml
agents:
queue: kubernetes
steps:
- name: Hello World!
commands:
- echo -n Hello!
- echo " World!"
plugins:
- kubernetes:
podSpecPatch:
containers:
- name: container-0
image: alpine:latest
- name: Hello World from alpine!
commands:
- echo -n Hello
- echo " from alpine!"
plugins:
- kubernetes:
podSpecPatch:
containers:
- name: container-0 # <-- For the time being, specify this exactly as `container-0`.
image: alpine:latest # Currently under experimentation to make this more ergonomic.