Как установить несколько команд в одном файле yaml с Kubernetes?

96

В этом официальном документе он может запускать команду в файле конфигурации yaml:

https://kubernetes.io/docs/tasks/configure-pod-container/

apiVersion: v1
kind: Pod
metadata:
  name: hello-world
spec:  # specification of the pod’s contents
  restartPolicy: Never
  containers:
  - name: hello
    image: "ubuntu:14.04"
    env:
    - name: MESSAGE
      value: "hello world"
    command: ["/bin/sh","-c"]
    args: ["/bin/echo \"${MESSAGE}\""]

Если я хочу запустить более одной команды, как это сделать?

що
источник

Ответы:

151
command: ["/bin/sh","-c"]
args: ["command one; command two && command three"]

Объяснение: В сообщении command ["/bin/sh", "-c"]говорится: «Запустите оболочку и выполните следующие инструкции». Затем аргументы передаются в оболочку как команды. В сценариях оболочки точка с запятой разделяет команды и &&условно выполняет следующую команду, если первая выполнена успешно. В приведенном выше примере он всегда запускается с command oneпоследующим command twoи выполняется только в command threeслучае command twoуспеха.

Альтернатива: во многих случаях некоторые из команд, которые вы хотите запустить, вероятно, устанавливают последнюю команду для запуска. В этом случае лучше всего создать собственный Dockerfile . В частности, обратите внимание на директиву RUN .

Тим Оллклер
источник
1
Да, очень верно, однако я думаю, что есть также хорошие варианты использования, которые можно расширить, так commandкак он переопределяет Dockerfile Entrypoint;)
Майкл Хаузенблас
1
Есть идеи, как это сделать с жизненным циклом контейнера? У него нет аргументов
aclokay 09
1
@aclokay вы можете просто указать аргументы как дополнительные командные строки. Разделение между командами и аргументами в контейнере просто для упрощения переопределения аргументов. Они функционально эквивалентны.
Тим Олклер
что здесь делает -c?
Абдул
1
@Abdul означает запуск сценария, предоставленного в качестве аргумента, вместо запуска интерактивной оболочки или загрузки сценария из файла.
Тим Олклер
77

Я предпочитаю использовать несколько строк для аргументов, это самый простой и легкий способ чтения. Также скрипт можно изменить, не затрагивая изображение, просто нужно перезапустить pod. Например, для дампа mysql спецификация контейнера может быть примерно такой:

containers:
  - name: mysqldump
    image: mysql
    command: ["/bin/sh", "-c"]
    args:
      - echo starting;
        ls -la /backups;
        mysqldump --host=... -r /backups/file.sql db_name;
        ls -la /backups;
        echo done;
    volumeMounts:
      - ...

Причина, по которой это работает, заключается в том, что yaml фактически объединяет все строки после "-" в одну, а sh запускает одну длинную строку "echo start; ls ...; echo done;".

