Итак, каковы различные решения этой проблемы? А какой самый лучший?
Лучшее решение уже предоставлено @PaulProgrammer, и пока нет противопоказаний, вам следует сделать подключаемые модули приложения неотъемлемой частью образа docker. Доводы в пользу таких решений уже хорошо объяснил @Matt:
Однако я бы сделал копию только в сборке образа контейнера. Это означает, что у вас всегда есть полный, воспроизводимый артефакт того, что работает. – Мэтт
Я полностью с этим согласен и также настоятельно рекомендую вам пересобрать образ докера, а не решать эту проблему на уровне kubernetes.
Однако, чтобы сделать эту тему полной и дать вам ответы на ваши дополнительные вопросы и развеять все возможные сомнения, я хотел бы добавить несколько слов к тому, что уже было написано.
Хочу еще раз подчеркнуть, что это не оптимальное решение, но с технической точки зрения это также возможно сделать с помощью init-контейнеров в kubernetes. Кроме того, я даже попытаюсь объяснить, почему это не лучшее решение или, точнее, почему оно неприменимо в вашем конкретном случае использования.
Как я могу это сделать? Полезен ли initContainers в таких случаях? Имеет ли init-контейнер доступ к файловой системе контейнера приложений, чтобы можно было выполнить приведенную выше команду? Я попытался использовать busybox в initContainers и запустил ls -lR /opt/myapp, чтобы посмотреть, существует ли вообще такой путь. Но похоже, что у контейнера инициализации нет доступа к файловой системе приложения.
Имейте в виду, что контейнеры инициализации всегда запускаются до запуска контейнеров приложений, и они не могут изменить исходную файловую систему контейнера приложений, как в случае запустить его еще даже не существует. Однако их можно использовать для предварительного заполнения дополнительного тома, который впоследствии можно смонтировать в контейнере приложения. Посмотрите на пример ниже:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 1
selector:
matchLabels:
app: debian
template:
metadata:
labels:
app: debian
spec:
containers:
- name: debian
image: debian
command: ['sh', '-c', 'sleep 3600']
volumeMounts:
- mountPath: "/app/data"
name: my-volume
readOnly: true
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: example-pvc
initContainers:
- name: init-myservice
image: busybox
command: ['sh', '-c', 'echo "Content of my file" > /mnt/my_file']
volumeMounts:
- mountPath: "/mnt"
name: my-volume
В этом примере мы заполняем каталог /app/data
контейнера приложения некоторым содержимым с помощью контейнера инициализации. command
здесь не так важно. Это может быть что угодно: от получения некоторого контента с помощью wget до клонирования репозитория git или scp некоторого контента с удаленного сервера. Обратите внимание, что вы не можете добавить таким образом дополнительный контент к уже существующему. Если каталог уже существовал и в нем уже был какой-то контент, он стирается и заполняется новым. На самом деле это не с технической точки зрения. Каталог используется как новая точка подключения для другого тома. Поскольку теперь он указывает на другой диск и его содержимое, исходное содержимое каталога больше недоступно с нашей точки зрения.
Каков типичный сценарий использования? Чем это может быть полезно?
Если вашему приложению нужны данные для обработки, вы обычно не хотите делать их неотъемлемой частью вашего образа Docker. Представьте, что он довольно часто меняется и вам всегда нужно скачивать его самую последнюю версию. Таким образом, вам не придется каждый раз беспокоиться о восстановлении изображений.
Но это не применимо в вашем случае. Во-первых, потому что вам нужно добавить некоторые данные (дополнительные плагины) к чему-то, что уже является неотъемлемой частью образа контейнера вашего приложения. В этой ситуации контейнеры инициализации не очень помогут. Во-вторых, вам скорее нужно иметь последовательное, воспроизводимое изображение, содержащее все необходимые плагины.
Как я уже сказал, технически это осуществимо, так как вы можете загрузить куда-нибудь все необходимые вам плагины (включая оригинальные, которые уже присутствуют в базовом образе) и скопировать весь контент с помощью контейнера инициализации. Преимущество такого подхода в том, что он не требует от вас создания пользовательских изображений при выпуске новой версии вашего базового приложения. Вы только изменяете тег изображения, а контейнер инициализации позаботится о заполнении каталога /opt/myapp/plugins/
всеми необходимыми подключаемыми модулями и гарантирует, что он не содержит ничего, кроме них. .
Я надеюсь, что он привнес что-то новое в эту ветку и немного прояснил, в каких ситуациях стоит использовать контейнер инициализации для заполнения вашего контейнера приложения данными, а в каких — лучше придерживаться своего собственного образа Docker.
person
mario
schedule
17.03.2020