kbld - digest reference to container image
Let’s imagine the situation when the deployment Kubernetes manifest is referencing the latest image tag of third-party software like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Then you made a static analysis of that manifest and in the result you get:
$ datree test deployment.yaml
...
❌ Ensure each container image has a pinned (tag) version [1 occurrence]
- metadata.name: nginx-deployment (kind: Deployment)
> key: spec.template.spec.containers.0.image (line: 17:16)
💡 Incorrect value for key `image` - specify an image version to avoid unpleasant "version surprises" in the future
...
It’s undoubtedly a valid point, but as I mentioned before I cannot change the image build process and get the “right” tags. How can we avoid this unpleasant version surprise?
A long long time ago docker decide to abandon its own mechanism of image IDs
by migrating it to a secure SHA256 checksum. It brings some benefits because each image layer get its own unique SHA256
checksum (the same like commit id in git) and can be shared between completely different images. The image tag becomes
some kind of pointer pointing to the selected SHA256 checksum. So there is a question of what is happening when we
change pointer latest
to a different checksum, does the previous checksum will be removed aka can I reuse it ?
Now to the play comes tools kbld, it’s a part of a bigger project called
carvel which again it’s a part of VMware Tanzu - a modern application approach including
the platform Kubernetes and tools above it. kbld
is responsible for building images using different building platforms
(docker, ko, bazel) and resolving image digest from the tag. The second feature is what are we looking for, we want to
stick our deployment with the exact image version:
$ kbld -f /tmp/pod.yaml
resolve | final: nginx:latest -> index.docker.io/library/nginx@sha256:2f770d2fe27bc85f68fd7fe6a63900ef7076bc703022fe81b980377fe3d27b70
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kbld.k14s.io/images: |
- origins:
- resolved:
tag: latest
url: nginx:latest
url: index.docker.io/library/nginx@sha256:2f770d2fe27bc85f68fd7fe6a63900ef7076bc703022fe81b980377fe3d27b70
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: index.docker.io/library/nginx@sha256:2f770d2fe27bc85f68fd7fe6a63900ef7076bc703022fe81b980377fe3d27b70
name: nginx
ports:
- containerPort: 80
Succeeded
Every time you run your app you will get the same version of it. AFAIK docker hub is not doing garbage collection so each image digest should be kept. A similar approach is taken in ArgoCD when you decide to combine it with Image Updater it’s called the digest update strategy.
powered by Hugo and Noteworthy theme