I'm looking for a pattern that allows to share volumes between two containers running on the same pod in Kubernetes.
My use case is: I have a Ruby on Rails application running inside a docker container. The docker image contains static assets in /app/<app-name>/public
directory, and I need to access those assets from the nginx container running alongside in the same pod.
In 'vanilla' docker I would have used --volumes-from
flag to share this directory:
docker run --name app -v /app/<app-dir>/public <app-image> docker run --volumes-from app nginx
After reading this doc: https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md I tried this (only relevant entries presented):
spec: containers: - image: <app-image> name: <app-name> volumeMounts: - mountPath: /app/<app-name>/public name: assets - image: nginx name: nginx volumeMounts: - mountPath: /var/www/html name: assets readOnly: true volumes: - name: assets hostPath: path: /tmp/assets
But:
/tmp/assets
on the node exists, it's empty/app/<app-name>/public
inside the app container is also emptyAs a workaround I'm gonna try to populate the shared directory when the application container is up (simply cp /app/<app-name>/public/*
to shared directory), but I really dislike this idea.
Question: how to mimic --volumes-from
in Kubernetes, or if there is no direct counterpart, how can I share files from one container to other running in the same pod ?
apiVersion: v1beta3
Client Version: version.Info{Major:"0", Minor:"17", GitVersion:"v0.17.0", GitCommit:"82f8bdac06ddfacf493a9ed0fedc85f5ea62ebd5", GitTreeState:"clean"} Server Version: version.Info{Major:"0", Minor:"17", GitVersion:"v0.17.0", GitCommit:"82f8bdac06ddfacf493a9ed0fedc85f5ea62ebd5", GitTreeState:"clean"}
You can get the volumes mounted on the pod using the output of kubectl describe pod which has the Mounts section in each container's spec . You can then exec into the pod using kubectl exec and the cd to the directory you want to write data to.
The Kubernetes emptyDir is defined as, the emptyDir in Kubernetes are volumes that can obtain empty when a pod is generated, the pod is running in its emptyDir which it exists, if the container in a pod has collision the emptyDir then the content of them will not get affected, if we try to delete a pod, then it can ...
For any kind of volume in a given pod, data is preserved across container restarts. At its core, a volume is a directory, possibly with some data in it, which is accessible to the containers in a pod.
A Volume in Kubernetes represents a directory with data that is accessible across multiple containers in a Pod. The container data in a Pod is deleted or lost when a container crashes or restarts, but when you use a volume, the new container can pick up the data at the state before the container crashes.
[update-2016-8] In latest Kubernetes release, you can use a very nice feature named init-container
to replace the postStart
part in my answer below, which will make sure the container order.
apiVersion: v1 kind: Pod metadata: name: javaweb-2 spec: initContainers: - name: war image: resouer/sample:v2 command: ["cp", "/sample.war", "/app"] volumeMounts: - mountPath: /app name: app-volume containers: - name: tomcat image: resouer/mytomcat:7.0 command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"] volumeMounts: - mountPath: /root/apache-tomcat-7.0.42-v2/webapps name: app-volume ports: - containerPort: 8080 hostPort: 8001 volumes: - name: app-volume emptyDir: {}
NOTE: initContainer is still a beta feature so the work version of this yaml is actually like: http://kubernetes.io/docs/user-guide/production-pods/#handling-initialization, please notice the pod.beta.kubernetes.io/init-containers
part.
---original answer begin---
Actually, you can. You need to use container life cycle handler to control what files/dirs you want to share with other containers. Like:
--- apiVersion: v1 kind: Pod metadata: name: server spec: restartPolicy: OnFailure containers: - image: resouer/sample:v2 name: war lifecycle: postStart: exec: command: - "cp" - "/sample.war" - "/app" volumeMounts: - mountPath: /app name: hostv1 - name: peer image: busybox command: ["tail", "-f", "/dev/null"] volumeMounts: - name: hostv2 mountPath: /app/sample.war volumes: - name: hostv1 hostPath: path: /tmp - name: hostv2 hostPath: path: /tmp/sample.war
Please check my gist for more details:
https://gist.github.com/resouer/378bcdaef1d9601ed6aa
And of course you can use emptyDir. Thus, war container can share its /sample.war to peer container without mess peer's /app directory.
If we can tolerate /app been overridden, it will be much simpler:
--- apiVersion: v1 kind: Pod metadata: name: javaweb-2 spec: restartPolicy: OnFailure containers: - image: resouer/sample:v2 name: war lifecycle: postStart: exec: command: - "cp" - "/sample.war" - "/app" volumeMounts: - mountPath: /app name: app-volume - image: resouer/mytomcat:7.0 name: tomcat command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"] volumeMounts: - mountPath: /root/apache-tomcat-7.0.42-v2/webapps name: app-volume ports: - containerPort: 8080 hostPort: 8001 volumes: - name: app-volume emptyDir: {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With