Стручок / развертывание Kubernetes при передаче аргументов в контейнер? - PullRequest
0 голосов
/ 18 января 2019

Я новичок в мире docker / k8s ... Меня спросили, могу ли я развернуть контейнер, используя args для изменения поведения (обычно, если приложение работает в «основной» или «подчиненной» версии), которую я сделал. Возможно, не оптимальное решение, но оно работает:

Это простой тест для проверки. Я сделал собственное изображение со скриптом внутри: role.sh:

#!/bin/sh
ROLE=$1
echo "You are running "$ROLE" version of your app"

Dockerfile:

FROM centos:7.4.1708

COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE=""
ARG ROLE

ENTRYPOINT ["role.sh"]
CMD ["${ROLE}"]

Если я запускаю этот контейнер с помощью Docker, используя следующую команду:

docker run -dit --name test docker.local:5000/test master

Я получаю следующий журнал, который именно то, что я ищу:

You are running master version of your app

Теперь я хочу иметь такое же поведение на k8s, используя файл yaml. Я пробовал несколько способов, но ни один не помог.

Файл YAML:

apiVersion: v1
kind: Pod
metadata:
  name: master-pod
  labels:
     app: test-master
spec:
  containers:
    - name: test-master-container
      image: docker.local:5000/test
      command: ["role.sh"]
      args: ["master"]

Я видел так много разных способов сделать это, и я должен сказать, что я все еще не понимаю разницу между ARG и ENV.

Я тоже пробовал с

 - name: test-master-container
   image: docker.local:5000/test
   env:
     - name: ROLE
       value: master

и

 - name: test-master-container
   image: docker.local:5000/test    
   args:
     - master

но ничего из этого не сработало, мои модули всегда находятся в состоянии CrashLoopBackOff .. Заранее спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 19 января 2019

Чтобы ответить на вашу конкретную ситуацию, ни ваша ARG, ни ваша ENV, похоже, не дают эффекта, если вы их объявили.

Ваш рабочий процесс будет выглядеть следующим образом:

  1. напишите свой Dockerfile (как и вы, хорошо)
  2. build ваш контейнер (вы не предоставили команду build, которую использовали, но, учитывая объявление вашей ARG, я предполагаю, что вы должны были передать значение туда)
  3. запустить ваш контейнер (либо docker run, либо в модуле kubernetes / развертывание / и т.д.)

Ваш ENV ROLE="" означает, что во время сборки у вас должна быть пустая переменная $ ROLE, которую вы можете использовать в Dockerfile, и она будет доступна под тем же именем в среде работающего контейнера (предположительно, в виде пустой строки).

Ваш ARG ROLE означает, что вам нужно передать роль в вашу команду docker build, которая будет доступна во всем Dockerfile во время сборки, предположительно перезаписывая ранее объявленный ENV, но не оказывая никакого влияния на процесс сборки.

Что касается вашего запущенного скрипта, единственная роль, которая имеет значение, это ROLE=$1, например. переменная $ ROLE, которая принимает значение первого аргумента. Это означает, что бессмысленно указывать ПРАВИЛО env в вашем kubernetes yml, потому что при запуске вашего сценария оно будет перезаписывать RULE первым аргументом вашего сценария, даже если его нет (в результате получается пустое значение).

Эта спецификация выглядит корректно, и не забывайте, что вы можете заменить args: ["master"] на что-то вроде args: ["$(ROLE)"] (например: он будет ожидать, что ROLE env var будет установлен на машине, выполняющей ваш kubectl.

apiVersion: v1
kind: Pod
metadata:
  name: master-pod
  labels:
     app: test-master
spec:
  containers:
    - name: test-master-container
      image: docker.local:5000/test
      command: ["role.sh"]
      args: ["master"]
0 голосов
/ 18 января 2019

По конкретным полям:

  • Кубернетес command: соответствует концепции «точки входа» Докера, и все, что здесь указано, запускается как основной процесс контейнера. Вам не нужно указывать command: в спецификации модуля, если ваш Dockerfile уже имеет правильный ENTRYPOINT.
  • Кубернетес args: соответствует концепции "команды" Докера, и все, что здесь указано, передается в качестве аргументов командной строки точке входа.
  • Переменные среды в Docker и Kubernetes имеют свою обычную семантику Unix.
  • Dockerfile ARG указывает параметр конфигурации время сборки для образа. Правила расширения и взаимодействие с переменными среды немного странны. По моему опыту у этого есть несколько полезных вариантов использования («какую версию JVM я на самом деле хочу построить?»), Но каждый контейнер , созданный из образа, будет иметь то же унаследованное значение ARG; это не очень хороший механизм для конфигурации во время выполнения .
  • Для различных вещей, которые могут быть установлены в Dockerfile или во время выполнения (ENV переменные, EXPOSE d порты, значение по умолчанию CMD, особенно VOLUME), нет особой необходимости "объявлять" их в Dockerfile, чтобы иметь возможность устанавливать их во время выполнения.

Есть несколько более или менее эквивалентных способов сделать то, что вы описываете. (Я буду использовать синтаксис docker run для компактности.) Вероятно, наиболее гибкий способ - установить ROLE в качестве переменной среды; при запуске сценария точки входа можно предположить, что $ROLE имеет значение, но его стоит проверить.

#!/bin/sh
# --> I expect $ROLE to be set
# --> Pass some command to run as additional arguments
if [ -z "$ROLE" ]; then
  echo "Please set a ROLE environment variable" >&2
  exit 1
fi
echo "You are running $ROLE version of your app"
exec "$@"
docker run --rm -e ROLE=some_role docker.local:5000/test /bin/true

В этом случае вы можете указать значение по умолчанию ROLE в Dockerfile, если хотите.

FROM centos:7.4.1708
COPY ./role.sh /usr/local/bin
RUN chmod a+x /usr/local/bin/role.sh
ENV ROLE="default_role"
ENTRYPOINT ["role.sh"]

Второй путь - взять роль в качестве параметра командной строки:

#!/bin/sh
# --> pass a role name, then a command, as parameters
ROLE="$1"
if [ -z "$ROLE" ]; then
  echo "Please pass a role as a command-line option" >&2
  exit 1
fi
echo "You are running $ROLE version of your app"
shift        # drops first parameter
export ROLE  # makes it an environment variable
exec "$@"
docker run --rm docker.local:5000/test some_role /bin/true

Я бы, вероятно, предпочел бы путь к переменной среды, поскольку было бы немного проще указать несколько несвязанных параметров и не смешивать «настройки» и «команду» в части «команда» вызова Docker.

Относительно того, почему ваш модуль "падает": Kubernetes обычно ожидает, что он будет работать долго, поэтому, если вы напишите контейнер, который просто печатает что-то и выходит, Kubernetes перезапустит его, а когда он не будет работать, всегда будет в состоянии CrashLoopBackOff. Что вы пытаетесь сделать прямо сейчас, не беспокойтесь об этом и посмотрите на kubectl logs капсулы. Подумайте об установке политики перезапуска спецификации модуля , если это вас беспокоит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...