CopyImage Controller
To copy public registry container images referenced in Deployment/DaemonSets to another private OCI Registry
Currently only support Docker(index.docker.io) registry
Demo
Development
This controller is developed using kubebuilder to generate all the bootstrap code as well as kuberetes manifests. As we do not require any CRDs for this controller, API Types creation is skipped.
Below controllers are created for watching/reconciling deployments
and daemonsets
respectively.
- CopyImageDeploymentReconciler
- CopyImageDaemonsetReconciler
Both controllers filters only create/update events on their respective watch objects as shown for CopyImageDeploymentReconciler
// CopyImageController for Deployments
func (r *CopyImageDeploymentReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&v1.Deployment{}).
WithEventFilter(predicate.Funcs{
DeleteFunc: func(e event.DeleteEvent) bool {
// Suppress Delete events to avoid filtering them out in the Reconcile function
return false
},
}).
Complete(r)
}
There a utility, utils.CloneImage
which intialize the private registry credentials along with the main logic to check/copy images to private registry.
Local Setup:
-
Prerequisite Make sure the following are installed.
-
Clone this project (which has already been setup for you)
- requires git
git clone https://github.com/dharmjit/copyimage-controller
-
Update code with your settings
- Update Makefile with your Docker Repository
- IMG ?= {your_repo_name}/copyimage-controller:latest
- Update Secret
dockersecret
defined inconfig/manager/manager.yaml
with base64 values applicable for you
- Update Makefile with your Docker Repository
-
Setup Local Dev cluster
- kind kind
- Requires go(1.14+) and docker
- Install [kind] (https://kind.sigs.k8s.io/docs/user/quick-start/)
- Create the cluster
kind create cluster
- Test the setup
kind get cluster
andkubectl get nodes
- kind kind
-
Run the controller
- Change directory in another shell
cd copyimage-controller
- Make run with your credentials
PRIV_OCI_REGISTRY=index.docker.io PRIV_OCI_REPOSITORY=your_repo_name PRIV_OCI_REGISTRY_USERNAME=your_username PRIV_OCI_REGISTRY_PASSWORD=your password make run
- Change directory in another shell
-
Verify the controller
cd copyimage-controller/test
kubectl create -f nginx-singlecontainer.yaml
kubectl get deploy/nginx-single-deployment -o yaml
-
Deploy the controller as a deployment
- set below variables in your terminal
export PRIV_OCI_REGISTRY="index.docker.io" export PRIV_OCI_REPOSITORY="" export PRIV_OCI_REGISTRY_USERNAME="" export PRIV_OCI_REGISTRY_PASSWORD=""```
- Build Controller Docker Image
make docker-build
- Push Controller Docker Image
make docker-push
- Deploy Controller and other Manifests
make deploy
- set below variables in your terminal
TODO
- Do not Remote Write Image if it already exists
- Add Namespace filter as predicate
- Update Event filter only for Image changes
- Custom Resync period
- Initialize an OCI client to reduce repeated authention with
remote.Write
- Update Message for
kubectl rollout history
- Concurrency Handling of
Utils.CloneImage
Method - Handle Optimistic Concurrency effectively if possible
- Better Handle
utils.CloneImage
errors - Externalize the Hardcoded Public Registry Name. It could be a list of public registries
Supplementary Resources
For those who are interested, there is documentation on kubebuilder available here: