Self-hosted service
enix/kube-image-keeper avatar
enix/kube-image-keeper

kuik, a Kubernetes controller that mirrors and reroutes container images

kuik is a container image routing, mirroring (caching) and replication system for Kubernetes

757 stars63 forksGoMIT

At a glance

What is it?
enix/kube-image-keeper, short-named kuik, watches which images the pods in a cluster actually use and keeps them available by copying them between registries and rewriting image references at pod creation through a mutating webhook. The v3 rewrite is still in alpha while the 2.3 line remains in maintenance, and the project publishes a per-feature status table.
Who is it for?
Adopt kuik if your cluster pulls images from registries it does not control and you need pods to survive a registry outage, and you are willing to run an admission webhook in the cluster. Skip it if your images already come from a registry inside your own network, since that is the problem kuik exists to solve.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem and the three mechanisms

kuik, pronounced like quick, is the short name for kube-image-keeper, a container image routing, mirroring and replication system for Kubernetes.

The primary objective is stated plainly: to maximise the availability of pod images strictly within the Kubernetes cluster it runs on. The secondary goal is bulletproof reliability by keeping the manipulation of Kubernetes primitives to an absolute minimum.

That last phrase is the design principle and it explains the whole architecture. A tool that pulls images into the cluster after the fact, or that edits running deployments to change their image, has to touch a lot of Kubernetes objects and can leave the cluster in a strange state when it fails. kuik aims to do its work before or without mutating existing workloads.

Three core mechanisms do the work.

Image routing rewrites pod image paths on the fly during their creation to redirect them to a functional registry. This happens through a lightweight MutatingWebhook, which automatically rewrites the image path whenever the source registry becomes unavailable.

Image copy mirrors the images used by the local cluster across registries, building what the README calls a virtual, highly available registry. The important qualifier is that it mirrors the images actually in use, not everything, which keeps the copy cost proportional to what the cluster needs.

Image monitoring continuously tracks the availability of the pod images used within the local cluster across various registries, which is what tells the routing mechanism to act.

The three map onto three custom resources. ImageAlternative handles routing, ImageMirror handles copying and ImageMonitor handles monitoring, and each is documented in the CRD reference.

What works today, feature by feature

The README carries a status table for the v3 rewrite, and it is unusually honest, marking each feature with the alpha version it became available in and listing what is planned and what is not planned.

Image routing through the ImageAlternative custom resource and the mutating webhook has been available since 3.0.0-alpha.2. Plain-HTTP alternatives and mirror destinations, controlled by the insecure option, are also available since alpha.2 for ImageAlternative and since alpha.4 for ImageMirror.

Pull secret injection through the secret syncer arrived in 3.0.0-alpha.3. That is the feature that makes private registries work in a cluster that only holds the credentials for the source registry.

Image copy through ImageMirror arrived in 3.0.0-alpha.4, and image monitoring through ImageMonitor has had tracking and checks since alpha.4 as well, with drift detection and alternatives merged on main and shipping in the next alpha.

Admission validation is planned for the beta, and credentials sourced from a cloud provider through the auth.provider option are planned for v3.1.

Two entries are notable for what they say about the boundaries. Private certificate authorities are not planned yet, tracked as issue 750, which means a cluster whose registry uses a private CA is not currently served by kuik's own TLS handling. And migration from v2 is listed as none, with the note that a migration plan will be proposed once v3 is generally available, tracked as issue 749.

That last row is the one to read carefully if you are on 2.x. The README says the stable v2.3 line is in maintenance with bug fixes only, and the v3 specification lives in docs/v3/ starting with spec.md, which is described as the source of truth for v3 behaviour, frozen for now and subject to change after beta.

Two milestones are named with dates: the v3.0 beta is due 2026-11-01, where every feature is implemented but not yet stable, and the v3.0 GA milestone, where it becomes stable and ready for production.

How it is built and what the tooling looks like

The implementation is Go on Kubernetes, using controller-runtime v0.25.0 with client-go, apimachinery and the Kubernetes API at 0.37.0. The module is built for Go 1.26.0.

The dependencies describe the job precisely. google/go-containerregistry is the library for talking to OCI registries and handling image references, and distribution/reference handles the reference parsing. prometheus/client_golang provides the metrics. fsnotify is the filesystem watcher, and the controller-runtime stack handles the reconciliation and the admission webhook.

The Dockerfile shows the build in three stages. The builder uses golang 1.27 on alpine, installs controller-gen at v0.22.0 to generate the CRD and deepcopy code, downloads the modules, then runs controller-gen object and go build with linker flags that inject the version, revision and build date time into the internal/info package. The build date is computed at build time and substituted into the flags.

Two runtime images are produced from that. The alpine image exists for development and debugging, giving you a shell and other tools. The shipped image is distroless static nonroot, running as user 65532, which is the right default for a component that sits in the admission path of every pod creation.

The build tooling is a Taskfile with a thin Makefile shim over it, and the Makefile header explains why the shim exists: the kubebuilder CLI runs make generate manifests after scaffolding, and the end to end suite runs make docker-build, make install and make deploy, so the shim is there for tools that call make on their own. Everything else is meant to call task directly, and task is installed into bin/ on first use.

