Skip to content

Custom Resource Definitions

This document describes the available Custom Resource Definitions (CRDs). Examples provided are non-exhaustive; for a full list of fields, please refer to the kubectl describe <resource-name> command.

For image, namespace, and pod filtering (scoping resources to specific images, namespaces, or pods) see Resource filtering.

Resource Types:

The ReplicatedImageSet and ClusterReplicatedImageSet resources declare equivalence between image patterns across different registries. By mapping multiple upstream locations to a single logical “ImageSet”, you ensure the cluster treats these varied sources as the same entity.

This is particularly useful for multi-homed projects (e.g., Thanos, Prometheus, Kubernetes components) where the same binary is published to multiple registries.

FieldRequiredDescription
spec.priorityControls ordering of alternatives relative to the original image and other CRs. Negative values place alternatives before the original image; positive values place them after. Default is 0 (original image first).
spec.namespaceFilter(ClusterReplicatedImageSet only.) Restricts which namespaces this resource applies to. See Namespace filtering.
spec.podFilterRestricts which pods this resource applies to. See Pod filtering.
spec.upstreams[]List of upstream image sources that should be considered equivalent.
spec.upstreams[].registryRegistry where the upstream image is hosted (e.g. docker.io, quay.io).
spec.upstreams[].pathPath identifying the image in the registry (e.g. /thanosio/thanos).
spec.upstreams[].priorityControls ordering of this upstream relative to other upstreams with the same parent priority. 0 means no specific ordering (YAML declaration order is preserved). Positive values are sorted ascending: lower value = higher priority.
spec.upstreams[].imageFilterRules used to select which images from this upstream are considered replicated. See Image filtering.
spec.upstreams[].discardAlternativeWhen true, keeps the upstream in the configuration but excludes it from image routing. The upstream still participates in image matching, so other upstreams in the same CR continue to work. Useful when a registry no longer exists, to avoid waiting for the check timeout.
spec.upstreams[].credentialSecretReference to a Secret used to pull matching images from this upstream.
spec.upstreams[].credentialSecret.nameName of the Secret.
spec.upstreams[].credentialSecret.namespaceNamespace of the Secret. Ignored for namespaced ReplicatedImageSet (uses the parent namespace instead).

In the following example, the ClusterReplicatedImageSet declares that the images hosted on Quay and Docker Hub are identical. This allows the system to resolve them as the same ImageSet regardless of the source registry used in a Pod spec and fallback to one or another depending on their availability.

apiVersion: kuik.enix.io/v1alpha1
kind: ClusterReplicatedImageSet
metadata:
name: thanos
spec:
upstreams:
- registry: docker.io
imageFilter:
include:
- /thanosio/thanos:.+
path: /thanosio/thanos
- registry: quay.io
imageFilter:
include:
- /thanos/thanos:.+
path: /thanos/thanos/

ReplicatedImageSet are the same, but scoped to a namespace. In the following example, we have three different upstreams for the same image and we use priority to order alternatives. So if our original image is using Quay and the registry is unreachable, kuik will consider both GHCR and DockerHub as alternative, but try using the one from GHCR first and only fallback to DockerHub if it’s unreachable too:

apiVersion: kuik.enix.io/v1alpha1
kind: ReplicatedImageSet
metadata:
name: x509-certificate-exporter
namespace: monitoring
spec:
upstreams:
- registry: quay.io
imageFilter:
include:
- /enix/x509-certificate-exporter:.+
path: /enix/
priority: 1
- registry: ghcr.io
imageFilter:
include:
- /enix/x509-certificate-exporter:.+
path: /enix/
priority: 2
- registry: docker.io
imageFilter:
include:
- /enix/x509-certificate-exporter:.+
path: /enix/
priority: 3

The ImageSetMirror and ClusterImageSetMirror resources define the actual mirroring implementation for your cluster. They determine which images are selected for synchronization, specify the target destination, and manage the authentication via push secrets.

