A gate is not a schedule¶
Post — Kubernetes 1.31: Read Only Volumes Based On OCI Artifacts (alpha), 2024-08-16, Kubernetes v1.31.
As written — a new alpha volume source, KEP-4639. Put an image reference where a volume goes and mount it:
kind: Pod
spec:
containers:
- volumeMounts:
- name: my-volume
mountPath: /path/to/directory
volumes:
- name: my-volume
image:
reference: my-image:tag
The framing is explicit about why: Kubernetes was designed for microservices and is now being
asked to serve AI/ML, where you want to ship a model or a dataset as an OCI artifact rather than
bake it into the application image. Alpha in v1.31, so you enable the ImageVolume feature gate
and try it.
As it runs now — it works with no gate to enable. The field is unconditional, and two things
about the shape have changed since the post: subPath and subPathExpr mounts on an image
volume are supported (from v1.33), and there is a new alpha gate, ImageVolumeWithDigest,
adding the resolved image digest to the Pod's status.
So nothing broke, nothing was withdrawn, and a reader following the post today would succeed — and would still have learned the wrong lesson, because the interesting part of this post is the sentence it does not contain.
The diff, and why — here is the ladder ImageVolume actually climbed, from the feature-gate
reference at the pin:
| stage | default | releases |
|---|---|---|
| alpha | false |
v1.31 – v1.32 |
| beta | false |
v1.33 – v1.34 |
| beta | true |
v1.35 |
| stable | true |
v1.36 – |
Five releases, four stage changes, and the step that matters is the second one: beta with the
gate still off by default, for two releases. "Graduates to beta" is read as "on unless you
turn it off" — that is what beta has meant for most features for most of Kubernetes' life — and
for ImageVolume in v1.33 and v1.34 it was false. A cluster on v1.34 that had read a
"now in beta" post would have had a Pod with an image volume start, mount nothing where the
volume should be, and never say why.
Compare a feature from the same year, announced four months earlier: RecursiveReadOnlyMounts
went alpha in v1.30, beta-and-on in v1.31, and stable-and-locked in v1.33 — three releases, no
off-by-default beta, done in eighteen months.
Two features, one year, both shipped by SIG Node, and their graduations share no shape at all.
That is the lesson: a feature gate records a decision that was made, not a schedule that will
be kept. The stage tells you what the project currently promises about an API's stability. It
tells you nothing about the default, nothing about the date, and nothing about whether the next
step is up. ImageVolume needed CRI work in both containerd and CRI-O before the default could
flip, and that is why it sat in beta-off — a fact you can only get from the ladder, never from
the announcement.
This is the shape of a 2024 diff. In 2015 the diff is that the commands are
gone; here the commands are fine and the diff is in the trajectory — which is why the census
records a version for every row and why a walk verdict on a still-working post is not a
contradiction.
Topology — solo. Bring it up with
the five provision steps, substituting
topology=solo, then ssh zain@10.10.10.180.
Do
- Do not look up whether the gate is still there — ask the cluster, and record whatever you get, including nothing:
- Run the post's example unmodified, with no gate set anywhere. Use an image whose contents you can recognise:
cat <<'YAML' | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: img
spec:
containers:
- name: c
image: busybox
command: ["sh", "-c", "sleep 3600"]
volumeMounts:
- name: vol
mountPath: /mnt/artifact
volumes:
- name: vol
image:
reference: busybox:1.36
pullPolicy: IfNotPresent
YAML
kubectl exec img -- ls /mnt/artifact
-
Establish that it is a volume and not a second container: write to it.
kubectl exec img -- touch /mnt/artifact/x. -
Test the failure mode the docs describe, which is the one that will bite in production. Delete the pod, then re-apply it with
reference: registry.example.invalid/nope:v1andpullPolicy: Never.kubectl get pod imgandkubectl describe pod img. -
Now the archaeology, which is the point. Reconstruct the ladder yourself from the pinned website tree —
content/en/docs/reference/command-line-tools-reference/feature-gates/— readingImageVolume.mdbesideRecursiveReadOnlyMounts.md. Two questions to answer in writing: which of the two islocked: trueat stable and what that changes for a cluster operator, and what a "beta" badge is worth as a prediction given these two ladders. -
ImageVolumeWithDigestis alpha at the pin — a new gate on a feature that already went stable. Read its file and work out why the digest could not simply have been added to the status when the feature graduated.
Expect — step 2 succeeds. No gate, no --feature-gates, no kubelet config: the volume mounts
and ls lists the busybox root filesystem. Step 3 fails read-only — the mount is not writable
and no field makes it writable.
Step 4 is the failure you should be able to recognise later: the Pod does not schedule-then-crash
and it does not report a missing volume. It goes to Failed, and the reason is on the Pod, not
on the container — volume resolution happens at Pod startup, so the container never runs at all.
That is a better failure than the silent empty mount a v1.34 cluster would have given you, and
noticing the difference is the exercise.
Step 5 is where the year's real lesson lands. Write down the sentence you would now add to the original post, in 2024, that would have made it honest about what "alpha" was promising.
Read on — KEP-4639:
find the kep.yaml milestones and compare them to the ladder in step 5. Where the two disagree,
which one happened?
Teardown — kubectl delete pod img --ignore-not-found. Leave the guest up; a later exercise
in this year reuses it.