|
| 1 | +# kube-image-keeper (kuik) |
| 2 | + |
| 3 | +[](https://github.com/enix/kube-image-keeper/releases) |
| 4 | +[](https://goreportcard.com/report/github.com/enix/kube-image-keeper) |
| 5 | +[](https://opensource.org/licenses/MIT) |
| 6 | +[](https://enix.io) |
| 7 | + |
| 8 | +**kuik** (pronounced /kwɪk/, like "quick") is the shortname of **kube-image-keeper**, a container image routing, caching and monitoring system for Kubernetes developed by Enix. It helps make applications more highly available by ensuring reliable access to container images. |
| 9 | + |
| 10 | +> [!NOTE] |
| 11 | +> This is a complete ground-up rewrite of the project — introducing a new design, new architecture, and improved observability. |
| 12 | +
|
| 13 | +## 🧪 Status: Beta |
| 14 | + |
| 15 | +> [!WARNING] |
| 16 | +> v2 is currently in **Beta**. Expect breaking changes and limited functionality as we iterate. |
| 17 | +
|
| 18 | +Feedback is welcome – open an issue or start a discussion. |
| 19 | + |
| 20 | +> [!CAUTION] |
| 21 | +> Not recommended for production use yet. |
| 22 | +
|
| 23 | +Production environments should continue using the stable v1 release available in the same repository until v2 reaches general availability. |
| 24 | + |
| 25 | +## 🤷 Why Version 2? |
| 26 | + |
| 27 | +Even if we are _proud_ of what we achieved with the v1 of **kube-image-keeper**, it was too often painful to work with: it was hard to deploy, overly complex, and the image caching feature — while ambitious — introduced often too much issues. We missed our original goal: to make kube-image-keeper an **easy, no-brainer install for any cluster** which would help ops in their day to day work and **provide confidence**. |
| 28 | + |
| 29 | +We learnt _a lot_ from this experience and with v2, **_we're starting fresh!_** Our focus is on **simplicity** and **observability** first. Caching is no longer the core feature — it will return later as an opt-in, second-class citizen. This reboot is about doing **_one thing well_**: giving clear visibility into what images are used, where, and how. |
| 30 | + |
| 31 | +## ✨ What's New in v2 |
| 32 | + |
| 33 | +kuik v2 is a **complete rewrite** of the project with a focus on **simplicity** and **ease of use**. |
| 34 | + |
| 35 | +### 🔍 Redesigned Architecture |
| 36 | + |
| 37 | +- **Minimal default features**: core functionality enabled by default, others opt-in |
| 38 | +- **Redesigned CRDs** for better clarity and extensibility |
| 39 | +- **Image routing**: kuik can rewrite Pod images on-the-fly to point to an operational registry |
| 40 | +- **Image replication**: kuik can manage copy between registries to create a virtual highly available registry |
| 41 | +- **Image monitoring**: kuik can monitor image availability across various registries |
| 42 | + |
| 43 | +## 🚧 Roadmap |
| 44 | + |
| 45 | +Planned features (subject to change): |
| 46 | + |
| 47 | +- Routing, Replication and Monitoring should be implemented and available as Beta in November |
| 48 | +- Further refinement will occur by the end of the year (2025). |
| 49 | +- General Availability should occur by December 2025 / January 2026. |
| 50 | +- We expect to communicate the launch of the v2 at the [Cloud Native Days France 2026 convention](https://www.cloudnativedays.fr/) |
| 51 | + |
| 52 | +## 📦 Installation |
| 53 | + |
| 54 | +```bash |
| 55 | +kubectl create namespace kuik-system |
| 56 | +VERSION=2.0.0-beta.X # Latest available beta version |
| 57 | +helm upgrade --install --namespace kuik-system kube-image-keeper oci://quay.io/enix/charts/kube-image-keeper:$VERSION |
| 58 | +``` |
| 59 | + |
| 60 | +## Values |
| 61 | + |
| 62 | +| Key | Type | Default | Description | |
| 63 | +|-----|------|---------|-------------| |
| 64 | +| configuration.monitoring.enabled | bool | `true` | | |
| 65 | +| configuration.routing.activeCheck.enabled | bool | `true` | | |
| 66 | +| configuration.routing.activeCheck.timeout | string | `"1s"` | | |
| 67 | +| configuration.routing.strategies | list | `[]` | | |
| 68 | +| manager.affinity | object | `{}` | Affinity for the manager pod | |
| 69 | +| manager.env | list | `[]` | Extra env variables for the manager pod | |
| 70 | +| manager.image.pullPolicy | string | `"IfNotPresent"` | Manager image pull policy | |
| 71 | +| manager.image.repository | string | `"quay.io/enix/kube-image-keeper"` | Manager image repository | |
| 72 | +| manager.image.tag | string | `""` | Manager image tag. Default chart appVersion | |
| 73 | +| manager.imagePullSecrets | list | `[]` | Specify secrets to be used when pulling manager image | |
| 74 | +| manager.livenessProbe | object | `{"httpGet":{"path":"/healthz","port":8081}}` | Liveness probe definition for the manager pod | |
| 75 | +| manager.nodeSelector | object | `{}` | Node selector for the manager pod | |
| 76 | +| manager.pdb.create | bool | `false` | Create a PodDisruptionBudget for the manager pod | |
| 77 | +| manager.pdb.maxUnavailable | string | `""` | Maximum unavailable pods | |
| 78 | +| manager.pdb.minAvailable | int | `1` | Minimum available pods | |
| 79 | +| manager.podAnnotations | object | `{}` | Annotations to add to the manager pod | |
| 80 | +| manager.podSecurityContext | object | `{}` | Security context for the manager pod | |
| 81 | +| manager.priorityClassName | string | `""` | Set the PriorityClassName for the manager pod | |
| 82 | +| manager.readinessProbe | object | `{"httpGet":{"path":"/readyz","port":8081}}` | Readiness probe definition for the manager pod | |
| 83 | +| manager.replicas | int | `1` | Number of manager pods | |
| 84 | +| manager.resources.limits.cpu | string | `"1"` | Cpu limits for the manager pod | |
| 85 | +| manager.resources.limits.memory | string | `"512Mi"` | Memory limits for the manager pod | |
| 86 | +| manager.resources.requests.cpu | string | `"50m"` | Cpu requests for the manager pod | |
| 87 | +| manager.resources.requests.memory | string | `"50Mi"` | Memory requests for the manager pod | |
| 88 | +| manager.securityContext | object | `{}` | Security context for containers of the manager pod | |
| 89 | +| manager.serviceMonitor.create | bool | `false` | Should a ServiceMonitor object be installed to scrape kuik manager metrics. For prometheus-operator (kube-prometheus) users. | |
| 90 | +| manager.serviceMonitor.extraLabels | object | `{}` | Additional labels to add to ServiceMonitor objects | |
| 91 | +| manager.serviceMonitor.relabelings | list | `[]` | Relabel config for the ServiceMonitor, see: https://coreos.com/operators/prometheus/docs/latest/api.html#relabelconfig | |
| 92 | +| manager.serviceMonitor.scrapeInterval | string | `"60s"` | Target scrape interval set in the ServiceMonitor | |
| 93 | +| manager.serviceMonitor.scrapeTimeout | string | `"30s"` | Target scrape timeout set in the ServiceMonitor | |
| 94 | +| manager.tolerations | list | `[]` | Toleration for the manager pod | |
| 95 | +| manager.verbosity | string | `"INFO"` | Manager logging verbosity | |
| 96 | +| manager.webhook.certificateIssuerRef | object | `{"kind":"Issuer","name":"kube-image-keeper-selfsigned-issuer"}` | Issuer reference to issue the webhook certificate, ignored if createCertificateIssuer is true | |
| 97 | +| manager.webhook.createCertificateIssuer | bool | `true` | If true, create the issuer used to issue the webhook certificate | |
| 98 | +| metrics.imageLastMonitorAgeMinutesBuckets.custom | list | `[10,30,60,120,180,360,1440]` | List of buckets to create in minutes, ommiting +inf | |
| 99 | +| metrics.imageLastMonitorAgeMinutesBuckets.exponential | object | `{"count":12,"factor":1.5,"start":15}` | Range from 15m to 1297m (21h) (start*factor^count) See https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#ExponentialBuckets | |
| 100 | +| metrics.imageLastMonitorAgeMinutesBuckets.exponential.start | int | `15` | Default is 15m | |
| 101 | +| metrics.imageLastMonitorAgeMinutesBuckets.exponentialRange | object | `{"count":12,"max":1000,"min":15}` | See https://pkg.go.dev/github.com/prometheus/client_golang/prometheus#ExponentialBucketsRange | |
| 102 | +| metrics.imageLastMonitorAgeMinutesBuckets.type | string | `"exponentialRange"` | Bucket generation method (can be one of exponential, exponentialRange or custom) | |
| 103 | +| rbac.create | bool | `true` | Create the ClusterRole and ClusterRoleBinding. If false, need to associate permissions with serviceAccount outside this Helm chart. | |
| 104 | +| registryMonitors.defaultSpec.interval | string | `"3h"` | Time window during which maxPerInterval limits the number of monitoring tasks. (e.g., 6h, 30m) | |
| 105 | +| registryMonitors.defaultSpec.maxPerInterval | int | `25` | Maximum monitoring tasks to run in the given interval and for a given registry. | |
| 106 | +| registryMonitors.defaultSpec.method | string | `"HEAD"` | HTTP method to use to monitor an image of this registry | |
| 107 | +| registryMonitors.defaultSpec.parallel | int | `1` | Maximum monitoring tasks to run in parallel for a given registry. | |
| 108 | +| registryMonitors.defaultSpec.timeout | string | `"30s"` | Maximum duration of a monitoring task | |
| 109 | +| registryMonitors.items | object | `{"docker.io":{"interval":"1h","maxPerInterval":2},"public.ecr.aws":{"interval":"1h","maxPerInterval":2}}` | RegistryMonitors to create on install and upgrade, if name is not provided, defaults to registry value. | |
| 110 | +| serviceAccount.annotations | object | `{}` | Annotations to add to the serviceAccount | |
| 111 | +| serviceAccount.create | bool | `true` | Create the serviceAccount. If false, use serviceAccount with specified name (or "default" if false and name unset.) | |
| 112 | +| serviceAccount.extraLabels | object | `{}` | Additional labels to add to the serviceAccount | |
| 113 | +| serviceAccount.name | string | `""` | Name of the serviceAccount (auto-generated if unset and create is true) | |
| 114 | +| unusedImageTTL | int | `24` | Delay in hours before deleting an Image that is not used by any pod | |
| 115 | + |
| 116 | +## License |
| 117 | + |
| 118 | +MIT License |
| 119 | + |
| 120 | +Copyright (c) 2020-2025 Enix SAS |
| 121 | + |
| 122 | +Permission is hereby granted, free of charge, to any person obtaining a copy |
| 123 | +of this software and associated documentation files (the "Software"), to deal |
| 124 | +in the Software without restriction, including without limitation the rights |
| 125 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 126 | +copies of the Software, and to permit persons to whom the Software is |
| 127 | +furnished to do so, subject to the following conditions: |
| 128 | + |
| 129 | +The above copyright notice and this permission notice shall be included in all |
| 130 | +copies or substantial portions of the Software. |
| 131 | + |
| 132 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 133 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 134 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 135 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 136 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 137 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 138 | +SOFTWARE. |
0 commit comments