|
| 1 | +--- |
| 2 | +layout: blog |
| 3 | +title: "Kubernetes 1.31: Read Only Volumes Based On OCI Artifacts (alpha)" |
| 4 | +date: 2024-08-16 |
| 5 | +slug: kubernetes-1-31-image-volume-source |
| 6 | +author: Sascha Grunert |
| 7 | +--- |
| 8 | + |
| 9 | +The Kubernetes community is moving towards fulfilling more Artificial |
| 10 | +Intelligence (AI) and Machine Learning (ML) use cases in the future. While the |
| 11 | +project has been designed to fulfill microservice architectures in the past, |
| 12 | +it’s now time to listen to the end users and introduce features which have a |
| 13 | +stronger focus on AI/ML. |
| 14 | + |
| 15 | +One of these requirements is to support [Open Container Initiative (OCI)](https://opencontainers.org) |
| 16 | +compatible images and artifacts (referred as OCI objects) directly as a native |
| 17 | +volume source. This allows users to focus on OCI standards as well as enables |
| 18 | +them to store and distribute any content using OCI registries. A feature like |
| 19 | +this gives the Kubernetes project a chance to grow into use cases which go |
| 20 | +beyond running particular images. |
| 21 | + |
| 22 | +Given that, the Kubernetes community is proud to present a new alpha feature |
| 23 | +introduced in v1.31: The Image Volume Source |
| 24 | +([KEP-4639](https://kep.k8s.io/4639)). This feature allows users to specify an |
| 25 | +image reference as volume in a pod while reusing it as volume mount within |
| 26 | +containers: |
| 27 | + |
| 28 | +```yaml |
| 29 | +… |
| 30 | +kind: Pod |
| 31 | +spec: |
| 32 | + containers: |
| 33 | + - … |
| 34 | + volumeMounts: |
| 35 | + - name: my-volume |
| 36 | + mountPath: /path/to/directory |
| 37 | + volumes: |
| 38 | + - name: my-volume |
| 39 | + image: |
| 40 | + reference: my-image:tag |
| 41 | +``` |
| 42 | +
|
| 43 | +The above example would result in mounting `my-image:tag` to |
| 44 | +`/path/to/directory` in the pod’s container. |
| 45 | + |
| 46 | +## Use cases |
| 47 | + |
| 48 | +The goal of this enhancement is to stick as close as possible to the existing |
| 49 | +[container image](/docs/concepts/containers/images/) implementation within the |
| 50 | +kubelet, while introducing a new API surface to allow more extended use cases. |
| 51 | + |
| 52 | +For example, users could share a configuration file among multiple containers in |
| 53 | +a pod without including the file in the main image, so that they can minimize |
| 54 | +security risks and the overall image size. They can also package and distribute |
| 55 | +binary artifacts using OCI images and mount them directly into Kubernetes pods, |
| 56 | +so that they can streamline their CI/CD pipeline as an example. |
| 57 | + |
| 58 | +Data scientists, MLOps engineers, or AI developers, can mount large language |
| 59 | +model weights or machine learning model weights in a pod alongside a |
| 60 | +model-server, so that they can efficiently serve them without including them in |
| 61 | +the model-server container image. They can package these in an OCI object to |
| 62 | +take advantage of OCI distribution and ensure efficient model deployment. This |
| 63 | +allows them to separate the model specifications/content from the executables |
| 64 | +that process them. |
| 65 | + |
| 66 | +Another use case is that security engineers can use a public image for a malware |
| 67 | +scanner and mount in a volume of private (commercial) malware signatures, so |
| 68 | +that they can load those signatures without baking their own combined image |
| 69 | +(which might not be allowed by the copyright on the public image). Those files |
| 70 | +work regardless of the OS or version of the scanner software. |
| 71 | + |
| 72 | +But in the long term it will be up to **you** as an end user of this project to |
| 73 | +outline further important use cases for the new feature. |
| 74 | +[SIG Node](https://github.com/kubernetes/community/blob/54a67f5/sig-node/README.md) |
| 75 | +is happy to retrieve any feedback or suggestions for further enhancements to |
| 76 | +allow more advanced usage scenarios. Feel free to provide feedback by either |
| 77 | +using the [Kubernetes Slack (#sig-node)](https://kubernetes.slack.com/messages/sig-node) |
| 78 | +channel or the [SIG Node mailinglist](https://groups.google.com/g/kubernetes-sig-node). |
| 79 | + |
| 80 | +## Detailed example {#example} |
| 81 | + |
| 82 | +The Kubernetes alpha feature gate [`ImageVolume`](/docs/reference/command-line-tools-reference/feature-gates) |
| 83 | +needs to be enabled on the [API Server](/docs/reference/command-line-tools-reference/kube-apiserver) |
| 84 | +as well as the [kubelet](/docs/reference/command-line-tools-reference/kubelet) |
| 85 | +to make it functional. If that’s the case and the [container runtime](/docs/setup/production-environment/container-runtimes) |
| 86 | +has support for the feature (like CRI-O ≥ v1.31), then an example `pod.yaml` |
| 87 | +like this can be created: |
| 88 | + |
| 89 | +```yaml |
| 90 | +apiVersion: v1 |
| 91 | +kind: Pod |
| 92 | +metadata: |
| 93 | + name: pod |
| 94 | +spec: |
| 95 | + containers: |
| 96 | + - name: test |
| 97 | + image: registry.k8s.io/e2e-test-images/echoserver:2.3 |
| 98 | + volumeMounts: |
| 99 | + - name: volume |
| 100 | + mountPath: /volume |
| 101 | + volumes: |
| 102 | + - name: volume |
| 103 | + image: |
| 104 | + reference: quay.io/crio/artifact:v1 |
| 105 | + pullPolicy: IfNotPresent |
| 106 | +``` |
| 107 | + |
| 108 | +The pod declares a new volume using the `image.reference` of |
| 109 | +`quay.io/crio/artifact:v1`, which refers to an OCI object containing two files. |
| 110 | +The `pullPolicy` behaves in the same way as for container images and allows the |
| 111 | +following values: |
| 112 | + |
| 113 | +- `Always`: the kubelet always attempts to pull the reference and the container |
| 114 | + creation will fail if the pull fails. |
| 115 | +- `Never`: the kubelet never pulls the reference and only uses a local image or |
| 116 | + artifact. The container creation will fail if the reference isn’t present. |
| 117 | +- `IfNotPresent`: the kubelet pulls if the reference isn’t already present on |
| 118 | + disk. The container creation will fail if the reference isn’t present and the |
| 119 | + pull fails. |
| 120 | + |
| 121 | +The `volumeMounts` field is indicating that the container with the name `test` |
| 122 | +should mount the volume under the path `/volume`. |
| 123 | + |
| 124 | +If you now create the pod: |
| 125 | + |
| 126 | +```shell |
| 127 | +kubectl apply -f pod.yaml |
| 128 | +``` |
| 129 | + |
| 130 | +And exec into it: |
| 131 | + |
| 132 | +```shell |
| 133 | +kubectl exec -it pod -- sh |
| 134 | +``` |
| 135 | + |
| 136 | +Then you’re able to investigate what has been mounted: |
| 137 | + |
| 138 | +```console |
| 139 | +/ # ls /volume |
| 140 | +dir file |
| 141 | +/ # cat /volume/file |
| 142 | +2 |
| 143 | +/ # ls /volume/dir |
| 144 | +file |
| 145 | +/ # cat /volume/dir/file |
| 146 | +1 |
| 147 | +``` |
| 148 | + |
| 149 | +**You managed to consume an OCI artifact using Kubernetes!** |
| 150 | + |
| 151 | +The container runtime pulls the image (or artifact), mounts it to the |
| 152 | +container and makes it finally available for direct usage. There are a bunch of |
| 153 | +details in the implementation, which closely align to the existing image pull |
| 154 | +behavior of the kubelet. For example: |
| 155 | + |
| 156 | +- If a `:latest` tag as `reference` is provided, then the `pullPolicy` will |
| 157 | + default to `Always`, while in any other case it will default to `IfNotPresent` |
| 158 | + if unset. |
| 159 | +- The volume gets re-resolved if the pod gets deleted and recreated, which means |
| 160 | + that new remote content will become available on pod recreation. A failure to |
| 161 | + resolve or pull the image during pod startup will block containers from |
| 162 | + starting and may add significant latency. Failures will be retried using |
| 163 | + normal volume backoff and will be reported on the pod reason and message. |
| 164 | +- Pull secrets will be assembled in the same way as for the container image by |
| 165 | + looking up node credentials, service account image pull secrets, and pod spec |
| 166 | + image pull secrets. |
| 167 | +- The OCI object gets mounted in a single directory by merging the manifest |
| 168 | + layers in the same way as for container images. |
| 169 | +- The volume is mounted as read-only (`ro`) and non-executable files |
| 170 | + (`noexec`). |
| 171 | +- Sub-path mounts for containers are not supported |
| 172 | + (`spec.containers[*].volumeMounts.subpath`). |
| 173 | +- The field `spec.securityContext.fsGroupChangePolicy` has no effect on this |
| 174 | + volume type. |
| 175 | +- The feature will also work with the [`AlwaysPullImages` admission plugin](/docs/reference/access-authn-authz/admission-controllers/#alwayspullimages) |
| 176 | + if enabled. |
| 177 | + |
| 178 | +Thank you for reading through the end of this blog post! SIG Node is proud and |
| 179 | +happy to deliver this feature as part of Kubernetes v1.31. |
| 180 | + |
| 181 | +As writer of this blog post, I would like to emphasize my special thanks to |
| 182 | +**all** involved individuals out there! You all rock, let’s keep on hacking! |
| 183 | + |
| 184 | +## Further reading |
| 185 | + |
| 186 | +- [Use an Image Volume With a Pod](/docs/tasks/configure-pod-container/image-volumes) |
| 187 | +- [`image` volume overview](/docs/concepts/storage/volumes/#image) |
0 commit comments