Оливер
источник
Хорошо, но когда вы запрашиваете редактирование с помощью kubectl, оно снова будет в одной строке. :)
sekrett
@sekrett о нет! :(
aclokay 02
1
Это сработало довольно хорошо - ключом является точка с запятой в каждой строке. Это особенно хорошее решение, когда команд много и они будут многострочными с решением выше. Делает git diff
проще простого
Это то, что я искал. использование переменной окружения в качестве аргументов в этом решении отлично работает.
Jingpeng Wu
+1 Прекрасно, плюс многострочные команды работают отлично: command: ['/bin/bash', '-c'] args: - exec &> /path/to/redirected/program.output;`python / program.py`` --key1 = val1` `--key2 = val2`` --key3 = val3`
nelsonspbr
46

Если вы хотите использовать том и ConfigMap, вы можете подключить данные ConfigMap как сценарий, а затем запустить этот сценарий:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  entrypoint.sh: |-
    #!/bin/bash
    echo "Do this"

    echo "Do that"
---
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: "ubuntu:14.04"
    command:
    - /bin/entrypoint.sh
    volumeMounts:
    - name: configmap-volume
      mountPath: /bin/entrypoint.sh
      readOnly: true
      subPath: entrypoint.sh
  volumes:
  - name: configmap-volume
    configMap:
      defaultMode: 0700
      name: my-configmap

Это немного уточняет спецификации вашего модуля и позволяет создавать более сложные сценарии.

$ kubectl logs my-pod
Do this
Do that
дулихан
источник
1
Очень круто, но я думаю, что проще встроить скрипт, просто используйте многострочный синтаксис. Я показываю это в отдельном ответе.
Оливер
А как насчет того, когда мне нужно передать двойные кавычки. Например, представьте себе эту команду: printf '% s @% s \ n' "$ (echo 'user')" "$ (echo 'host')"
L3K0V
16

Если вы хотите избежать объединения всех команд в одну команду ;или &&вы также можете получить настоящие многострочные скрипты с помощью heredoc:

command: 
 - sh
 - "-c"
 - |
   /bin/bash <<'EOF'

   # Normal script content possible here
   echo "Hello world"
   ls -l
   exit 123

   EOF

Это удобно для запуска существующих сценариев bash, но имеет недостаток, заключающийся в том, что для настройки heredoc требуется как внутренний, так и внешний экземпляр оболочки.

синий
источник
4

IMHO лучший вариант - использовать собственные скаляры блоков YAML . Именно в этом случае сложенный блок стиля.

Вызывая, sh -cвы можете передавать аргументы своему контейнеру в виде команд, но если вы хотите элегантно разделить их с помощью новой строки, вы захотите использовать свернутый блок стиля , чтобы YAML знал, как преобразовать новую строку в пробелы, эффективно объединяя команды.

Полный рабочий пример:

apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  containers:
  - name: busy
    image: busybox:1.28
    command: ["/bin/sh", "-c"]
    args:
    - >
      command_1 &&
      command_2 &&
      ... 
      command_n
рыбы
источник
1

Я не уверен, что вопрос еще активен, но из-за того, что я не нашел решения в приведенных выше ответах, я решил записать его.

Я использую следующий подход:

readinessProbe:
  exec:
    command:
    - sh
    - -c
    - |
      command1
      command2 && command3

Я знаю, что мой пример связан с readinessProbe, livenessProbe и т. Д., Но подозреваю, что тот же случай относится к командам контейнера. Это обеспечивает гибкость, поскольку отражает стандартный сценарий, написанный на Bash.

tmetodie
источник
0

Вот как вы можете передать несколько команд и аргументов в один файл YAML с помощью кубернетов:

# Write your commands here
command: ["/bin/sh", "-c"]
# Write your multiple arguments in args
args: ["/usr/local/bin/php /var/www/test.php & /usr/local/bin/php /var/www/vendor/api.php"]

Полный блок контейнеров из yaml файла:

    containers:
      - name: widc-cron # container name
        image: widc-cron # custom docker image
        imagePullPolicy: IfNotPresent # advisable to keep
        # write your command here
        command: ["/bin/sh", "-c"]
        # You can declare multiple arguments here, like this example
        args: ["/usr/local/bin/php /var/www/tools/test.php & /usr/local/bin/php /var/www/vendor/api.php"]
        volumeMounts: # to mount files from config-map generator
          - mountPath: /var/www/session/constants.inc.php
            subPath: constants.inc.php
            name: widc-constants
Йоги Гореча
источник
0

Чтобы представить еще один возможный вариант, можно использовать секреты, поскольку они представлены модулю в виде томов:

Секретный пример:

apiVersion: v1
kind: Secret 
metadata:
  name: secret-script
type: Opaque
data:
  script_text: <<your script in b64>>

Экстракт ямла:

....
containers:
    - name: container-name
      image: image-name
      command: ["/bin/bash", "/your_script.sh"]
      volumeMounts:
        - name: vsecret-script
          mountPath: /your_script.sh
          subPath: script_text
....
  volumes:
    - name: vsecret-script
      secret:
        secretName: secret-script

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

ночь
источник
0

Вот мой успешный пробег

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: busybox
  name: busybox
spec:
  containers:
  - command:
    - /bin/sh
    - -c
    - |
      echo "running below scripts"
      i=0; 
      while true; 
      do 
        echo "$i: $(date)"; 
        i=$((i+1)); 
        sleep 1; 
      done
    name: busybox
    image: busybox
Бражеш Джайшвал
источник