3

I have a Kubernetes Job, job.yaml :

---
apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
---
apiVersion: batch/v1
kind: Job
metadata:
  name: my-job
  namespace: my-namespace
spec:
  template:
    spec:
      containers:
      - name: my-container
        image: gcr.io/project-id/my-image:latest
        command: ["sh", "run-vpn-script.sh", "/to/download/this"] # need to run this multiple times
        securityContext:
          privileged: true
          allowPrivilegeEscalation: true
      restartPolicy: Never

I need to run command for different parameters. I have like 30 parameters to run. I'm not sure what is the best solution here. I'm thinking to create container in a loop to run all parameters. How can I do this? I want to run the commands or containers all simultaneously.

user6308605
  • 693
  • 8
  • 26

3 Answers3

2

In simpler terms , you want to run multiple commands , following is a sample format to execute multiple commands in a pod :

command: ["/bin/bash","-c","touch /foo && echo 'here' && ls /"]

When we apply this logic to your requirement for two different operations

 command: ["sh", "-c", "run-vpn-script.sh /to/download/this && run-vpn-script.sh /to/download/another"] 
confused genius
  • 2,876
  • 2
  • 16
  • 29
  • So means it will run one after another? What if I want to run `sh` all at the same time? – user6308605 Jul 06 '21 at 05:08
  • Infact && makes it run only when previous command is sucessful.if you want to run them oneafter another we need replace && with ;. if you need them to run "parallely"(kind of) then you might need put all those commands in a file with & at the end of each command and pass that file as an argument to "sh" – confused genius Jul 06 '21 at 05:26
2

Some of the ways that you could do it outside of the solutions proposed in other answers are following:


Helm example:

Helm in short is a templating tool that will allow you to template your manifests (YAML files). By that you could have multiple instances of Jobs with different name and a different command.

Assuming that you've installed Helm by following guide:

You can create an example Chart that you will modify to run your Jobs:

  • helm create chart-name

You will need to delete everything that is in the chart-name/templates/ and clear the chart-name/values.yaml file.

After that you can create your values.yaml file which you will iterate upon:

jobs:
  - name: job1
    command: ['"perl",  "-Mbignum=bpi", "-wle", "print bpi(3)"']
    image: perl
  - name: job2
    command: ['"perl",  "-Mbignum=bpi", "-wle", "print bpi(20)"']
    image: perl
  • templates/job.yaml
{{- range $jobs := .Values.jobs }}
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ $jobs.name }}
  namespace: default # <-- FOR EXAMPLE PURPOSES ONLY!
spec:
  template:
    spec:
      containers:
      - name: my-container
        image: {{ $jobs.image }}
        command: {{ $jobs.command }}
        securityContext:
          privileged: true
          allowPrivilegeEscalation: true
      restartPolicy: Never
---
{{- end }}

If you have above files created you can run following command on what will be applied to the cluster beforehand:

  • $ helm template . (inside the chart-name folder)
---
# Source: chart-name/templates/job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job1
  namespace: default
spec:
  template:
    spec:
      containers:
      - name: my-container
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(3)"]
        securityContext:
          privileged: true
          allowPrivilegeEscalation: true
      restartPolicy: Never
---
# Source: chart-name/templates/job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: job2
  namespace: default
spec:
  template:
    spec:
      containers:
      - name: my-container
        image: perl
        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(20)"]
        securityContext:
          privileged: true
          allowPrivilegeEscalation: true
      restartPolicy: Never

A side note #1!

This example will create X amount of Jobs where each one will be separate from the other. Please refer to the documentation on data persistency if the files that are downloaded are needed to be stored persistently (example: GKE).

A side note #2!

You can also add your namespace definition in the templates (templates/namespace.yaml) so it will be created before running your Jobs.

You can also run above Chart by:

  • $ helm install chart-name . (inside the chart-name folder)

After that you should be seeing 2 Jobs that are completed:

  • $ kubectl get pods
NAME         READY   STATUS      RESTARTS   AGE
job1-2dcw5   0/1     Completed   0          82s
job2-9cv9k   0/1     Completed   0          82s

And the output that they've created:

  • $ echo "one:"; kubectl logs job1-2dcw5; echo "two:"; kubectl logs job2-9cv9k
one:
3.14
two:
3.1415926535897932385

Additional resources:

Dawid Kruk
  • 8,982
  • 2
  • 22
  • 45
1

If you want to run the same command multiple times you can deploy the same YAML multiple times by just changing the name.

You can go with the sed command for replacing the values in YAML and apply those YAML to the cluster for creating the container.

Example job.yaml

---
apiVersion: v1
kind: Namespace
metadata:
  name: my-namespace
---
apiVersion: batch/v1
kind: Job
metadata:
  name: my-job
  namespace: my-namespace
spec:
  template:
    spec:
      containers:
      - name: my-container
        image: gcr.io/project-id/my-image:latest
        command: COMMAND # need to run this multiple times
        securityContext:
          privileged: true
          allowPrivilegeEscalation: true
      restartPolicy: Never

command :

'job.yaml | sed -i "s,COMMAND,["sh", "run-vpn-script.sh", "/to/download/this"],"

so the above command will replace all the values in YAML and you can apply the YAML to the cluster for creating the container. Same you can apply for other variables.

You can pass the different parameters as per the need in the command that got set in the YAML.

You can also deploy the multiple jobs using the command also

kubectl create job test-job --from=cronjob/a-cronjob

https://www.mankier.com/1/kubectl-create-job

pass other param as per need into the command.

If you don't just want to run the POD you can also try

kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>

https://jamesdefabia.github.io/docs/user-guide/kubectl/kubectl_run/

Harsh Manvar
  • 27,020
  • 6
  • 48
  • 102
  • should I apply the `sed` command before or after applying the `job.yaml`? Sorry, I'm not clear how use this – user6308605 Jul 06 '21 at 04:33
  • 1
    what `sed` command will is find the COMMAND in YAML and file and replace it with your command config you want to pass. You can write the `sed` command which will use the one YAML as base template and give you new updated YAML with value. – Harsh Manvar Jul 06 '21 at 04:34
  • Please you can also check this answer : https://stackoverflow.com/a/48297258/5525824 – Harsh Manvar Jul 06 '21 at 04:36