Forge
Forge is a Kubernetes controller designed to securely build OCI-compliant images
inside a cluster and push them to one or more target registries. This project
was derived from the work done in the img project and extended to support
build dispatch via a custom resource definition.
Development
Requirements
- Linux
- go 1.13
- golangci-lint
- kubebuilder
- A Kubernetes cluster with kubectl access configured (minikube suggested)
Local setup
Start Kubernetes cluster:
minikube start --insecure-registry="localhost:32002"
Install helm on the host:
export HELM_VERSION="v3.4.2"
curl -L https://get.helm.sh/helm-$HELM_VERSION-linux-amd64.tar.gz | tar -xvz -C /tmp
sudo mv /tmp/linux-amd64/helm /usr/local/bin/
helm repo add stable https://charts.helm.sh/stable
helm repo update
Install Docker registry:
helm upgrade -i docker-registry stable/docker-registry \
--values e2e/helm_values/docker-registry-auth-only.yaml \
--wait
Create Docker registry auth secret:
kubectl apply -f config/samples/docker-registry-auth.yaml
Prepare cluster for running Forge builds:
make install
(Repeat this step if you modify the custom resource definition.)
Local edit / compile / test workflow
Run tests:
make test
Connect the host's Docker client to minikube's Docker server so that the image that will be built will be available in minikube:
eval $(minikube docker-env)
Build Forge image with a custom name:
export IMG=test-forge:$(date +%s)
make docker-build
Run Forge's controller on the host, using the image from the previous step for build jobs:
go run main.go --build-job-image $IMG
On a different terminal, create a CIB (container image build) resource to trigger a build:
kubectl apply -f config/samples/init-container-sample.yaml
Watch for build pods:
kubectl get pods | grep build
Follow the build logs:
kubectl logs -f build-init-container-sample-jmnjf
Confirm that the image was built and uploaded to the Docker registry:
curl -u marge:simpson $(minikube ip):32002/v2/_catalog
To try again with the same CIB resource name, first delete the old resource so that the Forge controller will destroy
the job and pod, and then create it again:
kubectl delete cib example-build
kubectl apply -f config/samples/forge_v1alpha1_containerimagebuild.yaml
Inspecting generated images
Since minikube was started with an option to allow a local insecure Docker registry on port 32002, a minikube shell
session will be able to work with images that were pushed to that registry:
minikube ssh
echo 'simpson' | docker login localhost:32002 -u marge --password-stdin
docker pull localhost:32002/init-container-sample
Preparer Plugins
Forge supports the inclusion of custom plugins for the "preparation" phase of a build (between the initialization of the context and the actual image build).
This functionality is built with the go-plugin framework from Hashicorp.
Creation
example/preparer_plugin.go has the necessary structure for creating a new preparer plugin.
Functionality is implemented through two primary functions:
Prepare(contextPath string, pluginData map[string]string) error
Prepare runs between the context creation and image build starting. contextPath
is an absolute path to the context for the build.
pluginData
is the key-value data passed through the ContainerImageBuild.
Cleanup() error
Cleanup runs after the build has finished (successfully or otherwise).
Using
To add a new runtime plugin for Forge, place a file in /usr/local/share/forge/plugins/
(by default) or specify it with --preparer-plugins-path
.