From 04c2135a98c0d5b93f8edb8cfa985d62b30dcde0 Mon Sep 17 00:00:00 2001 From: kubeJocker <102039539+kubejocker@users.noreply.github.com> Date: Fri, 26 Jul 2024 10:43:07 +0800 Subject: [PATCH] feature: add backup for zookeeper (#851) (cherry picked from commit f1da95b13560ec3d57e0e98007883fea824bcf1d) --- addons/zookeeper/config/zookeeper-config.tpl | 11 +++++-- addons/zookeeper/dataprotection/backup.sh | 22 +++++++++++++ addons/zookeeper/dataprotection/restore.sh | 19 ++++++++++++ .../zookeeper/templates/backupactionset.yaml | 31 +++++++++++++++++++ .../templates/backuppolicytemplate.yaml | 24 ++++++++++++++ addons/zookeeper/templates/cmpd.yaml | 29 +++++++++++++---- addons/zookeeper/values.yaml | 6 +++- 7 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 addons/zookeeper/dataprotection/backup.sh create mode 100644 addons/zookeeper/dataprotection/restore.sh create mode 100644 addons/zookeeper/templates/backupactionset.yaml create mode 100644 addons/zookeeper/templates/backuppolicytemplate.yaml diff --git a/addons/zookeeper/config/zookeeper-config.tpl b/addons/zookeeper/config/zookeeper-config.tpl index 60b76b49f..bf18b15e5 100644 --- a/addons/zookeeper/config/zookeeper-config.tpl +++ b/addons/zookeeper/config/zookeeper-config.tpl @@ -9,9 +9,9 @@ syncLimit=30 # the directory where the snapshot is stored. # do not use /tmp for storage, /tmp here is just # example sakes. -dataDir=/bitnami/zookeeper/data +dataDir={{ .ZOOKEEPER_DATA_DIR }} # -dataLogDir=/bitnami/zookeeper/log +dataLogDir={{ .ZOOKEEPER_DATA_LOG_DIR }} # the port at which the clients will connect clientPort=2181 # the maximum number of client connections. @@ -48,7 +48,12 @@ maxClientCnxns=500 {{- $name := index (splitList "." $fqdn) 0 }} {{- $tokens := splitList "-" $name }} {{- $ordinal := index $tokens (sub (len $tokens) 1) }} - {{- printf "server.%s=%s:2888:3888:participant;0.0.0.0:2181\n" $ordinal $fqdn }} + {{- if ge $i 3 }} + {{- printf "server.%s=%s:2888:3888:observer;0.0.0.0:2181\n" $ordinal $fqdn }} + {{- printf "peerType=observer\n" }} + {{- else }} + {{- printf "server.%s=%s:2888:3888:participant;0.0.0.0:2181\n" $ordinal $fqdn }} + {{- end }} {{- end }} # logging diff --git a/addons/zookeeper/dataprotection/backup.sh b/addons/zookeeper/dataprotection/backup.sh new file mode 100644 index 000000000..6a1e82441 --- /dev/null +++ b/addons/zookeeper/dataprotection/backup.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e +set -o pipefail +export PATH="$PATH:$DP_DATASAFED_BIN_PATH" +# if the script exits with a non-zero exit code, touch a file to indicate that the backup failed, +# the sync progress container will check this file and exit if it exists +function handle_exit() { + exit_code=$? + if [ $exit_code -ne 0 ]; then + echo "failed with exit code $exit_code" + touch "${DP_BACKUP_INFO_FILE}.exit" + exit 1 + fi +} +trap handle_exit EXIT + +java -cp /zoocreeper.jar com.boundary.zoocreeper.Backup \ +-z ${DP_DB_HOST}:${MY_ZOOKEEPER_ZOOKEEPER_SERVICE_PORT_CLIENT} --compress | \ +datasafed push -z zstd-fastest - "${DP_BACKUP_NAME}.backup.json" + +TOTAL_SIZE=$(datasafed stat / | grep TotalSize | awk '{print $2}') +echo "{\"totalSize\":\"$TOTAL_SIZE\"}" >"${DP_BACKUP_INFO_FILE}" \ No newline at end of file diff --git a/addons/zookeeper/dataprotection/restore.sh b/addons/zookeeper/dataprotection/restore.sh new file mode 100644 index 000000000..430b6522d --- /dev/null +++ b/addons/zookeeper/dataprotection/restore.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e +set -o pipefail + +export PATH="$PATH:$DP_DATASAFED_BIN_PATH" +TMP_DIR=/tmp/zookeeper/restore +mkdir -p ${TMP_DIR} + +backupFileName="${DP_BACKUP_NAME}.backup.json" +datasafed pull -d zstd-fastest "${backupFileName}" ${TMP_DIR}/backup.json + +touch ${ZOOKEEPER_DATA_DIR}/.restore_new_cluster + +java -cp /zoocreeper.jar com.boundary.zoocreeper.Restore \ +-z ${KB_CLUSTER_COMP_NAME}:${DP_DB_PORT} -f ${TMP_DIR}/backup.json \ +--overwrite-existing --compress --exclude /zookeeper/config* + +rm -rf ${TMP_DIR} +rm -rf ${ZOOKEEPER_DATA_DIR}/.restore_new_cluster \ No newline at end of file diff --git a/addons/zookeeper/templates/backupactionset.yaml b/addons/zookeeper/templates/backupactionset.yaml new file mode 100644 index 000000000..7262ab410 --- /dev/null +++ b/addons/zookeeper/templates/backupactionset.yaml @@ -0,0 +1,31 @@ +apiVersion: dataprotection.kubeblocks.io/v1alpha1 +kind: ActionSet +metadata: + name: zookeeper-backup-zoocreeper + labels: + {{- include "zookeeper.labels" . | nindent 4 }} +spec: + backupType: Full + backup: + backupData: + image: {{ .Values.images.registry | default "docker.io" }}/apecloud/zoocreeper:1.0.1 + runOnTargetPodNode: true + command: + - sh + - -c + - | + {{- .Files.Get "dataprotection/backup.sh" | nindent 10 }} + syncProgress: + enabled: true + intervalSeconds: 5 + + restore: + postReady: + - job: + image: {{ .Values.images.registry | default "docker.io" }}/apecloud/zoocreeper:1.0.1 + runOnTargetPodNode: true + command: + - sh + - -c + - | + {{- .Files.Get "dataprotection/restore.sh" | nindent 14 }} \ No newline at end of file diff --git a/addons/zookeeper/templates/backuppolicytemplate.yaml b/addons/zookeeper/templates/backuppolicytemplate.yaml new file mode 100644 index 000000000..e9f66b7f9 --- /dev/null +++ b/addons/zookeeper/templates/backuppolicytemplate.yaml @@ -0,0 +1,24 @@ +apiVersion: apps.kubeblocks.io/v1alpha1 +kind: BackupPolicyTemplate +metadata: + name: {{ include "zookeeper.fullname" . }}-backup-policy-template + labels: + {{- include "zookeeper.labels" . | nindent 4 }} + service-kind/zookeeper: "true" + annotations: + dataprotection.kubeblocks.io/is-default-policy-template: "true" +spec: + backupPolicies: + - componentDefs: [zookeeper] + target: + role: follower + backupMethods: + - name: zoocreeper + snapshotVolumes: false + actionSetName: zookeeper-backup-zoocreeper + targetVolumes: + volumeMounts: + - name: data + mountPath: /bitnami/zookeeper/data + - name: snapshot-log + mountPath: /bitnami/zookeeper/log \ No newline at end of file diff --git a/addons/zookeeper/templates/cmpd.yaml b/addons/zookeeper/templates/cmpd.yaml index 5eda6ce9c..e1e4a175e 100644 --- a/addons/zookeeper/templates/cmpd.yaml +++ b/addons/zookeeper/templates/cmpd.yaml @@ -30,6 +30,17 @@ spec: port: 2888 - name: http port: 8080 + - name: ordinal + serviceName: ordinal + spec: + ports: + - name: client + port: 2181 + - name: quorum + port: 2888 + - name: http + port: 8080 + podService: true roles: - name: leader @@ -72,6 +83,10 @@ spec: fi runtime: + volumes: + - name: snapshot-log + emptyDir: {} + securityContext: fsGroup: 0 runAsGroup: 0 @@ -148,8 +163,10 @@ spec: volumeMounts: - name: data mountPath: /bitnami/zookeeper/data - - name: log + - name: snapshot-log mountPath: /bitnami/zookeeper/log + - name: log + mountPath: /opt/bitnami/zookeeper/logs - name: config mountPath: /opt/bitnami/zookeeper/conf/zoo.cfg subPath: zoo.cfg @@ -166,12 +183,12 @@ spec: value: {{ .Values.metrics.enabled | quote }} - name: ZOOKEEPER_METRICS_PORT value: {{ .Values.metrics.port | quote }} + - name: ZOOKEEPER_DATA_DIR + value: {{ .Values.zookeeper.dataDir }} + - name: ZOOKEEPER_DATA_LOG_DIR + value: {{ .Values.zookeeper.dataLogDir }} + - volumes: - - name: data - needSnapshot: true - - name: log - needSnapshot: true configs: - name: zookeeper-config namespace: {{ .Release.Namespace }} diff --git a/addons/zookeeper/values.yaml b/addons/zookeeper/values.yaml index a29295f60..5750c7ef4 100644 --- a/addons/zookeeper/values.yaml +++ b/addons/zookeeper/values.yaml @@ -11,4 +11,8 @@ images: metrics: enabled: true - port: 7000 \ No newline at end of file + port: 7000 + +zookeeper: + dataDir: /bitnami/zookeeper/data + dataLogDir: /bitnami/zookeeper/log \ No newline at end of file