19

I am new to helm and I have tried to deploy a few tutorial charts. Had a couple of queries:

  1. I have a Kubernetes job which I need to deploy. Is it possible to deploy a job via helm?

  2. Also, currently my kubernetes job is deployed from my custom docker image and it runs a bash script to complete the job. I wanted to pass a few parameters to this chart/job so that the bash commands takes the input parameters. That's the reason I decided to move to helm because it provided a more flexibility. Is that possible?

Tibebes. M
  • 6,940
  • 5
  • 15
  • 36
codec
  • 7,978
  • 26
  • 71
  • 127

3 Answers3

15

You can use Helm Hooks to run jobs. Depending on how you set up your annotations you can run a different type of hook (pre-install, post-install, pre-delete, post-delete, pre-upgrade, post-upgrade, pre-rollback, post-rollback, crd-install). An example from the doc is as follows:

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{.Release.Name}}"
  labels:
    app.kubernetes.io/managed-by: {{.Release.Service | quote }}
    app.kubernetes.io/instance: {{.Release.Name | quote }}
    helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}"
  annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{.Release.Name}}"
      labels:
        app.kubernetes.io/managed-by: {{.Release.Service | quote }}
        app.kubernetes.io/instance: {{.Release.Name | quote }}
        helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job
        image: "alpine:3.3"
        command: ["/bin/sleep","{{default "10" .Values.sleepyTime}}"]

You can pass your parameters as secrets or configMaps to your job as you would to a pod.

a14m
  • 7,808
  • 8
  • 50
  • 67
cookiedough
  • 3,552
  • 2
  • 26
  • 51
  • Is it possible to pass parameters to a kubernetes job? – codec Apr 01 '19 at 15:26
  • @aaj As I mentioned at the bottom of the post, you can sent in parameters through a secret or configMap, and if you are talking about substituting variables, you can add variables in your manifest just like you would with any other helm chart template files. – cookiedough Apr 01 '19 at 15:29
  • What would happen if you let a Job be part of the release (i.e. you define a Job template without the hooks)? – GACy20 Jan 21 '22 at 15:40
  • @GACy20: If you remove helm hook annotation then this job is considered as a normal kubernetes job (it will go to "Completed" state). The pod that this job creates also would be in "Completed" state. If you uninstall helm chart, this job will be deleted. "helm upgrade" cannot delete and create this job again. (This is requirement) If you add hook annotations, this job's creation is dependent on what annotation you used. Eg: If you used "post-install" hook, then other k8s resources in helm will get created first when helm chart is installed, and after those this job will get created. – Pankaj Yadav Jan 25 '22 at 11:31
  • You can refer to this answer for some idea: https://stackoverflow.com/a/70846491/14715359 – Pankaj Yadav Jan 25 '22 at 11:43
15

You can use helm. Helm installs all the kubernetes resources like job,pods,configmaps,secrets inside the templates folder. You can control the order of installation by helm hooks. Helm offers hooks like pre-install, post-install, pre-delete with respect to deployment. if two or more jobs are pre-install then their weights will be compared for installing.

|-scripts/runjob.sh
|-templates/post-install.yaml
|-Chart.yaml
|-values.yaml

Many times you need to change the variables in the script as per the environment. so instead of hardcoding variable in script, you can also pass parameters to script by setting them as environment variables to your custom docker image. Change the values in values.yaml instead of changing in your script.

values.yaml

key1:
  someKey1: value1
key2:
  someKey2: value1

post-install.yaml

apiVersion: batch/v1
kind: Job
metadata:
  name: post-install-job
  labels:
    provider: stackoverflow
    microservice: {{ template "name" . }}
    release: "{{ .Release.Name }}"
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade,pre-rollback
    "helm.sh/hook-delete-policy": before-hook-creation
    "helm.sh/hook-weight": "3"
spec:
  template:
    metadata:
      name: "{{.Release.Name}}"
      labels:
        provider: stackoverflow
        microservice: {{ template "name" . }}
        release: "{{ .Release.Name }}"
        app: {{ template "fullname" . }}
    spec:
      restartPolicy: Never
      containers:
        - name: post-install-job
          image: "custom-docker-image:v1"
          command: ["/bin/sh", "-c", {{ .Files.Get "scripts/runjob.sh" | quote }} ]
          env:
          #setting KEY1 as environment variable in the container,value of KEY1 in container is value1(read from values.yaml)
          - name: KEY1
            value: {{ .Values.key1.someKey1 }}
          - name: KEY2
            value: {{ .Values.key2.someKey2 }}

runjob.sh

# you can access the variable from env variable
echo $KEY1
echo $KEY2
# some stuff
Manikanta P
  • 2,777
  • 2
  • 19
  • 22
5

I had a similar scenario where I had a job I wanted to pass a variety of arguments to. I ended up doing something like this:

Template:

apiVersion: batch/v1
kind: Job
metadata:
  name: myJob
spec:
  template:
    spec:
      containers:
      - name: myJob
        image: myImage
        args: {{ .Values.args }}

Command (powershell):

helm template helm-chart --set "args={arg1\, arg2\, arg3}" | kubectl apply -f -