KINDONC!!
a.k.a. kind-on-c
a.k.a. kind on concourse
This is a [concourse] task which uses kind to start a kubernetes cluster locally for users to run their tests against.
Users can choose to run whichever kubernetes version kind uses by default, or use a specific kubernetes version by providing the kubernetes source tree checked out at a specific version.
It is heavily based on concourse-dcind and of course uses kind. This is really just plumbing ...
kind
thinks is cool ...jobs:
- name: kind
plan:
- in_parallel:
- get: kind-on-c
- get: kind-release
params:
globs:
- kind-linux-amd64
- task: run-kind
privileged: true
file: kind-on-c/kind.yaml
params:
KIND_TESTS: |
# your actual tests go here!
kubectl get nodes -o wide
resources:
- name: kind-release
type: github-release
source:
owner: kubernetes-sigs
repository: kind
access_token: <some github token>
pre_release: true
- name: kind-on-c
type: git
source:
uri: https://github.com/pivotal-k8s/kind-on-c
This uses the kind
binary, provided by the kind-release
resource, to create
a kubernetes cluster. It will use the node image from the kind team.
The version of kind
in use and thus, indirectly, the kubernetes version
deployed can be controlled by pinning the kind-release
resource to a specific
version.
When the cluster is up and running, any commands configured in $KIND_TESTS
will run. The environment is setup with $KUBECONFIG
which points to the
client configuration for the deployed kubernetes cluster. Also the most recent
(stable) version of kubectl will be downloaded and put into the $PATH
,
therefore kubectl <something>
will just work™️.
jobs:
- name: kind
plan:
- in_parallel:
- get: k8s-git
- get: kind-on-c
- get: kind-release
params:
globs:
- kind-linux-amd64
- task: run-kind
privileged: true
file: kind-on-c/kind.yaml
params:
KIND_TESTS: |
# your actual tests go here!
kubectl get nodes -o wide
resources:
- name: k8s-git
type: git
source:
uri: https://github.com/kubernetes/kubernetes
- name: kind-release
type: github-release
source:
owner: kubernetes-sigs
repository: kind
access_token: <some github token>
pre_release: true
- name: kind-on-c
type: git
source:
uri: https://github.com/pivotal-k8s/kind-on-c
If the task finds an task input named k8s-git
it treats that as a
kubernetes source tree and tells kind to create a node image off of that. You
can just use a git resource, and pin it to a specific commit if need be, if you
want to run a specific kubernetes version.
In this case, also kubectl
is compiled on the fly and therefore exactly
matches the version of kubernetes deployed.
KIND_TESTS
KIND_TESTS: |
kubectl get nodes -o jsonpath="{..name}" | grep -q 'worker2' || {
echo >&2 "Expected node 'worker2' not found"
return 1
}
Note: The tests will run in bash with the options errexit
& nounset
KIND_CONFIG
KIND_CONFIG: |
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
Note: potentially the config you specify will be patched with things that are essential for kind-on-c to work properly.
EXPORT_NODE_ROOTFS
exported-node-rootfs
.EXPORT_NODE_IMAGE
exported-node-image
.INSTALL_METALLB
LoadBalancer
and get an
EXTERNAL-IP
for those. This external IP can be used to connect to a
exposed service from the task container, thus from code running in
KIND_TESTS
.KIND_PRE_START
DOCKERD_OPTS
DOCKERD_TIMEOUT
KINDONC_DEBUG
KIND_LOGLEVEL
<= 0.5.1
this value is used for the --loglevel
option and needs to be one of panic
, fatal
, error
, warning
, info
, debug
.> 0.5.1
this value is used for the --verbosity
option and needs to be and integer. KIND_CLUSTER_NAME
kind-on-c
, mandatorykind-release
, mandatory
Must prrovide the kind binary, named kind-linux-amd64
.
This should either be backed by a github-release resource or a earlier task
that compiles kind from the source.k8s-git
, optionalnode-image
, optional
Must provide an OCI image image.tar
that will be used as a node image. This
can be an image generated via
EXPORT_NODE_IMAGE
/exported-node-image
or any other OCI image that can be used as node image for kind.inputs
, optionalinputs
input. More about that in Aggregated inputs & outputs.The task generates all the outputs in this list, however depending on the task's configuration it may leave certain (or even all) outputs empty.
exported-node-image
registry-image
resource could be used to push the node image into a registry.
jobs:
- name: kind
plan:
- task: run-kind
privileged: true
file: kind-on-c/kind.yaml
params:
EXPORT_NODE_IMAGE: 1
- put: image-repo # this is a registry-image resource
params:
image: exported-node-image/image.tar
exported-node-rootfs
metadata.json
.
With that it is possible to use the node image as a task image for a
following concourse task.
jobs:
- name: kind
plan:
- task: run-kind
privileged: true
file: kind-on-c/kind.yaml
params:
EXPORT_NODE_ROOTFS: 1
- task: do something with the node rootfs
image: exported-node-rootfs
config:
platform: linux
run:
path: bash
args:
- -xeuc
- |
echo "Concourse is now running the image we built with kind"
outputs
ouputs
output. More about that in Aggregated inputs &
outputs.Chances are good, that you need some additional tools to run your
KIND_TESTS
. To do that, you can use a custom task image.
You can e.g. use the registry-image
resource to pull in your custom image and
then override kind-on-c's default image by providing its rootfs to the
kind-on-c task via the image
directive. This overrides the image that is
configured in the task config.
When it comes to creating the image, you can base it on the default kind-on-c
image and add your additional tools and things as another layer. For that you
can follow the image's ci-latest
tag, which gets updated every time we push a
new task image. Or you can extract all information (repo and digest) of the
default task image from the task config file.
When you want to bring a entirely different image which is not based on kind-on-c's default task image, you need to check which dependencies we need in the Dockerfile.
For e.g. static binaries you could, instead of providing a custom image, have
concourse pull down all the needed things and provide them to the task via the
inputs
input. Also, of course, nothing stand in the way to use both a custom
image and provide certain things via inputs
.
jobs:
- name: kind
plan:
- in_parallel:
- get: custom-kind-on-c-image
- get: kind-on-c
- get: kind-release
- get: other-custom-things
- task: run-kind
privileged: true
file: kind-on-c/kind.yaml
image: custom-kind-on-c-image # This overrides the image from the task config file
input_mapping:
inputs: other-custom-things
params:
KIND_TESTS: # use custom things either from the image or from inputs
resources:
- name: custom-kind-on-c-image
type: registry-image
source: {repository: my-custom-image, tag: "1.13"}
- name: other-custom-things
type: some-resource-type
source: {...}
Currently this task only allows for a fixed set of inputs and outputs (some inputs are optional, some output might be kept empty). This set cannot be changed by users of kind-on-c.
Still users need to be able to provide one or more of their own resources to be consumed by this task as inputs or generate one or more outputs by this task.
A workaround for this are (what I call now) aggregated inputs & outputs:
Users can use as many input resources they want, they however need to aggregate
them into the one input inputs
for this task. Likewise, if that is something
a user needs to do, they can place all their outputs into the single outputs
output and have a later task split them apart again, into separate, individual
outputs.
After all, inputs and outputs are eventually "just directories" on disk and therefore relatively easy to manipulate if need be.
The following (contrived) example shows how this could be used:
input-res-1
, input-res-2
, and input-res-3
into the input inputs
inputs
outputs
and places artifacts
, metrics
, and logs
in thereoutputs
output of the kind-on-c task, splits
those up and makes them available as separate outputs artifacts
, metrics
,
and logs
put
resources just care about one of the individual outputsplan:
- in_parallel:
- get: kind-on-c
- get: input-res-1
trigger: true
- get: input-res-2
trigger: true
- get: input-res-3
- task: aggregate inputs for kind-on-c
config:
platform: linux
image_resource:
type: registry-image
source: { repository: bash }
inputs:
- name: input-res-1
- name: input-res-2
- name: input-res-3
outputs:
- name: inputs # this will be the aggregated inputs for kind-on-c
run:
path: bash
args:
- -xeuc
- |
cp -a input-res-1 inputs/
cp -a input-res-2 inputs/
cp -a input-res-3 inputs/
- task: kind-on-c
privileged: true
file: kind-on-c/kind.yaml
params:
KIND_TESTS: |
# your actual tests go here!
cp -a some/artifacts outputs
cp -a some/metrics outputs
cp -a some/logs outputs
- task: split aggregated outputs of kind-on-c
config:
platform: linux
image_resource:
type: registry-image
source: { repository: bash }
inputs:
- name: outputs
outputs:
- name: artifacts
- name: metrics
- name: logs
run:
path: bash
args:
- -xeuc
- |
cp -a outputs/artifacts/* artifacts
cp -a outputs/metrics/* metrics
cp -a outputs/logs/* logs
- in_parallel:
- put: artifactory # using only the artifacts output of the last task
params:
folder: artifacts
- put: lftp-log-dump # using only the log output of the previous task
params:
files: "logs/*.log"
- put: swift-metrics-store # using only the metrics output of the previous task
params:
from: "metrics/(.*)"
kind-on-c made the design decision to use a task file. This is mostly to have an easy way to specify the specific version of the kind-on-c image, have the pipeline automatically update it, and track which commit has been tested with which version of the image.
concourse however does not allow to mix settings (e.g. inputs) from a task file with inline configuration in the task config.
Therefore, for now at least, kind-on-c is opting for specifying the set of allowed/available inputs/outputs, which might mean a bit of overhead for the users.