An opinionated Buildkite plugin for running pipeline steps as Kubernetes Jobs.
The plugin is based on the work of the EmabrkStudios/k8s-buildkite-plugin.
Since the step isn't actually performed by the build-agent itself, but in a separately scheduled (and isolated) container, a few things don't work as on a "normal" build-agent.
The build step container will have the buildkite-agent
binary mounted at /usr/local/bin/buildkite-agent
to allow using the agent subcommands for annotations, metadata and artifacts directly.
This behavior may be disabled by setting mount-buildkite-agent: false
in the pipeline.
Note: The user is responsible for making sure the container specified in
image
contains any external dependencies required by the otherwise statically linked buildkite-agent binary. This includes certificate authorities, and possibly git and ssh depending on how it's being used.
As the build-agent doesn't run in the same container as the actual commands, automatic upload of artifacts specified in artifact_paths
won't work.
A workaround to this is to run buildkite-agent artifact upload ...
as a command in the step itself.
The plugin requires jsonnet
, jq
, and kubectl
to be installed in the Buildkite agent (and the init) image used.
By default, the init image used is defined in this repositories Dockerfile
and published as quay.io/muhlba91/buildkite-agent:<TAG>
.
For your convenience, you can also use this image as yout Buildkite agent image as it's based on the official Buildkite image.
Please make sure to define a correct version of the plugin. Plugin releases are always tagged with v*
(for example v1.0.0
).
To be able to create and manage the jobs in your cluster, make sure the ServiceAccount
linked to your Buildkite agent deployment has sufficient RBAC permissions.
Please refer to charts/agent/templates/rbac.yml
for the RBAC permissions required.
For your convencience, a Helm chart is provided. Please take a look at the values.yaml
file for customization.
You can install the chart with Helm like this:
helm repo add buildkite-agent-kubernetes https://muhlba91.github.io/buildkite-agent-kubernetes
helm install buildkite-agent-kubernetes buildkite-agent-kubernetes/agent -f values.yaml
If you want to scale the Buildkite agent, you need to scrape and external metrics like buildkite_busy_agent_percentage
from Buildkite.
For example, you can use https://github.com/elotl/buildscaler.
For your convenience, a Helm chart to run Buildscaler is provided. Please take a look at the values.yaml
file for customization.
You can install the chart with Helm like this:
helm repo add buildkite-agent-kubernetes https://muhlba91.github.io/buildkite-agent-kubernetes
helm install buildkite-agent-kubernetes buildkite-agent-kubernetes/buildscaler -f values.yaml
steps:
- command: "echo 'Hello, World!'"
plugins:
- muhlba91/kubernetes#v0.0.0:
image: alpine
If you want to control how your command is passed to the container, you can use the command
parameter on the plugin directly:
steps:
- plugins:
- muhlba91/kubernetes#v0.0.0:
image: alpine
always-pull: true
command: ["echo", "command"]
You can pass in additional environment variables, including values from a Secret:
steps:
- command:
- "yarn install"
- "yarn run test"
plugins:
- muhlba91/kubernetes#v0.0.0:
image: "node:16"
environment:
- "PUBLIC_ENVIRONMENT_VARIABLE=value"
environment-from-secret:
- "environment-secrets"
The name of the container image to use.
Example: node:16
Whether to always pull the latest image before running the command. Sets imagePullPolicy on the container. If false
, the value IfNotPresent
is used.
Default: false
Sets the command for the container. Useful if the container image has an entrypoint, but requires extra arguments.
Note that this has different meaning than in Docker. This sets the args
field for the Container.
This option can't be used if your step already has a top-level, non-plugin command
option present.
Examples: [ "/bin/mycommand", "-c", "test" ]
, ["arg1", "arg2"]
Override the image’s default entrypoint.
Note that this has different meaning than in Docker. This sets the command
field for the Container.
Example: /my/custom/entrypoint.sh
An array of additional environment variables to pass into to the docker container. Items can be specified as KEY=value
.
Example: [ "FOO=bar", "PUBLIC_VALUE=value" ]
One or more Secrets that should be added to the container as environment variables. Each key in the secret will be exposed as an environment variable. If specified as an array, all listed secrets will be added in order.
Example: my-secrets
One or more Secrets that should be added to the job init container as environment variables. Each key in the secret will be exposed as an environment variable. If specified as an array, all listed secrets will be added in order.
Example: my-secrets
Override the job initContainer. A buildkite-agent binary is expected to exist to do the checkout, along with git and ssh. The default is to use a public image based on the Dockerfile in this repository. If set to an empty string no init container is used.
Example: quay.io/muhlba91/buildkite-agent:<VERSION>
Wether to run the container in privileged mode.
The name of the secret containing the buildkite agent token used for bootstrapping in the init container.
The key of the secret value containing the buildkite agent token, within the secret specified in agent-token-secret-name
.
Default: buildkite-agent-token
The name of the secret containing the git credentials used for checking out source code with HTTPS.
The key of the secret value containing the git credentials used for checking out source code with HTTPS.
The contents of this file will be used as the git credential store file.
Default: git-credentials
The name of the secret containing the git credentials used for checking out source code with SSH.
The key of the secret value containing the SSH key used when checking out source code with SSH as transport.
Default: ssh-key
Mount a host path as a directory inside the container. Must be in the form of /host/path:/some/mount/path
.
Multiple host paths may be mounted by specifying a list of host/mount pairs.
Example: my-secret:/my/secret
Mount a secret as a directory inside the container. Must be in the form of secretName:/some/mount/path
.
Multiple secrets may be mounted by specifying a list of secret/mount pairs.
Example: my-secret:/my/secret
The name of the secret containing the buildkite agent token, ssh and git credentials used for bootstrapping in the init container. The key names of the secret are configured as with separate secrets. This is useful if you have control over secret creation and would like to avoid explicitly providing the key and secret names.
Example: buildkite-secrets
Optionally mount a host path to be used as base directory for buildkite builds. This allows local caching and incremental builds using fast local storage.
Should be used with some care, since the actual storage used is outside the control of Kubernetes itself.
Example: /var/lib/buildkite/builds
Optionally mount an existing Persistent Volume Claim used as backing storage for the build.
Optionally mount a host path to be used as git-mirrors path. This enables multiple pipelines to share a single git repository.
Should be used with some care, since the actual storage used is outside the control of Kubernetes itself.
Example: /var/lib/buildkite/builds
Sets cpu request for the build container.
Sets cpu limit for the build container.
Sets memory request for the build container.
Sets memory limit for the build container.
Sets the service account for the build container.
Default: default
If set to true
, the spawned jobs will use the same node affinity, tolerations, and nodeSelector as the buildkite agent.
Override the working directory to run the command in, inside the container. The default is the build directory where the buildkite bootstrap and git checkout runs.
(Advanced / hack use). Provide a jsonnet function to transform the resulting job manifest.
Example:
patch: |
function(job) job {
spec+: {
template+: {
spec+: {
tolerations: [ { key: 'foo', value: 'bar', operator: 'Equal', effect: 'NoSchedule' }, ],
},
},
},
}
If set to true
, the resulting k8s job spec is printed to the log. This can be useful when debugging.
Configures spec.backoffLimit
to enable retries of job's pod creation.
Default value: 0
.
Configures spec.ttlSecondsAfterFinished
on the k8s job, requires TTL Controller enabled in the cluster, otherwise ignored.
Default value: 3600
.
If set to true
, the plugin cleans up k8s jobs older than 1 day even if they're still running.
Default value: true
.
If you have TTL Controller enabled or some other means to cleanup finished jobs, it is recommended to set the value to false
in order to reduce load on k8s api servers.
If set to true
plugin cleans up finished k8s job.
Default value: true
.
If you have TTL controller or https://github.com/lwolf/kube-cleanup-operator running, it is highly recommended to set the value to false
to reduce load on k8s api servers.
We welcome community contributions to this project.
If you enjoy the application and want to support my efforts, please feel free to buy me a coffe. :)