Home Posts About Contact

Cloud Application Development

Containerize applications and run them in the cloud with OpenShift

OpenShift Cron Job Example

OpenShift Cron Jobs provide a way to run programs and scripts on a fixed schedule, without having to rely on services in long lived containers. A new container gets created to execute code for each run of the cron job, and the container gets removed after the code inside of it reports it has finished running and exited successfully. If you're not already familiar with Kubernetes Jobs or cron schedule formatting in general, here is an overview of the available scheduling options:

┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 6) (Sunday to Saturday;
│ │ │ │ │                                       7 is also Sunday on some systems)
│ │ │ │ │
│ │ │ │ │
* * * * *  command to execute
 
So a cron schedule of "30 14 * * 5" would run at 2:30 PM every Friday, according to the timezone the host node is using. In the case of Openshift Online, the nodes are set to use UTC. Cron Jobs will launch containers that behave and run just like any other containers on OpenShift, only these will be deleted as soon as they report a successful completion. They can use secrets, volumeMounts, Image Pull Secrets, any other configuration settings you're used to using in DeploymentConfigs The restartPolicy specifies that the job will keep restarting this container when any failures are encountered during the job's run. This makes it important to ensure your commands, scripts, and programs all exit cleanly, e.g. "exit 0" for bash, "sys.exit(0)" for python, etc. These serve as as one layer of safeguards so the pods don't get stuck in an infinite restart loop.
- apiVersion: batch/v2alpha1
  kind: CronJob
  metadata:
    name: report
  spec:
    schedule: "30 14 * * 5"
    jobTemplate:
      spec:
        template:
          metadata:
            labels:
              parent: "cronjobreport"
          spec:
            containers:
            - name: cronreport
              image: "${NAMESPACE}/report-sender-pod:latest"
              command: ["/secrets/cronjob.py"]
              volumeMounts:
              - mountPath: /secrets
                name: report-sender-pod-secrets
            volumes:
            - name: report-sender-pod-secrets
              secret:
                secretName: report-sender-pod-secrets
            restartPolicy: OnFailure
And finally, here is an example of a complete template, containing two separate cron jobs and one long lived container DeploymentConfig:
---
apiVersion: v1 
kind: Template
metadata:
  creationTimestamp: null
  generation: 1
  labels:
    provider: openshift
    report-sender-pod-host: "true"
    component: report-sender-pod
  name: report-sender-pod 
objects:
- apiVersion: v1
  kind: ImageStream
  metadata:
    labels:
      template: report-sender-pod
    name: "report-sender"
  spec:
    tags:
    - annotations: null
      from:
        kind: DockerImage
        name: "/cron-report-sender/report-sender:latest"
        pullSecret:
          name: dockercfgjson
      importPolicy:
        scheduled: true
      name: latest
- apiVersion: batch/v2alpha1
  kind: CronJob
  metadata:
    name: report
  spec:
    schedule: "30 14 * * 5"  
    jobTemplate:             
      spec:
        template:
          metadata:
            labels:          
              parent: "cronjobreport"
          spec:
            containers:
            - name: cronreport
              image: "${NAMESPACE}/report-sender-pod:latest"
              command: ["/secrets/cronjob.py"]
              volumeMounts:
              - mountPath: /secrets
                name: report-sender-pod-secrets
            volumes:
            - name: report-sender-pod-secrets
              secret:
                secretName: report-sender-pod-secrets
            restartPolicy: OnFailure 
- apiVersion: batch/v2alpha1
  kind: CronJob
  metadata:
    name: report
  spec:
    schedule: "05 13 * * 1"
    jobTemplate:
      spec:
        template:
          metadata:
            labels:
              parent: "cronjobreport"
          spec:
            containers:
            - name: cronreport
              image: "${NAMESPACE}/report-sender-pod:latest"
              command: ["/secrets/cronjob.py"]
              volumeMounts:
              - mountPath: /secrets
                name: report-sender-pod-secrets
            volumes:
            - name: report-sender-pod-secrets
              secret:
                secretName: report-sender-pod-secrets
            restartPolicy: OnFailure
- apiVersion: v1
  kind: DeploymentConfig
  metadata:
    labels:
      template: report-sender-pod
    name: report-sender-pod
  spec:
    replicas: 1
    selector:
      deploymentconfig: report-sender-pod
    strategy:
      resources: {}
      type: Rolling
    template:
      metadata:
        labels:
          deploymentconfig: report-sender-pod
      spec:
        containers:
        - env:
          - name: OO_PAUSE_ON_START
            value: "false"
          image: "report-sender-pod/report-sender-pod:latest"
          imagePullPolicy: Always
          name: report-sender-pod
          resources: {}
          securityContext: {}
          terminationMessagePath: /dev/termination-log
          volumeMounts:
          - mountPath: /secrets
            name: report-sender-pod-secrets
        dnsPolicy: ClusterFirst
        restartPolicy: Always
        securityContext: {}
        terminationGracePeriodSeconds: 30
        volumes:
        - name: report-sender-pod-secrets
          secret:
            secretName: report-sender-pod-secrets
    test: false
    triggers:
    - type: ConfigChange
    - imageChangeParams:
        automatic: true
        containerNames:
        - report-sender-pod
        from:
          kind: ImageStreamTag
          name: "${PLAT}-report-sender-pod:latest"
      type: ImageChange
parameters:
- description: Platform name
  name: PLAT
  value: rhel7
- description: Project name
  name: NAMESPACE
  value: cron-report-sender