Команды, переданные 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.

1 ответ

Решение

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

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

---
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 я рекомендую вам прочитать этот раздел в официальной документации kubernetes.

Другие вопросы по тегам