Як встановити кілька команд в одному файлі yaml за допомогою Kubernetes?


94

У цьому офіційному документі він може запускати команду у файлі конфігурації 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}\""]

Якщо я хочу запустити більше однієї команди, як це зробити?

Відповіді:


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

Пояснення: У ньому command ["/bin/sh", "-c"]сказано "запустити оболонку і виконати наступні інструкції". Потім аргументи передаються як команди оболонці. У сценаріях оболонки крапка з комою відокремлює команди та &&умовно запускає наступну команду, якщо перша вдала. У наведеному вище прикладі він завжди виконується з command oneнаступним command two, і виконується лишеcommand three випадку command twoуспіху.

Альтернатива: У багатьох випадках деякі команди, які ви хочете запустити, імовірно, встановлюють останню команду для запуску. У цьому випадку створення власного файлу Docker - це шлях. Подивіться, зокрема, на директиву RUN .


1
Так, дуже дійсний, однак, я думаю, що є також хороші випадки використання, які можна поширити, commandоскільки це перекриває Dockerfile Entrypoint;)
Майкл Хаузенблас

1
Будь-яка ідея про те, як це зробити із життєвим циклом контейнера? Він не має аргументів
aclokay

1
@aclokay ви можете просто вказати аргументи як додаткові командні рядки. Розділення між командою та аргументами в контейнері полягає лише в тому, щоб полегшити перевизначення аргументів. Вони функціонально еквівалентні.
Tim Allclair

що тут робить -c?
Абдул

1
@Abdul це означає запустити скрипт, наданий як аргумент, а не запускати інтерактивну оболонку або завантажувати сценарій з файлу.
Тім Оллер

76

Я віддаю перевагу багаторядковому аргументуванню, це найпростіше і найпростіше для читання. Крім того, сценарій можна змінити, не впливаючи на зображення, просто потрібно перезапустити під. Наприклад, для дампа 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 о ні! :(
aclokay 02

1
Це спрацювало досить добре - ключовою є точка з комою в кожному рядку. Це особливо гарне рішення, коли команд багато, і воно буде багаторядковим із наведеним вище рішенням. Робить git diff вітерець
kellyfj

Це те, що я шукав. використання змінної середовища як аргументів з цим рішенням працює добре.
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,

15

Якщо ви хочете уникнути об’єднання всіх команд в одну команду за допомогою ;або &&ви також можете отримати справжні багаторядкові сценарії, використовуючи heredoc:

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

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

   EOF

Це зручно для запуску існуючих скриптів bash, але має мінус - вимагати як внутрішнього, так і зовнішнього екземпляра оболонки для налаштування heredoc.


3

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.


0

Ось як ви можете передавати кілька команд та аргументів в один файл YAML за допомогою kubernetes:

# 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.