Skip to content

Known limits

This documents the in-development version. Switch to v2.3 for the latest stable release.

This page lists what the current version of kuik does not do yet, and how to work around it. The release notes say when a release lifts or adds one.

  • Cloud credentials: credentials from a cloud provider (auth.provider: aws, gcp, azure) are accepted but not used yet: kuik moves on to the next credential, and never injects them as pull Secrets. Planned for 3.1; use a secretRef meanwhile, see Registry credentials.
  • One install per cluster: the Secret names the secret syncer reserves are cluster-wide, so the syncers of 2 installs would refuse each other’s writes, see Installation.
  • Reconciler first: the webhook admits pods unchanged until the reconciler has created the ConfigMap kuik-cluster-id, so never run with reconciler.replicas: 0, see Cluster ID.
  • Cluster ID: deleting the ConfigMap kuik-cluster-id, or its namespace, generates a new cluster ID and orphans every tag already copied; never copy it to another cluster that shares a destination, or both delete each other’s tags, see Cluster ID.
  • Backups: a restore tool such as Velero is refused the pull Secrets kuik manages; the syncer recreates them, but the restore ends PartiallyFailed. Exclude these Secrets from the backup, see What the syncer may write.
  • Tag deletion: a destination that never accepts tag deletion holds a deleted ImageMirror until cleanup.enabled is set to false, or cleanup.deleteByDigest to true when that ImageMirror is the only writer of its destination and the destination accepts the deletion of a manifest by digest (otherwise it stays held, with Ready False and reason RegistryDeleteUnsupported, see An ImageMirror stays Terminating), see Deleting an ImageMirror. A refusal for credentials (401, 403) shows on a live ImageMirror only as a Warning ImageDeletionFailed event, with no condition, and on a deleted one only in the reconciler logs.
  • Push refused with 403: a destination that refuses a push with a 403, such as a quota refusal, still gets it once per destination credential before the copy backs off, see Copies.
  • Harbor: Harbor refuses tag deletion through the registry API (any DELETE by tag answers 400), so cleanup deletes nothing on a Harbor destination by default; support for tag deletion is requested in goharbor/harbor#24213. On a Harbor destination the ImageMirror is the only writer of, set cleanup.deleteByDigest: true: kuik then deletes manifests by digest, which Harbor accepts. On a Harbor destination other clusters, other ImageMirrors or other tools write to, deleting by digest removes their tags too, see Deleting by digest: set cleanup.enabled: false there and use Harbor’s tag retention rules. Both setups are described in Harbor as an ImageMirror destination.
  • No drift detection: an ImageMonitor does not tell when a tag moves upstream under the pods that run it, since Kubernetes exposes no reliable way to know which digest a container runs (kubernetes#115199). An ImageMirror under driftPolicy: Warn tells when a copied tag moves, see the ImageMonitor reference.
  • One verdict per image, whatever the transport: the check of an image serves every ImageMonitor and every ImageMirror drift check that tracks it, though an origin’s transport depends on the pods that declare it. When an ImageAlternative with selectors declares an origin insecure for the pods of one monitor and not for those of another, both report the verdict of whichever checked last, over plain HTTP or HTTPS. Give such an ImageAlternative selectors that cover every pod declaring the origin, see the ImageMonitor reference.
  • Retention after a restart: an image whose last pod goes away while no reconciler runs (restart, leader change) is not retained by an ImageMonitor, see the ImageMonitor reference.
  • Node runtime: the tls key and insecure: true configure kuik only: configure the nodes’ container runtime for the same hosts, or pods fail to pull, see Registry TLS.
  • Request interval and check timeout: kuik does not check that check.timeout leaves room for requestInterval: a too large interval makes every check of that host time out as Unreachable. Give a paced host a check.timeout of at least 6 times its requestInterval per credential tried, see Spacing the requests.