Как имитировать '-volumes-from' в Kubernetes
Я ищу шаблон, который позволяет обмениваться томами между двумя контейнерами, работающими на одном контейнере в Кубернете.
Мой вариант использования:
У меня есть приложение Ruby on Rails, запущенное внутри контейнера докеров.
Изображение docker содержит статические ресурсы в каталоге /app/<app-name>/public
, и мне нужно получить доступ к этим ресурсам из контейнера nginx, работающего рядом с тем же пакетом.
В docker 'vanilla' я бы использовал флаг --volumes-from
для совместного использования этого каталога:
docker run --name app -v /app/<app-dir>/public <app-image>
docker run --volumes-from app nginx
После прочтения этого документа: https://github.com/GoogleCloudPlatform/kubernetes/blob/master/docs/volumes.md
Я попробовал это (только соответствующие записи):
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
Но:
- Даже если
/tmp/assets
на node существует, он пуст
-
/app/<app-name>/public
внутри контейнера приложения также пуст
В качестве обходного пути я попытаюсь заполнить общий каталог, когда контейнер приложения вставлен (просто cp /app/<app-name>/public/*
в общий каталог), но мне действительно не нравится эта идея.
Вопрос: как имитировать --volumes-from
в Kubernetes, или если нет прямого аналога, как я могу обмениваться файлами из одного контейнера на другой, работающий в одном и том же контейнере?
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"}
Ответы
Ответ 1
[update-2016-8] В последнем выпуске Kubernetes вы можете использовать очень приятную функцию с именем init-container
, чтобы заменить часть postStart
в моем ответе ниже, что позволит убедиться, что контейнер.
![введите описание изображения здесь]()
ПРИМЕЧАНИЕ: initContainer по-прежнему является бета-функцией, поэтому рабочая версия этого yaml на самом деле похожа: http://kubernetes.io/docs/user-guide/production-pods/#handling-initialization, обратите внимание на часть pod.beta.kubernetes.io/init-containers
.
--- исходный ответ начинается ---
Собственно, вы можете. Вам необходимо использовать обработчик жизненного цикла контейнера для управления файлами/каталогами, которые вы хотите разделить с другими контейнерами. Как:
---
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
Пожалуйста, проверьте мои настройки для получения более подробной информации:
https://gist.github.com/resouer/378bcdaef1d9601ed6aa
И, конечно, вы можете использовать emptyDir. Таким образом, военный контейнер может делить его /sample.war на одноранговый контейнер без каталога беспорядочного peer/app.
Если мы допустим перенос /app, это будет намного проще:
---
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: {}
Ответ 2
Ответ - на данный момент - вы не можете. Здесь несколько обсуждений из проблем Кубернеса:
Однако могу ли я предположить, что у вас есть альтернативный дизайн, который может работать лучше?
- Если ваши активы заблокированы в точке, в которой собирается контейнер,
вы можете использовать что-то вроде
gitRepo
том, который скопировал бы его в emptyDir
в момент перехода в реальном времени, и будет означать, что вам не придется перемещать контент вокруг
все, просто загрузите его непосредственно в общий каталог.
- Если ваши активы заблокированы в точке контейнера
будучи построенным, вероятно, лучше всего скопировать их в тот момент, используя
команда Docker COPY.
- Если вы действительно хотите придерживаться того, как вы это делаете, вам придется скопировать содержимое в том тома
emptyDir
, который предназначен именно для того, что вы ищете (минус отсутствие необходимости скопируйте его).
Объемы NFS [1] также могут решить вашу проблему, но могут быть чрезмерно сложными.
Кроме того, я бы рекомендовал, чтобы эти две службы существовали в разных контейнерах, поэтому вы можете масштабировать их отдельно. Вы можете создать конечную точку службы для связи между ними, если вам нужно.
[1] https://github.com/GoogleCloudPlatform/kubernetes/blob/master/examples/nfs/nfs-web-pod.yaml
Ответ 3
Дальнейшее обновление из будущего:
Теперь есть плагин FlexVol для томов Docker: https://github.com/dims/docker-flexvol
Во время написания FlexVol все еще является альфа-функцией, поэтому предостерегает emptor.
Ответ 4
Если вы используете Docker v17.0.5 или выше, вы можете использовать многоступенчатую сборку для копирования файлов из одного из ваших контейнеров в другой во время сборки. Это отличный учебник по расширенным функциям по адресу https://medium.com/@tonistiigi/advanced-multi-stage-build-patterns-6f741b852fae.
То, как я использовал его для копирования статических ресурсов из моего внутреннего контейнера в прокси Nginx,
ARG API_BACKEND_CONTAINER="api:backend"
FROM $API_BACKEND_CONTAINER as source
FROM nginx:mainline-alpine
ARG NGINX_ROOT=/usr/share/nginx/html/
COPY --from=source /var/share/api/static/ ${NGINX_ROOT}
Самое замечательное то, что поскольку API_BACKEND_CONTAINER
является аргументом сборки, я могу передать тег последней сборки API.
Ответ 5
Kubernetes имеет свои собственные типы томов, и это наиболее часто используемые типы томов:
- emptyDir
- секрет
- gitRepo
- hostPath (аналогично --volumes-from)
- Конфиг Карты
- постоянное хранилище (диски хранения, предоставляемые облачными платформами)
Вы можете узнать больше о томах kubernets здесь - https://kubernetes.io/docs/concepts/storage/volumes/
Пример тома hostpath:
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
hostpath будет монтировать каталог хост/узел в каталог контейнера. Несколько контейнеров внутри модуля могут использовать разные или одинаковые тома. Вы должны указать это в каждом контейнере. Тома hostPath не зависят от жизненного цикла модуля, но создают тесную связь между узлом и модулем, поэтому следует избегать использования hostPath.