Шлем и команда с && - PullRequest
       3

Шлем и команда с &&

0 голосов
/ 29 января 2020

У меня есть следующее задание Helm для приложения Django для запуска миграций и сбора файлов stati c:

apiVersion: batch/v1
kind: Job
metadata:
  name: django-app-job
  labels:
    app.kubernetes.io/name: django-app-job
    helm.sh/chart: django-app
    app.kubernetes.io/instance: staging-admin
    app.kubernetes.io/managed-by: Tiller
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "1"
    "helm.sh/hook-delete-policy": hook-succeeded,hook-failed
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/name: django-app-job
        app.kubernetes.io/instance: foobar
    spec:
      restartPolicy: OnFailure
      containers:
        - name: django-app
          command:
          - "/bin/bash"
          - "-c"
          - "python3 ./manage.py migrate"
          - "&&"
          - "python3 ./manage.py collectstatic --noinput"

Но выполняется только миграция для обновления схемы БД, но он никогда не запускает сбор информации c. Даже если миграция пройдет нормально. Задание не завершается сбоем, потому что в противном случае обновление завершится неудачей, а этого не произойдет.

Но если я изменю команду на такую:

      containers:
        - name: django-app
          command:
          - "/bin/bash"
          - "-c"
          - "python3 ./manage.py migrate && python3 ./manage.py collectstatic --noinput"

, теперь задания запускают миграции и собирать стати c. В чем разница между 2 командами?

1 Ответ

2 голосов
/ 30 января 2020

На низком уровне все команды Unix фактически выполняются как последовательность слов. Обычно оболочка разделяет командные строки на слова для вас, но в манифесте Kubernetes вы должны вручную указывать одно слово за раз.

В вашем примере опция Bourne shell sh -c читает только следующее отдельное слово и выполняет его как команду, применяя обычные правила оболочки. Любые оставшиеся слова используются в качестве позиционных параметров, если в команде используются переменные типа $1.

. Вы можете продемонстрировать это за пределами Kubernetes в своей локальной оболочке, используя кавычки, чтобы заставить оболочку разбивать слова так, как это необходимо. Вы хотите:

# Option one
'/bin/sh' '-c' 'echo foo' '&&' 'echo bar'
# Prints "foo"

# Option two
'/bin/sh' '-c' 'echo foo && echo bar'
# Prints "foo", "bar"

Одна хитрость, которая проявляется довольно часто, заключается в использовании скаляров блока YAML для записи одной строки в несколько строк, что дает что-то вроде скрипта оболочки но на самом деле это не так.

command: ['/bin/sh', '-c']
args: >-
  python3 ./manage.py migrate
  &&
  python3 ./manage.py collectstatic --noinput
...