Build
Build Quarks-operator from source
The quarks-* operators share some common scripts, that are in the quarks-utils
project. You can run bin/tools
to download them. Or download them manually from quarks-utils
.
Some scripts require the PROJECT
env var to be set, e.g. PROJECT=quarks-secret
.
make tools
Kubernetes allows developers to extend the objects its APIs process and store using Custom Resource Definitions (CRDs). We are creating four CRDs (see Controllers):
The CRDs are also defined in code and applied automatically when quarks-operator starts. If you are editing CRDs, you should update changes to this YAML files in sync.
create a new directory: ./pkg/kube/apis/<group_name>/<version>
in that directory, create the following files:
types.go
register.go
doc.go
You can safely use the implementation from another controller as inspiration. You can also copy the files and modify them.
The types.go
file contains the definition of your resource. This is the file you care about. Make sure to run make generate
every time you make a change. You can also check to see what changes would be done by running make verify-gen-kube
.
The register.go
file contains some code that registers your new types.
This file looks almost the same for all API resources.
The doc.go
(deep object copy) is required to make the deepcopy
generator work.
It’s safe to copy this file from another controller.
in bin/gen-kube
, add your resource to the GROUP_VERSIONS
variable (separated by a space " "
):
|
|
regenerate code
|
|
create a directory structure like this for your actual controller code:
|
|
controller.go
is your controller implementation; this is where you should implement an Add
function where register the controller with the Manager
, and you watch for changes for resources that you care about.reconciler.go
contains the code that takes action and reconciles actual state with desired state.Simple implementation to get you started below. As always, use the other implementations to get you started.
Controller:
|
|
Reconciler:
|
|
add the new resource to addToSchemes
in pkg/controllers/controller.go
.
add the new controller to addToManagerFuncs
in the same file.
create a custom resource definition and add docs to docs/crds
.
|
|
env/machine
env/catalog
A pattern that comes up quite often is that an object needs to be updated if it already exists or created if it doesn’t. controller-runtime
provides the controller-util
package which has a CreateOrUpdate
function that can help with that. The object’s desired state must be reconciled with the existing state inside the passed in callback MutateFn - type MutateFn func() error
. The MutateFn is called regardless of creating or updating an object.
|
|
CreateOrUpdate
s should not use blindly DeepCopyInto
or DeepCopy
all the time, but make more precise changes.We start with a single context and pass that down via controllers into
reconcilers. Reconcilers will create a context with timeout from the inherited
context and linting will check if the cancel()
function of that context is
being handled.
The ctxlog
module provides a context with a named zap logger and an event recorder to the reconcilers.
This is how it’s set up for reconcilers:
|
|
The ctxlog
package provides several logging functions. Infof
, Errorf
, Error
and such wrap the corresponding zap log methods.
The logging functions are also implemented on struct, to add event generation to the logging:
|
|
The reason should be camel-case, so switch statements could match it.
Error funcs like WithEvent().Errorf()
also return an error, with the same message as the log message and event that were generated.
Calling WarningEvent
just creates a warning event, without logging.
The quarks-operator uses quarks-job as an external component. The quarks-job operator is run in a separate process.
When using jobs that capture output, quarks-job needs to know its docker image, to run the persist-output
command in a container.
References to quarks job:
go.mod
:
‘b5dc240’QUARKS_JOB_IMAGE_TAG
:
‘v0.0.0-0.gb5dc240’bin/build-helm
, which uses the QUARKS_JOB_HELM_VERSION
variable:
‘0.0.0-0.gb5dc240’Both variables are set in bin/include/dependencies
.
To update a dependency in a project use go get
, e.g.:
go get -t -u code.cloudfoundry.org/quarks-job@aad515c
Using the git commit sha prevents caching problems, which might occur with branch names.
When working locally with multiple repositories it’s helpful to replace github dependencies with local directories. The go mod edit -replace
will modify the go.mod
file to point to a local dir, e.g. ‘../quarks-job’ instead:
go mod edit -replace code.cloudfoundry.org/quarks-utils=../quarks-utils
go mod edit -replace code.cloudfoundry.org/quarks-job=../quarks-job
The modified libraries are not visible to the container. As a workaround a vendor folder can be used, which is also faster:
GO111MODULE=on go mod vendor
GO111MODULE=off make build-image
rm -fr vendor
To use a local docker image export QUARKS_JOB_IMAGE_TAG
and make sure the image is available to the cluster, e.g. for kind:
kind load docker-image cfcontainerization/quarks-operator:$DOCKER_IMAGE_TAG
kind load docker-image cfcontainerization/quarks-job:$QUARKS_JOB_IMAGE_TAG
To use a local docker image export QUARKS_JOB_IMAGE_TAG
and make sure the image is available to the cluster, e.g. for kind:
docker tag <quarks-operator-tag> cfcontainerization/quarks-operator:$DOCKER_IMAGE_TAG
docker tag <quarks-job-tag> cfcontainerization/quarks-job:$QUARKS_JOB_IMAGE_TAG
APIs and types follow the upstream versioning scheme described at: https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-versioning
Copy the grc (generic colouriser grcat) config file zap.grc.conf to /usr/share/grc/conf.zap
and pipe logs to grcat conf.zap
:
# install the custom log config
cp docs/zap.grc.conf /usr/share/grc/conf.zap
# running operator
kubectl get pods -A -l name=quarks-operator --no-headers=true | tail -1 | read namespace name _
kubectl logs -f -n "$namespace" "$name" | grcat conf.zap
# integration tests example
grcat conf.zap < /tmp/quarks-operator-tests.log
Build Quarks-operator from source
Tools to simplify your development workflow
Useful links to Kubernetes operators implementations or patterns