FieldRequiredDescription
spec.priorityControls ordering of alternatives relative to the original image and other CRs. Negative values place alternatives before the original image; positive values place them after. Default is 0 (original image first).
spec.namespaceFilter(ClusterImageSetMirror only.) Restricts which namespaces this resource applies to. See Namespace filtering.
spec.podFilterRestricts which pods this resource applies to. See Pod filtering.
spec.imageFilterRules used to select which images are eligible for mirroring. See Image filtering.
spec.cleanupCleanup strategy for mirrored images.
spec.cleanup.enabledWhether automatic cleanup of unused mirrored images is enabled. Default is false.
spec.cleanup.retentionDuration to retain unused mirrored images before cleanup (e.g. 720h).
spec.mirrors[]List of mirror destinations.
spec.mirrors[].registryTarget registry where images will be mirrored (e.g. registry.example.com).
spec.mirrors[].pathPath prefix on the target registry (e.g. /mirror).
spec.mirrors[].priorityControls ordering of this mirror relative to other mirrors with the same parent priority. 0 means no specific ordering (YAML declaration order is preserved). Positive values are sorted ascending: lower value = higher priority.
spec.mirrors[].credentialSecretReference to a Secret used to push images to this mirror.
spec.mirrors[].credentialSecret.nameName of the Secret.
spec.mirrors[].credentialSecret.namespaceNamespace of the Secret. Ignored for namespaced ImageSetMirror (uses the parent namespace instead).
spec.mirrors[].cleanupPer-mirror cleanup strategy override. Same fields as spec.cleanup.

In this example, the ClusterImageSetMirror ensures that all images are mirrored to a private registry. It uses a specific credentialSecret to authenticate against the destination.

apiVersion: kuik.enix.io/v1alpha1
kind: ClusterImageSetMirror
metadata:
name: global-mirror
spec:
imageFilter:
include:
- .*
mirrors:
- registry: registry.example.com
path: /mirror
credentialSecret:
name: registry-secret
namespace: kuik-system
cleanup:
enabled: true
retention: 24h

The registry secret must be a docker-registry type secret. You could create it with:

Terminal window
kubectl -n kuik-system create secret docker-registry registry-secret --docker-server=registry.example.com --docker-username=username --docker-password=password

When cleanup is enabled, kuik only delete mirror image reference once an image is no longer running in the cluster since more than retention time (useful to deal with image used by CronJobs). You still have to configure garbage collection on your registry to actually reclaim space.

If an image is rewritten to use our mirror, kuik will copy the secret to the pod’s namespace and add it to pod imagePullSecrets.

The ClusterImageSetAvailability resource continuously monitors the upstream availability of container images used in the cluster. It automatically discovers images from running Pods, checks whether they are still reachable on their source registry, and reports their status.

This is useful for detecting images that have been deleted, made private, or are hosted on unreachable registries before they cause issues during a Pod reschedule.

FieldRequiredDescription
spec.unusedImageExpiryHow long to keep tracking an image after no Pod uses it. Once elapsed the image is removed from status (e.g. 720h). Zero means unused images are never removed.
spec.imageFilterRules used to select which images to monitor. See Image filtering.
spec.namespaceFilterRestricts which namespaces this resource applies to. See Namespace filtering.
spec.podFilterRestricts which pods this resource applies to. See Pod filtering.
  1. The controller watches all Pods in the cluster and collects their container image references.
  2. Images matching the imageFilter are added to .status.images with status Scheduled.
  3. A rate-limited checker performs availability checks against each image’s source registry (one image per registry per tick, configurable via monitoring.registries in the operator configuration file).
  4. When a Pod is deleted and no other Pod uses the same image, unusedSince is set. After unusedImageExpiry, the image is removed from tracking.
apiVersion: kuik.enix.io/v1alpha1
kind: ClusterImageSetAvailability
metadata:
name: monitor-critical-images
spec:
unusedImageExpiry: 720h
imageFilter:
include:
- ".+/nginx:.+"
- ".+/redis:.+"

The check rate and method are controlled per-registry in the operator’s config.yaml, not in the CRD. See the full operator configuration reference for the list of all supported fields, their defaults, and the precedence rules.

monitoring:
registries:
default:
method: HEAD
interval: 3h
maxPerInterval: 25
timeout: 10s
items:
docker.io:
interval: 1h
maxPerInterval: 6
fallbackCredentialSecret:
name: dockerhub-creds
namespace: kuik-system
FieldDefaultDescription
methodHEADHTTP method used for the availability check (HEAD or GET).
interval3hTime window over which maxPerInterval checks are spread.
maxPerInterval25Maximum number of image checks per interval for a given registry.
timeout0 (none)Timeout for each individual check.
fallbackCredentialSecretnoneSecret to use when Pod pull secrets are unavailable.