diff --git a/devops/Dockerfile b/devops/Dockerfile new file mode 100644 index 0000000..63d80cb --- /dev/null +++ b/devops/Dockerfile @@ -0,0 +1,3 @@ +FROM curlimages/curl +WORKDIR /opt/devops +ADD bin . diff --git a/devops/bin/k8s-pgdb.sh b/devops/bin/k8s-pgdb.sh new file mode 100755 index 0000000..a045072 --- /dev/null +++ b/devops/bin/k8s-pgdb.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +set -e + +if [ "$#" -lt 4 ] ;then + echo "Backup postgres database on k8s container with pg_dump and gzip" + echo + echo " Usage $0 [dbname]" + exit 1 +fi + +BACKUPGZ=$2 +APP=$3 +CONTAINER=$4 +DBNAME=${5-"$(basename "$BACKUPGZ" .sql.gz)"} + +POD=$(kubectl get pod --selector "app=$APP" | tail +2 | awk '{print $1}') +if [ -z "$POD" ] ; then + echo not pod found! + exit 1 +fi + +backup () { + kubectl exec "$POD" -c "$CONTAINER" -- pg_dump -U postgres --no-owner "$DBNAME" | gzip > "$BACKUPGZ" +} + +restore () { + kubectl exec "$POD" -c "$CONTAINER" -- psql postgres postgres -c "DROP DATABASE IF EXISTS $DBNAME" + kubectl exec "$POD" -c "$CONTAINER" -- psql postgres postgres -c "CREATE DATABASE $DBNAME" + kubectl exec -i "$POD" -c "$CONTAINER" -- sh -c "gunzip -c | psql $DBNAME postgres" < "$BACKUPGZ" +} + + +case $1 in + backup) + backup + ;; + restore) + restore + ;; +esac diff --git a/devops/bin/k8s-pgdball.sh b/devops/bin/k8s-pgdball.sh new file mode 100755 index 0000000..adfca05 --- /dev/null +++ b/devops/bin/k8s-pgdball.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +set -e + +if [ "$#" -lt 4 ] ;then + echo "Backup all postgres databases on k8s container with pg_dump and gzip" + echo + echo " Usage $0 [dbname]" + exit 1 +fi + +DIR=$(dirname "$(readlink -f "$0")") +BACKUPDIR=$2 +APP=$3 +CONTAINER=$4 + +POD=$(kubectl get pod --selector "app=$APP" | tail +2 | awk '{print $1}') +if [ -z "$POD" ] ; then + echo not pod found! + exit 1 +fi + +backup () { + mkdir -p "$BACKUPDIR" + for DBNAME in $( + kubectl exec "$POD" -c "$CONTAINER" -- \ + psql postgres postgres -c "SELECT datname FROM pg_database" | \ + tail +3 | head -n -2 + ); do + case $DBNAME in + postgres|template0|template1) + ;; + *) + echo "backing up $DBNAME to $BACKUPDIR/$DBNAME.sql.gz" + "$DIR/k8s-pgdb.sh" backup "$BACKUPDIR/$DBNAME.sql.gz" "$APP" "$CONTAINER" "$DBNAME" + ;; + esac + done +} + +restore () { + for BACKUPGZ in "$BACKUPDIR"/*.sql.gz ;do + "$DIR/pgdb.sh" restore "$BACKUPGZ" + done +} + + +case $1 in + backup) + backup + ;; + restore) + restore + ;; +esac diff --git a/devops/renew-cf-dns-record.sh b/devops/bin/renew-cf-dns-record.sh old mode 100644 new mode 100755 similarity index 96% rename from devops/renew-cf-dns-record.sh rename to devops/bin/renew-cf-dns-record.sh index f714c47..d40e917 --- a/devops/renew-cf-dns-record.sh +++ b/devops/bin/renew-cf-dns-record.sh @@ -22,4 +22,4 @@ curl -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RE -H "Content-Type: application/json" \ --data '{"type": "A", "name": "'"$DOMAIN"'", "content": "'"$IP"'"}' -echo "$IP" > /tmp/myip \ No newline at end of file +echo "$IP" > /tmp/myip diff --git a/devops/k8s-devops.yaml b/devops/k8s-devops.yaml new file mode 100644 index 0000000..4dc295e --- /dev/null +++ b/devops/k8s-devops.yaml @@ -0,0 +1,82 @@ +# update cloudflare dns record if ip changed on minutely basis +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: ddns +spec: + schedule: "*/1 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: renew-cf-dns-record + image: devops + imagePullPolicy: IfNotPresent + args: + - renew-cf-dns-record.sh + - {EMAIL} + - {APP_KEY} + - {ZONE_ID} + - {RECORD_ID} + - {DOMAIN} + volumeMounts: + - name: tmp + mountPath: /tmp + restartPolicy: OnFailure + volumes: + - name: tmp + hostPath: + path: /tmp +--- +# backup local data and remote postgres database at 6:00am everyday +apiVersion: batch/v1beta1 +kind: CronJob +metadata: + name: backup +spec: + schedule: "0 6 * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: backup-local-dir + image: devops + imagePullPolicy: IfNotPresent + args: + - backup-local-dir + - {BLD_ROTATE} + - {BLD_SRC_DIR} + - {BLD_DEST_DIR} + volumeMounts: + - name: bldsrcdir + mountPath: {BLD_SRC_DIR} + - name: blddestdir + mountPath: {BLD_DEST_DIR} + - name: backup-k8s-pgdbs + image: devops + imagePullPolicy: IfNotPresent + args: + - backup-k8s-pgdbs + - {BKP_ROTATE} + - {POD_APP_LABEL} + - {CONTAINER_NAME} + - {BKP_DEST_DIR} + volumeMounts: + - name: bkpdestdir + mountPath: {BKP_DEST_DIR} + restartPolicy: OnFailure + volumes: + - name: bldsrcdir + hostPath: + path: {BLD_SRC_DIR} + type: Directory + - name: blddestdir + hostPath: + path: {BLD_DEST_DIR} + type: DirectoryOrCreate + - name: bkpdestdir + hostPath: + path: {BKP_DEST_DIR} + type: DirectoryOrCreate