Best practice for running a cron job inside an app on Openshift?

Viewed 3500

I want to run a simple backup of my postgres db deployed in Openshift. What are the best practices for running a cron job? Since systemd is not available on the containers and can only be enabled through a hack, I'd rather use a 'cleaner' approach. Besides cronie or systemd timer units, what options are there? There seems one could enable cron in earlier Openshift versions, however Openshift v4.x doesn't support this feature anymore and the docs only mention the Kubernetes Cron Jobs objects.

2 Answers

Here is what I use:

  • Dedicated Pod with same image (ensure db dump client is available) and PVC for backup mounted
  • ConfigMap with backup script
  • Cronjob running that pod frequently

Here's some example manifests:

PVC:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-bkp
  namespace: database
    annotations:
    volume.beta.kubernetes.io/storage-class: "storage-class-name"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

CM:

apiVersion: v1
kind: ConfigMap
metadata:
  name: psqldump
  namespace: database
  labels:
    job-name: db-backup
data:
  psqldump.sh: |
    #!/bin/bash
    DBS=$(psql -xl |awk /^Name/'{print $NF}')
    for DB in ${DBS}; do
      SCHEMAS=$(psql -d ${DB} -xc "\dn" |awk /^Name/'{print $NF}')
      for SCHEMA in ${SCHEMAS}; do
        echo "Dumping database '${DB}' from Schema '${SCHEMA}' into ${BACKUPDIR}/${PGHOST}_${SCHEMA}_${DB}_${ENVMNT}_$(date -I).sql"
        pg_dump -n "${SCHEMA}" ${DB} > ${BACKUPDIR}/${PGHOST}_${SCHEMA}_${DB}_${ENVMNT}_$(date -I).sql
      done
    done
    echo "Deleting dumps older than ${RETENTION} days"
    find ${BACKUPDIR} -name "*.sql" -mtime +${RETENTION} -exec rm -rf {} \;

CronJob:

apiVersion: v1
kind: Template
metadata:
  name: postgres-backup
  namespace: database
objects:
- kind: CronJob
  apiVersion: batch/v1beta1
  metadata:
    name: postgres-backup
    namespace: database
  spec:
    schedule: "0 3 * * *"
    successfulJobsHistoryLimit: 1
    jobTemplate:
      spec:
        template:
          metadata:
            namespace: database
          spec:
            containers:
            - name: postgres-dbbackup
              image: "postgres:11"
              env:
              - name: PGHOST
                value: "${_PGHOST}"
              - name: PGUSER
                value: "${_PGUSER}"
              - name: RETENTION
                value: "${_RETENTION}"
              - name: BACKUPDIR
                value: "${_BACKUPDIR}"
              command: ["/bin/bash", "-c", "/usr/local/bin/psqldump.sh"]
              volumeMounts:
              - mountPath: /usr/local/bin
                name: psqldump-volume
              - mountPath: /backup
                name: backup-volume
            volumes:
              - name: psqldump-volume
                configMap:
                  name: psqldump
                  defaultMode: 0755
              - name: backup-volume
                persistentVolumeClaim:
                  claimName: database-bkp
            restartPolicy: Never
parameters:
  - name: _PGHOST
    value: postgres
  - name: _PGUSER
    value: postgres
  - name: _RETENTION
    value: "30"
  - name: _BACKUPDIR
    value: "/backup"

PGHOST is the pod name of your data base. If you have a dedicated user and password for your backup, export the env vars PGUSER and PGPASS accordingly

Running the cronjob inside the same pod as your db is not a good idea (the pod where the db runs can be killed/respawned etc)

IMHO the best solution is to define a Cronjob in the same project as the db, the Job will use an official OpenShift base image with the OC CLI, and from there execute a script that will connect to the pod where the db runs (oc rsh..) and perform the backup

Or execute a script from outside OCP that will connect to the cluster (with a system account), then executeoc rsh <db pod name> <backup command>

Related