Karthikeyan Sundararajan

kubernetes-image-volumes

Kuberetes Image Volumes Feature in 1.33 (beta)

Create kind cluster

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    apiServer:
      extraArgs:
        feature-gates: "ImageVolume=true"
    controllerManager:
      extraArgs:
        feature-gates: "ImageVolume=true"
    scheduler:
      extraArgs:
        feature-gates: "ImageVolume=true"
  - |
    kind: KubeletConfiguration
    featureGates:
      ImageVolume: true
nodes:
  - role: control-plane
    extraPortMappings:
      - containerPort: 30000
        hostPort: 30000
    kubeadmConfigPatches:
      - |
        kind: InitConfiguration
        nodeRegistration:
          kubeletExtraArgs:
            feature-gates: "ImageVolume=true"
kind create cluster --config kind-imagevolume.yaml

Once the cluster is up, create a pod with multiple image references as volumes,

# build-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: build-pod
spec:
  containers:
  - name: shell
    command: ["sleep", "infinity"]
    image: debian
    volumeMounts:
    - name: jdk21
      mountPath: /jdk21
      subPath: dir
    - name: python313
      mountPath: /python313
      subPath: dir
    - name: node24
      mountPath: /node24
      subPath: dir
  volumes:
  - name: jdk21
    image:
      reference: openjdk:21
      pullPolicy: IfNotPresent
  - name: python313
    image:
      reference: python:3.13
      pullPolicy: IfNotPresent
  - name: node24
    image:
      reference: node:24
      pullPolicy: IfNotPresent
kubectl apply -f build-pod.yaml

Here are the important lines,

  - name: jdk21
    image:
      reference: openjdk:21
      pullPolicy: IfNotPresent

We are attaching a volume but it is not a PVC or a ConfigMap or Secret. It is a container image itself.

Lets get into the image and see how it looks,

k exec -it build-pod -- bash
root@build-pod:/# df -h
overlay        1007G  7.7G  948G   1% /jdk21
overlay        1007G  7.7G  948G   1% /python313
overlay        1007G  7.7G  948G   1% /node24

Great, we can see mounts as the name we specified in the volumeMount section

Lets see whats inside in one of the folder,

root@build-pod:~# cd /jdk21/
root@build-pod:/jdk21# ls -l
total 60
lrwxrwxrwx 1 root root    7 Oct  9  2021 bin -> usr/bin
dr-xr-xr-x 2 root root 4096 Oct  9  2021 boot
drwxr-xr-x 2 root root 4096 Oct  9  2021 dev
drwxr-xr-x 1 root root 4096 Sep 21  2023 etc
drwxr-xr-x 2 root root 4096 Oct  9  2021 home
lrwxrwxrwx 1 root root    7 Oct  9  2021 lib -> usr/lib
lrwxrwxrwx 1 root root    9 Oct  9  2021 lib64 -> usr/lib64
drwxr-xr-x 2 root root 4096 Oct  9  2021 media
drwxr-xr-x 2 root root 4096 Oct  9  2021 mnt
drwxr-xr-x 2 root root 4096 Oct  9  2021 opt
dr-xr-xr-x 2 root root 4096 Sep 21  2023 proc
dr-xr-x--- 1 root root 4096 Sep 21  2023 root
drwxr-xr-x 4 root root 4096 Sep 21  2023 run
lrwxrwxrwx 1 root root    8 Oct  9  2021 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Oct  9  2021 srv
dr-xr-xr-x 2 root root 4096 Sep 21  2023 sys
drwxrwxrwt 1 root root 4096 Sep 21  2023 tmp
drwxr-xr-x 1 root root 4096 Sep 21  2023 usr
drwxr-xr-x 1 root root 4096 Sep 21  2023 var

Cool, we can see the entire filesystem of the jdk21 image.

Lets try and see if we can really use it

root@build-pod:/jdk21# /jdk21/usr/java/openjdk-21/bin/java -version
openjdk version "21" 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)

We can directly use java here. Lets see if we can use node and python

root@build-pod:/node24# /node24/usr/local/bin/node --version
v24.4.1

root@build-pod:/# /python313/usr/bin/python3 --version
/python313/usr/bin/python3: error while loading shared libraries: libexpat.so.1: cannot open shared object file: No such file or directory

node is working but python isn’t. Looks like we need to set LD_LIBRARY_PATH for python to work,

root@build-pod:/node24# export LD_LIBRARY_PATH=/python313/usr/lib:/python313/usr/lib/x86_64-linux-gnu
root@build-pod:/node24# /python313/usr/bin/python3 --version
Python 3.11.2

Thats great. We can directly attach the images as volume and use it with this new feature. No more 15GB or 30GB bulk images and no more struggle of maintaining the Dockerfiles.