diff --git a/charts/tidb-backup/templates/backup-job.yaml b/charts/tidb-backup/templates/backup-job.yaml index 8338d15d0f..6481117d21 100644 --- a/charts/tidb-backup/templates/backup-job.yaml +++ b/charts/tidb-backup/templates/backup-job.yaml @@ -46,16 +46,16 @@ spec: - name: GOOGLE_APPLICATION_CREDENTIALS value: /gcp/credentials.json {{- end }} - {{- if .Values.ceph }} + {{- if or .Values.ceph .Values.s3 }} - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: {{ .Values.ceph.secretName }} + name: {{ or .Values.ceph.secretName .Values.s3.secretName }} key: access_key - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: {{ .Values.ceph.secretName }} + name: {{ or .Values.ceph.secretName .Values.s3.secretName }} key: secret_key {{- end }} - name: TIDB_USER diff --git a/charts/tidb-backup/templates/restore-job.yaml b/charts/tidb-backup/templates/restore-job.yaml index 52bbfec597..5c1f927c02 100644 --- a/charts/tidb-backup/templates/restore-job.yaml +++ b/charts/tidb-backup/templates/restore-job.yaml @@ -44,16 +44,16 @@ spec: - name: GOOGLE_APPLICATION_CREDENTIALS value: /gcp/credentials.json {{- end }} - {{- if .Values.ceph }} + {{- if or .Values.ceph .Values.s3 }} - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: {{ .Values.ceph.secretName }} + name: {{ or .Values.ceph.secretName .Values.s3.secretName }} key: access_key - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: {{ .Values.ceph.secretName }} + name: {{ or .Values.ceph.secretName .Values.s3.secretName }} key: secret_key {{- end }} - name: TIDB_USER diff --git a/charts/tidb-backup/templates/scripts/_start_backup.sh.tpl b/charts/tidb-backup/templates/scripts/_start_backup.sh.tpl index d3f324c72b..8c6c8e8843 100644 --- a/charts/tidb-backup/templates/scripts/_start_backup.sh.tpl +++ b/charts/tidb-backup/templates/scripts/_start_backup.sh.tpl @@ -48,3 +48,11 @@ uploader \ --endpoint={{ .Values.ceph.endpoint }} \ --backup-dir=${dirname} {{- end }} + +{{- if .Values.s3 }} +uploader \ + --cloud=aws \ + --region={{ .Values.s3.region }} \ + --bucket={{ .Values.s3.bucket }} \ + --backup-dir=${dirname} +{{- end }} diff --git a/charts/tidb-backup/templates/scripts/_start_restore.sh.tpl b/charts/tidb-backup/templates/scripts/_start_restore.sh.tpl index 99e350cf0e..e32c57d105 100644 --- a/charts/tidb-backup/templates/scripts/_start_restore.sh.tpl +++ b/charts/tidb-backup/templates/scripts/_start_restore.sh.tpl @@ -21,6 +21,15 @@ downloader \ --destDir=/data {{- end }} +{{- if .Values.s3 }} +downloader \ + --cloud=aws \ + --region={{ .Values.s3.region }} \ + --bucket={{ .Values.s3.bucket }} \ + --srcDir=${BACKUP_NAME} \ + --destDir=/data +{{- end }} + count=1 while ! mysql -u ${TIDB_USER} -h `eval echo '${'$host'}'` -P 4000 -p${TIDB_PASSWORD} -e 'select version();' do diff --git a/charts/tidb-backup/values.yaml b/charts/tidb-backup/values.yaml index 88b07a1d45..73af407c9a 100644 --- a/charts/tidb-backup/values.yaml +++ b/charts/tidb-backup/values.yaml @@ -44,7 +44,7 @@ initialCommitTs: "" restoreOptions: "-t 16" # By default, the backup/restore uses PV to store/load backup data -# You can choose to store/load backup data to/from gcp or ceph bucket by enabling the following corresponding section: +# You can choose to store/load backup data to/from gcp, ceph or s3 bucket by enabling the following corresponding section: # backup to or restore from gcp bucket, the backup path is in the form of - gcp: {} @@ -57,7 +57,7 @@ gcp: {} # kubectl create secret generic gcp-backup-secret --namespace= --from-file=./credentials.json # secretName: gcp-backup-secret -# backup to or restore from ceph bucket, the backup path is in the form of - +# backup to or restore from ceph bucket, the backup path is in the form of - ceph: {} # endpoint: "" # bucket: "" @@ -65,3 +65,12 @@ ceph: {} # You can create the secret by: # kubectl create secret generic ceph-backup-secret --namespace= --from-literal=access_key= --from-literal=secret_key= # secretName: ceph-backup-secret + +# backup to or restore from s3 bucket, the backup path is in the form of - +s3: {} + # region: "" + # bucket: "" + # secretName is the name of the secret which stores s3 object store access key and secret key + # You can create the secret by: + # kubectl create secret generic s3-backup-secret --namespace= --from-literal=access_key= --from-literal=secret_key= + # secretName: s3-backup-secret \ No newline at end of file diff --git a/charts/tidb-cluster/templates/scheduled-backup-cronjob.yaml b/charts/tidb-cluster/templates/scheduled-backup-cronjob.yaml index 6ab29aad78..7fab17433a 100644 --- a/charts/tidb-cluster/templates/scheduled-backup-cronjob.yaml +++ b/charts/tidb-cluster/templates/scheduled-backup-cronjob.yaml @@ -64,16 +64,16 @@ spec: - name: GOOGLE_APPLICATION_CREDENTIALS value: /gcp/credentials.json {{- end }} - {{- if .Values.scheduledBackup.ceph }} + {{- if or .Values.scheduledBackup.ceph .Values.scheduledBackup.s3 }} - name: AWS_ACCESS_KEY_ID valueFrom: secretKeyRef: - name: {{ .Values.scheduledBackup.ceph.secretName }} + name: {{ or .Values.scheduledBackup.ceph.secretName .Values.scheduledBackup.s3.secretName }} key: access_key - name: AWS_SECRET_ACCESS_KEY valueFrom: secretKeyRef: - name: {{ .Values.scheduledBackup.ceph.secretName }} + name: {{ or .Values.scheduledBackup.ceph.secretName .Values.scheduledBackup.s3.secretName }} key: secret_key {{- end }} - name: TIDB_USER diff --git a/charts/tidb-cluster/templates/scripts/_start_scheduled_backup.sh.tpl b/charts/tidb-cluster/templates/scripts/_start_scheduled_backup.sh.tpl index b30db653bd..632237adff 100755 --- a/charts/tidb-cluster/templates/scripts/_start_scheduled_backup.sh.tpl +++ b/charts/tidb-cluster/templates/scripts/_start_scheduled_backup.sh.tpl @@ -46,3 +46,11 @@ uploader \ --endpoint={{ .Values.scheduledBackup.ceph.endpoint }} \ --backup-dir=${backupPath} {{- end }} + +{{- if .Values.scheduledBackup.s3 }} +uploader \ + --cloud=aws \ + --region={{ .Values.scheduledBackup.s3.region }} \ + --bucket={{ .Values.scheduledBackup.s3.bucket }} \ + --backup-dir=${backupPath} +{{- end }} diff --git a/charts/tidb-cluster/values.yaml b/charts/tidb-cluster/values.yaml index 09323e7503..2c8144ad0b 100644 --- a/charts/tidb-cluster/values.yaml +++ b/charts/tidb-cluster/values.yaml @@ -481,6 +481,15 @@ scheduledBackup: # kubectl create secret generic ceph-backup-secret --from-literal=access_key= --from-literal=secret_key= # secretName: ceph-backup-secret + # backup to s3 + s3: {} + # region: "" + # bucket: "" + # secretName is the name of the secret which stores s3 object store access key and secret key + # You can create the secret by: + # kubectl create secret generic s3-backup-secret --from-literal=access_key= --from-literal=secret_key= + # secretName: s3-backup-secret + metaInstance: "{{ $labels.instance }}" metaType: "{{ $labels.type }}" metaValue: "{{ $value }}" diff --git a/deploy/aliyun/templates/tidb-cluster-values.yaml.tpl b/deploy/aliyun/templates/tidb-cluster-values.yaml.tpl index e7ac10ba21..a7ceba6e4a 100644 --- a/deploy/aliyun/templates/tidb-cluster-values.yaml.tpl +++ b/deploy/aliyun/templates/tidb-cluster-values.yaml.tpl @@ -359,7 +359,7 @@ scheduledBackup: binlogImage: "pingcap/tidb-binlog:${cluster_version}" binlogImagePullPolicy: IfNotPresent # https://github.com/tennix/tidb-cloud-backup - mydumperImage: pingcap/tidb-cloud-backup:latest + mydumperImage: pingcap/tidb-cloud-backup:20190610 mydumperImagePullPolicy: IfNotPresent # storageClassName is a StorageClass provides a way for administrators to describe the "classes" of storage they offer. # different classes might map to quality-of-service levels, or to backup policies, @@ -402,6 +402,15 @@ scheduledBackup: # kubectl create secret generic ceph-backup-secret --from-literal=access_key= --from-literal=secret_key= # secretName: ceph-backup-secret + # backup to s3 + s3: {} + # region: "" + # bucket: "" + # secretName is the name of the secret which stores s3 object store access key and secret key + # You can create the secret by: + # kubectl create secret generic s3-backup-secret --from-literal=access_key= --from-literal=secret_key= + # secretName: s3-backup-secret + metaInstance: "{{ $labels.instance }}" metaType: "{{ $labels.type }}" metaValue: "{{ $value }}" diff --git a/deploy/aws/templates/tidb-cluster-values.yaml.tpl b/deploy/aws/templates/tidb-cluster-values.yaml.tpl index 280be11311..156a7f5fdf 100644 --- a/deploy/aws/templates/tidb-cluster-values.yaml.tpl +++ b/deploy/aws/templates/tidb-cluster-values.yaml.tpl @@ -360,7 +360,7 @@ scheduledBackup: binlogImage: "pingcap/tidb-binlog:${cluster_version}" binlogImagePullPolicy: IfNotPresent # https://github.com/tennix/tidb-cloud-backup - mydumperImage: pingcap/tidb-cloud-backup:latest + mydumperImage: pingcap/tidb-cloud-backup:20190610 mydumperImagePullPolicy: IfNotPresent # storageClassName is a StorageClass provides a way for administrators to describe the "classes" of storage they offer. # different classes might map to quality-of-service levels, or to backup policies, @@ -403,6 +403,15 @@ scheduledBackup: # kubectl create secret generic ceph-backup-secret --from-literal=access_key= --from-literal=secret_key= # secretName: ceph-backup-secret + # backup to s3 + s3: {} + # region: "" + # bucket: "" + # secretName is the name of the secret which stores s3 object store access key and secret key + # You can create the secret by: + # kubectl create secret generic s3-backup-secret --from-literal=access_key= --from-literal=secret_key= + # secretName: s3-backup-secret + metaInstance: "{{ $labels.instance }}" metaType: "{{ $labels.type }}" metaValue: "{{ $value }}" diff --git a/deploy/gcp/templates/tidb-cluster-values.yaml.tpl b/deploy/gcp/templates/tidb-cluster-values.yaml.tpl index c3f02294ac..bc44382350 100644 --- a/deploy/gcp/templates/tidb-cluster-values.yaml.tpl +++ b/deploy/gcp/templates/tidb-cluster-values.yaml.tpl @@ -359,7 +359,7 @@ scheduledBackup: binlogImage: "pingcap/tidb-binlog:${cluster_version}" binlogImagePullPolicy: IfNotPresent # https://github.com/tennix/tidb-cloud-backup - mydumperImage: pingcap/tidb-cloud-backup:latest + mydumperImage: pingcap/tidb-cloud-backup:20190610 mydumperImagePullPolicy: IfNotPresent # storageClassName is a StorageClass provides a way for administrators to describe the "classes" of storage they offer. # different classes might map to quality-of-service levels, or to backup policies, @@ -402,6 +402,15 @@ scheduledBackup: # kubectl create secret generic ceph-backup-secret --from-literal=access_key= --from-literal=secret_key= # secretName: ceph-backup-secret + # backup to s3 + s3: {} + # region: "" + # bucket: "" + # secretName is the name of the secret which stores s3 object store access key and secret key + # You can create the secret by: + # kubectl create secret generic s3-backup-secret --from-literal=access_key= --from-literal=secret_key= + # secretName: s3-backup-secret + metaInstance: "{{ $labels.instance }}" metaType: "{{ $labels.type }}" metaValue: "{{ $value }}" diff --git a/docs/backup-restore.md b/docs/backup-restore.md index 1ba5f1b1f2..b236dcd53c 100644 --- a/docs/backup-restore.md +++ b/docs/backup-restore.md @@ -12,7 +12,7 @@ Currently, TiDB Operator only supports automatic [restore operation](#restore) f Full backup uses `mydumper` to make a logical backup of TiDB cluster. The backup job will create a PVC([PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims), the same below) to store backup data. -By default, the backup uses PV ([Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistent-volumes)) to store the backup data. You can also store the backup data to [Google Cloud Storage](https://cloud.google.com/storage/) bucket or [Ceph Object Storage](https://ceph.com/ceph-storage/object-storage/) by changing the configuration. This way the PV temporarily stores backup data before it is placed in object storage. Refer to [TiDB cluster Backup configuration](./references/tidb-backup-configuration.md) for full configuration guide of backup and restore. +By default, the backup uses PV ([Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistent-volumes)) to store the backup data. You can also store the backup data to [Google Cloud Storage](https://cloud.google.com/storage/) bucket, [Ceph Object Storage](https://ceph.com/ceph-storage/object-storage/) or [Amazon S3](https://aws.amazon.com/s3/) by changing the configuration. This way the PV temporarily stores backup data before it is placed in object storage. Refer to [TiDB cluster Backup configuration](./references/tidb-backup-configuration.md) for full configuration guide of backup and restore. You can either set up a scheduled full backup or take a full backup in an ad-hoc manner. @@ -77,7 +77,7 @@ For backups stored in PV, you can view the PVs by using the following command: $ kubectl get pvc -n ${namespace} -l app.kubernetes.io/component=backup,pingcap.com/backup-cluster-name=${cluster_name} ``` -If you store your backup data to [Google Cloud Storage](https://cloud.google.com/storage/) or [Ceph Object Storage](https://ceph.com/ceph-storage/object-storage/), you can view the backups by using the related GUI or CLI tool. +If you store your backup data to [Google Cloud Storage](https://cloud.google.com/storage/), [Ceph Object Storage](https://ceph.com/ceph-storage/object-storage/) or [Amazon S3](https://aws.amazon.com/s3/), you can view the backups by using the related GUI or CLI tool. ## Restore @@ -85,7 +85,7 @@ The helm chart `charts/tidb-backup` helps restore a TiDB cluster using backup da * Set `clusterName` to the target TiDB cluster name * Set `mode` to `restore` -* Set `name` to the backup name you want to restore([view backups](#view-backups) helps you view all the backups available). If the backup is stored in `Google Cloud Storage` or `Ceph Object Storage`, you must configure the corresponding section too (you might continue to use the same configuration you set in the [adhoc full backup](#ad-hoc-full-backup)). +* Set `name` to the backup name you want to restore([view backups](#view-backups) helps you view all the backups available). If the backup is stored in `Google Cloud Storage`, `Ceph Object Storage` or `Amazon S3`, you must configure the corresponding section too (you might continue to use the same configuration you set in the [adhoc full backup](#ad-hoc-full-backup)). Create a Kubernetes [Secret](https://kubernetes.io/docs/concepts/configuration/secret/) containing the user and password that has the privilege to restore the database (skip this if you have already created one in the [adhoc full backup](#ad-hoc-full-backup) section): diff --git a/images/tidb-operator-e2e/tidb-cluster-values.yaml b/images/tidb-operator-e2e/tidb-cluster-values.yaml index f31b791819..7e688a6944 100644 --- a/images/tidb-operator-e2e/tidb-cluster-values.yaml +++ b/images/tidb-operator-e2e/tidb-cluster-values.yaml @@ -224,7 +224,7 @@ fullbackup: binlogImage: pingcap/tidb-binlog:v3.0.0-rc.1 binlogImagePullPolicy: IfNotPresent # https://github.com/tennix/tidb-cloud-backup - mydumperImage: pingcap/tidb-cloud-backup:latest + mydumperImage: pingcap/tidb-cloud-backup:20190610 mydumperImagePullPolicy: IfNotPresent # storageClassName is a StorageClass provides a way for administrators to describe the "classes" of storage they offer. # different classes might map to quality-of-service levels, or to backup policies, diff --git a/tests/actions.go b/tests/actions.go index 12d8cbe16e..b57ae3da15 100644 --- a/tests/actions.go +++ b/tests/actions.go @@ -2032,7 +2032,7 @@ func (oa *operatorActions) getBackupDir(info *TidbClusterConfig) ([]string, erro Containers: []corev1.Container{ { Name: getBackupDirPodName, - Image: "pingcap/tidb-cloud-backup:latest", + Image: "pingcap/tidb-cloud-backup:20190610", Command: []string{"sleep", "3000"}, VolumeMounts: []corev1.VolumeMount{ {