Commands passed to a Kubernetes Job and Pod

1.3k Views Asked by At

I've a perl command which I need to pass to a kubernetes job. Command computes and prints the value of pi to 2000 places.

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

I've passed the command to a job yaml file as shown below. Via kubectl, yaml file creates job successfully and prints the value of pi.

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

When I tried with below command syntax, it gives me error. Could you please tell me why the below command synax is incorrect?

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.

Also when I pass the complete command in a single quote, it gives me error.

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

There are 1 best solutions below

2
On BEST ANSWER

command: key requires that you pass an array as it's argument (compare with this example). You can specify an array in two equivalent forms:

in a single line, using square brackets []:

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

and in a multi-line fashion:

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

You can use both double " and signle ' quotes, so the example below will be also correct and will work:

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

However you cannot use both at the same time. I don't know what you would like to achieve by putting there "'print bpi(2000)'", but this syntax doesn't make any sense and is simply incorrect.

You might as well ask why you can't run 'echo bla' in bash while at the same time echo bla runs successfully, giving you the desired result.

Note that when providing command this way in kubernetes, only first element of the array is an actual command (executable file searched in $PATH) and other following elements are its arguments. Keeping this in mind, you should notice that your next two examples also don't make any sense as neither "print" nor "bpi(2000)" provided separately are not valid arguments:

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.

To be able to fully understand what this command is doing, we need to dive a bit into basic perl documentation. I left only those options that were used in our example and are relevant to it:

$ 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.

Now let's analyse our command step by step:

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

Each element of the array, which follows the main command "perl" is a separate entity which is passed as an argument of the main command, its flag, or an argument of recently provided flag, which according to documentation is required and should be provided in a very specific form.

In our -wle set of flags, e option is crucial as it must be followed by specific argument:

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

which in our example is:

print bpi(2000)

I want to emphasize it again. Every element of the array is treated as a separate entity. By breaking it into two separate elements such as "print", " bpi(2000)" or "print", "bpi(2000)" you feed perl -e only with print argument which doesn't make for it any sense as it requires very specific command telling it what should be printed. It is exactly as if you run in bash shell:

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

which will result in the following error from perl interpreter:

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

And finally when you run your last example:

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

you'll get quite detailed message explaining why it doesn't work in Pod events (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

It basically tries to find in $PATH an executable file named "perl -Mbignum=bpi -wle print bpi(2000)" which of course cannot be done.

If you want to familiarize with different ways of defining a command and its arguments for a container in kubernetes, I recommend you reading this section in official kubernetes documentation.