Команды, переданные Kubernetes Job и Pod

У меня есть команда perl, которую мне нужно передать на задание kubernetes. Команда вычисляет и выводит значение числа пи с точностью до 2000 знаков.

perl -Mbignum = bpi -wle 'печатать bpi (2000)'

Я передал команду в yaml-файл задания, как показано ниже. Через kubectl файл yaml успешно создает задание и выводит значение числа пи.

apiVersion: batch/v1
kind: Job
metadata:
   name: pi-job
spec:
   template:
     spec:
        containers:
          - name: pi
            image: perl
            command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]
        restartPolicy: Never

Когда я попытался использовать синтаксис команды ниже, он выдает ошибку. Не могли бы вы сказать мне, почему синтаксис приведенной ниже команды неверен?

command: ["perl",  "-Mbignum=bpi", "-wle", "'print bpi(2000)'"]     # placed inside single quote
command: ["perl",  "-Mbignum=bpi", "-wle", "print", " bpi(2000)"]   # print splitted in two quotes.
command: ["perl",  "-Mbignum=bpi", "-wle", "print", "bpi(2000)"]    # print splitted in two quotes.

Кроме того, когда я передаю полную команду в одинарных кавычках, это вызывает ошибку.

command: ["perl -Mbignum=bpi -wle print bpi(2000)"]       # complete command in single quotes.

person Naseem Khan    schedule 04.02.2020    source источник
comment
Что за сообщение об ошибке?   -  person openJT    schedule 04.02.2020


Ответы (1)


command: ключ требует, чтобы вы передали массив в качестве аргумента (сравните с этот пример). Вы можете указать массив в двух эквивалентных формах:

в одну строку, используя квадратные скобки []:

---
items: [ 1, 2, 3, 4, 5 ]
names: [ "one", "two", "three", "four" ]

и в многострочном режиме:

---
items:
  - 1 
  - 2 
  - 3
  - 4 
  - 5 
names:
  - "one"
  - "two"
  - "three"
  - "four"

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

command: ['perl',  '-Mbignum=bpi', '-wle', 'print bpi(2000)']

Однако вы не можете использовать оба одновременно. Я не знаю, чего бы вы хотели достичь, поместив туда "'print bpi(2000)'", но этот синтаксис не имеет никакого смысла и просто неверен.

Вы также можете спросить, почему вы не можете запустить 'echo bla' в bash, в то же время echo bla работает успешно, давая желаемый результат.

Обратите внимание, что при предоставлении command таким образом в кубернетах только первый элемент массива является фактическим command (исполняемый файл ищется в $PATH), а другие следующие элементы являются его аргументами. Помня об этом, вы должны заметить, что ваши следующие два примера также не имеют никакого смысла, поскольку ни «print», ни «bpi (2000)», предоставленные отдельно, не являются допустимыми аргументами:

command: ["perl",  "-Mbignum=bpi", "-wle", "print", " bpi(2000)"]   # print splitted in two quotes.
command: ["perl",  "-Mbignum=bpi", "-wle", "print", "bpi(2000)"]    # print splitted in two quotes.

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

$ perl --help

Usage: perl [switches] [--] [programfile] [arguments]
  -e program        one line of program (several -e's allowed, omit programfile)
  -l[octal]         enable line ending processing, specifies line terminator
  -[mM][-]module    execute "use/no module..." before executing program
  -w                enable many useful warnings

Run 'perldoc perl' for more help with Perl.

Теперь давайте разберем нашу команду пошагово:

["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]

Каждый элемент массива, следующий за основной командой "perl", является отдельной сущностью, которая передается как аргумент основной команды, ее флаг или аргумент недавно предоставленного флага, который согласно документации является обязательным и должен быть предоставлен в очень конкретной форме.

В нашем -wle наборе флагов опция e имеет решающее значение, поскольку за ней должен следовать конкретный аргумент:

 -e program        one line of program (several -e's allowed, omit programfile)

что в нашем примере:

print bpi(2000)

Еще раз хочу это подчеркнуть. Каждый элемент массива рассматривается как отдельный объект. Разбивая его на два отдельных элемента, таких как "print", " bpi(2000)" или "print", "bpi(2000)", вы вводите perl -e только с print аргументом, который не имеет никакого смысла, поскольку требует очень конкретной команды, сообщающей ему, что следует печатать. Это точно так же, как если бы вы запустили оболочку bash:

perl -Mbignum=bpi -wle 'print' 'bpi(2000)'

что приведет к следующей ошибке интерпретатора perl:

Use of uninitialized value $_ in print at -e line 1.

И, наконец, когда вы запустите свой последний пример:

command: ["perl -Mbignum = bpi -wle print bpi (2000)"] # завершите команду в одинарных кавычках.

вы получите довольно подробное сообщение, объясняющее, почему это не работает в Pod событиях (kubectl describe pod pi):

Error: failed to start container "pi": Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"perl -Mbignum=bpi -wle print bpi(2000)\": executable file not found in $PATH": unknown

Он в основном пытается найти в $ PATH исполняемый файл с именем "perl -Mbignum=bpi -wle print bpi(2000)", что, конечно, невозможно.

Если вы хотите ознакомиться с различными способами определения command и его arguments для container в кубернетах, я рекомендую вам прочитать этот раздел официальной документации Kubernetes.

person mario    schedule 04.02.2020
comment
Это развеяло все мои сомнения относительно команд и аргументов. Это было очень хорошо объяснено. Ваше здоровье. - person Naseem Khan; 05.02.2020
comment
@ Насим Хан, я рад, что смог помочь. Если ответ был полезен или помог решить вашу проблему, вы можете проголосовать за него и отметить его как принятый. См. Следующую статью в справочном центре: Что мне делать, когда кто-то ответит на мой вопрос? - person mario; 10.02.2020