The repository layout is a Kubernetes project layout: api/ for the CRD types, cmd/ for the entry point, internal/ for the implementation, helm/ for the chart, config/ for the standard Kubebuilder configuration, docs/ for the documentation including the v3 specification, notes/ for development decisions, test/ for the suites, hack/ for scripts, and a website/ directory. The badges show separate CI workflows for lint, unit tests and end to end tests, and the chart is published to Artifact Hub.

The stability question and the cost of an admission webhook

Two things are worth spelling out before anyone runs this in a cluster they care about.

The first is that kuik sits in the pod creation path. Every pod that starts passes through the MutatingWebhook, so if the webhook is slow, unavailable or misconfigured, pods do not start. The README's own stated goal of keeping the manipulation of Kubernetes primitives to an absolute minimum is about not editing running workloads, but the webhook is still a dependency on the critical path of every deployment in the cluster. A cluster with a strict deployment availability requirement should treat the webhook's own high availability as part of that requirement, and the fact that it is described as lightweight is a claim about resource use rather than about failure behaviour.

The second is the gap between the alpha and the stable line. The README marks v3 as neither stable nor feature complete, with the beta due 2026-11-01 where every feature is implemented but not yet stable, and GA after that. The 2.3.x branch is in maintenance with bug fixes only, and the migration path from v2 is listed as none, with a plan to be proposed once GA is out.

That gives you two reasonable strategies. Stay on 2.3 while you need stability, and treat the v3 documentation as reading rather than a commitment. Or move to v3 beta once the feature table shows what you need, understanding that you will be on a moving target until GA.

Two features that are simply absent are worth knowing in advance. Private certificate authorities are not planned yet, so a registry fronted by an internal CA is not covered by kuik's own TLS handling. And plain-HTTP alternatives and mirror destinations are available through the insecure option, which is a development and lab convenience rather than something to enable against production registries.

The pull secret injection through the secret syncer is the feature that makes the whole design work with private images, and it has been available since alpha.3. If your workload pulls from a private source registry, that is the piece you would be relying on most.

Where this fits against the alternatives

The first alternative is doing nothing and relying on the registry being there. In many clusters that is fine, and it is the cheapest option. kuik earns its place when the images in your cluster come from somewhere you do not control, when an outage of that provider means pods cannot start, and when the cost of an outage is high enough to justify running an admission webhook in the cluster.

The second alternative is a pull-through cache registry. A pull-through cache registry is simpler than kuik, since the cache is invisible to Kubernetes. What kuik adds is the routing behaviour: it can point a pod at an alternative registry when the source becomes unavailable, rather than simply failing the pull while a cache warms up. And the copy is selective, driven by what the cluster uses, rather than a general proxy cache.

The third is to mirror images into your own registry as part of your release pipeline, which is what most mature setups do. That gives you a local copy with no dependency on the upstream provider at all. kuik is aimed at the cases where you did not build the images and cannot control their publishing, so the mirroring has to be automatic.

The honest caveats are the ones the README states. The v3 rewrite is in alpha and the feature table has gaps, including no private certificate authority support and no migration path from v2 yet. Running a mutating webhook means every pod creation passes through it, so its availability becomes the availability of your cluster's ability to start workloads, which is a significant thing to put on an early-stage component.

For a team on 2.x today, the sensible path is the maintenance branch, and the v3 documentation is worth reading now so you can see where the project is going before you commit to the rewrite.

Editorial conclusion

Adopt kuik if your cluster pulls images from registries it does not control and you need pods to survive a registry outage, and you are willing to run an admission webhook in the cluster. Skip it if your images already come from a registry inside your own network, since that is the problem kuik exists to solve. Verify first by reading the feature status table in the README to see which parts of v3 are actually available, and start from the 2.3 line if you need something stable rather than the v3 rewrite.

Frequently asked questions

What is kuik and what does it do in a Kubernetes cluster?

kuik is the short name for kube-image-keeper, a controller that maximises pod image availability inside the cluster it runs on. It rewrites pod image paths at creation to a working registry, mirrors the images the cluster uses between registries, and tracks the availability of those images across registries.

How does the image routing work?

A lightweight MutatingWebhook rewrites the image path on pods as they are created, redirecting them to a functional registry whenever the source registry becomes unavailable. The routing is driven by the ImageAlternative custom resource.

Is kuik v3 ready for production?

Not yet. The README warns that kuik v3 is at a very early stage of development, neither stable nor feature complete, and is released as alphas. The v3.0 beta milestone is due 2026-11-01 and the GA milestone follows, while the 2.3.x branch remains the stable version in maintenance with bug fixes only.

Which features does kuik support today?

Image routing and the ImageAlternative resource since alpha.2, pull secret injection since alpha.3, image copy through ImageMirror and image monitoring since alpha.4, and insecure plain-HTTP alternatives and mirror destinations for both. Admission validation is planned for the beta and cloud provider credentials for v3.1.

What does the kuik repository look like for a developer?

It is a Go project on controller-runtime with api/ for the custom resource types, cmd/ and internal/ for the implementation, helm/ for the chart and config/ for the Kubebuilder configuration, plus docs/ containing the v3 specification and notes/ recording development decisions. The Makefile is a thin shim over a Taskfile so that the kubebuilder CLI can call make targets.

Official sources

  1. enix/kube-image-keeper on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/enix-kube-image-keeper.svg)](https://hysenlabs.com/projects/enix-kube-image-keeper)

Was this useful?