Few days ago, DigitalOcean announced PostgreSQL DBaaS, which is really nice, but even better, they promised soon availability of MySQL and Redis managed services. While we are waiting for this, I will describe in this article how to backup your Kubernetes MySQL database to Spaces, DigitalOcean's S3 compatible storage.

In my case, MySQL database, actually MariaDB is running as a cluster service on my Kubernetes cluster. First you have to create your Spaces storage and you should get an endpoint similar to this one https://mybucket.ams3.digitaloceanspaces.com. Next, under menu API, on the left hand side menu, you should create your Spaces keys. These values are needed to configure the backup cronjob.

Now we can start with the Kubernetes stuff. First let's create secret:

kubectl create secret generic mariadb-backup-secrets \
  --from-literal=spacesKey="XXX" \
  --from-literal=spacesSecret="YYY" \
  --from-literal=mariaDbPassword="ZZZ"
  • XXX is your Spaces key name
  • YYY is your Spaces secret for the key
  • ZZZ is your MySQL password (probably for user root if you want to backup all databases)

Now let's create Kubernetes CronJob:

---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: mariadb-backup
spec:
  schedule: "0 3 * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 2
  failedJobsHistoryLimit: 2
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: mysqldump
            image: schickling/mysql-backup-s3
            env:
              - name: S3_ENDPOINT
                value: https://ams3.digitaloceanspaces.com
              - name: S3_REGION
                value: ams3
              - name: S3_BUCKET
                value: mybucket
              - name: S3_PREFIX
                value: "mariadb-backup"
              - name: S3_ACCESS_KEY_ID
                valueFrom:
                  secretKeyRef:
                    name: mariadb-backup-secrets
                    key: spacesKey
              - name: S3_SECRET_ACCESS_KEY
                valueFrom:
                  secretKeyRef:
                    name: mariadb-backup-secrets
                    key: spacesSecret
              - name: MYSQL_HOST
                value: mariadb.default.svc.cluster.local
              - name: MYSQL_USER
                value: root
              - name: MYSQL_PASSWORD
                valueFrom:
                  secretKeyRef:
                    name: mariadb-backup-secrets
                    key: mariaDbPassword
              - name: MULTI_FILES
                value: "true"
          restartPolicy: OnFailure
  • shedule fields is crontab compatible format of the time when your job should run (see man 5 crontab)
  • S3_ENDPOINT is your endpoint without the Spaces name. If you got https://mybucket.ams3.digitaloceanspaces.com when you configured Spaces, you should extract mybucket here. Then next part of the URL is your region, which is in my case Amsterdam. So your S3_ENDPOINT should be https://ams3.digitaloceanspaces.com
  • S3_REGION seems to be optional, but you can set it anyways
  • S3_BUCKET is your Spaces name, let's sam mybucket
  • S3_PREFIX is a directory within your Spaces. You can create this directory at DigitalOcean interface and if not, it will be created automatically after the first storage to it. You can have multiple directories for different purposes.
  • S3_ACCESS_KEY_ID is your key name from Spaces
  • S3_SECRET_ACCESS_KEY is your secret from Spaces
  • MULTI_FILES defines weather all databases will be backed up in the same file or in separate files. I choosed to backup in separate files so that I can easily restore if needed.

Your Kubernetes CronJob will run at defined times, but you can also trigger it manually in your Dashboard or in your shell:

kubectl create job --from=cronjob/mariadb-backup mariadb-backup-manual-001