Skip to content

Commit

Permalink
*: support backup/restore with NFS radondb#148
Browse files Browse the repository at this point in the history
  • Loading branch information
acekingke committed Oct 19, 2021
1 parent 68d361e commit 8c61da3
Show file tree
Hide file tree
Showing 24 changed files with 405 additions and 22 deletions.
7 changes: 6 additions & 1 deletion api/v1alpha1/backup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ type BackupSpec struct {
Image string `json:"image"`

// HostName represents the host for which to take backup
HostName string `json:"hostname"`
// If is empty, is use leader HostName
HostName string `json:"hostname,omitempty"`

// Represents the name of backup to NFS
// +optional
BackupToNFS string `json:"BackupToNFS,omitempty"`

// ClusterName represents the cluster name to backup
ClusterName string `json:"clustname"`
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha1/mysqlcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ type MysqlClusterSpec struct {
// Represents the name of the cluster restore from backup path
// +optional
RestoreFrom string `json:"restoreFrom,omitempty"`

// Represents the name of the cluster restore from NFS
// +optional
RestoreFromNFS string `json:"restoreFromNFS,omitempty"`
}

// MysqlOpts defines the options of MySQL container.
Expand Down
10 changes: 7 additions & 3 deletions backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ func (b *Backup) GetNameForJob() string {
return fmt.Sprintf("%s-backup", b.Name)
}

// Create the backup Domain Name.
func (b *Backup) GetBackupURL(cluster_name string, hostname string) string {
return fmt.Sprintf("%s.%s-mysql.%s:%v", hostname, cluster_name, b.Namespace, utils.XBackupPort)
// Create the backup Domain Name or leader DNS.
func (b *Backup) GetBackupURL(clusterName string, hostName string) string {
if len(hostName) != 0 {
return fmt.Sprintf("%s.%s-mysql.%s:%v", hostName, clusterName, b.Namespace, utils.XBackupPort)
} else {
return fmt.Sprintf("%s-leader.%s:%v", clusterName, b.Namespace, utils.XBackupPort)
}
}
38 changes: 35 additions & 3 deletions backup/syncer/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,41 @@ func (s *jobSyncer) ensurePodSpec(in corev1.PodSpec) corev1.PodSpec {
sctName := fmt.Sprintf("%s-secret", s.backup.Spec.ClusterName)
in.Containers[0].Name = utils.ContainerBackupName
in.Containers[0].Image = s.backup.Spec.Image
in.Containers[0].Args = []string{
"request_a_backup",
s.backup.GetBackupURL(s.backup.Spec.ClusterName, s.backup.Spec.HostName),

if len(s.backup.Spec.BackupToNFS) != 0 {
// add volumn about pvc
in.Volumes = []corev1.Volume{
{
Name: utils.XtrabackupPV,
VolumeSource: corev1.VolumeSource{
NFS: &corev1.NFSVolumeSource{
Server: s.backup.Spec.BackupToNFS,
Path: "/",
},
},
},
}
//"rm -rf /backup/*;curl --user sys_backups:sys_backups sample-mysql-0.sample-mysql.default:8082/download|xbstream -x -C /backup"
in.Containers[0].Command = []string{
"/bin/bash", "-c", "--",
}
var backupToDir string = utils.BuildBackupName()
in.Containers[0].Args = []string{
fmt.Sprintf("mkdir -p /backup/%s;curl --user $BACKUP_USER:$BACKUP_PASSWORD %s/download|xbstream -x -C /backup/%s; exit ${PIPESTATUS[0]}",
backupToDir, s.backup.GetBackupURL(s.backup.Spec.ClusterName, s.backup.Spec.HostName), backupToDir),
}
in.Containers[0].VolumeMounts = []corev1.VolumeMount{
{
Name: utils.XtrabackupPV,
MountPath: utils.XtrabckupLocal,
},
}
} else {
// in.Containers[0].ImagePullPolicy = s.opt.ImagePullPolicy
in.Containers[0].Args = []string{
"request_a_backup",
s.backup.GetBackupURL(s.backup.Spec.ClusterName, s.backup.Spec.HostName),
}
}
var optTrue bool = true
in.Containers[0].Env = []corev1.EnvVar{
Expand Down
5 changes: 4 additions & 1 deletion charts/mysql-operator/crds/mysql.radondb.com_backups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ spec:
spec:
description: BackupSpec defines the desired state of Backup
properties:
BackupToNFS:
description: Represents the name of backup to NFS
type: string
clustname:
description: ClusterName represents the cluster name to backup
type: string
Expand All @@ -46,14 +49,14 @@ spec:
type: integer
hostname:
description: HostName represents the host for which to take backup
If is empty, is use leader HostName
type: string
image:
default: radondb/mysql-sidecar:latest
description: To specify the image that will be used for sidecar container.
type: string
required:
- clustname
- hostname
type: object
status:
description: BackupStatus defines the observed state of Backup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,9 @@ spec:
description: Represents the name of the cluster restore from backup
path
type: string
restoreFromNFS:
description: Represents the name of the cluster restore from NFS
type: string
xenonOpts:
default:
admitDefeatHearbeatCount: 5
Expand Down
5 changes: 4 additions & 1 deletion config/crd/bases/mysql.radondb.com_backups.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ spec:
spec:
description: BackupSpec defines the desired state of Backup
properties:
BackupToNFS:
description: Represents the name of backup to NFS
type: string
clustname:
description: ClusterName represents the cluster name to backup
type: string
Expand All @@ -46,14 +49,14 @@ spec:
type: integer
hostname:
description: HostName represents the host for which to take backup
If is empty, is use leader HostName
type: string
image:
default: radondb/mysql-sidecar:latest
description: To specify the image that will be used for sidecar container.
type: string
required:
- clustname
- hostname
type: object
status:
description: BackupStatus defines the observed state of Backup
Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/mysql.radondb.com_mysqlclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,9 @@ spec:
description: Represents the name of the cluster restore from backup
path
type: string
restoreFromNFS:
description: Represents the name of the cluster restore from NFS
type: string
xenonOpts:
default:
admitDefeatHearbeatCount: 5
Expand Down
2 changes: 1 addition & 1 deletion config/samples/backup_secret.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
kind: Secret
apiVersion: v1
apiVersion: mysql.radondb.com/v1alpha1
metadata:
name: sample-backup-secret
namespace: default
Expand Down
2 changes: 2 additions & 0 deletions config/samples/mysql_v1alpha1_backup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ metadata:
spec:
# Add fields here
image: radondb/mysql-sidecar:latest
# hostname if empty, use the leader as hostname
hostname: sample-mysql-0
clustname: sample
# BackupToNFS: "IP of NFS server"
2 changes: 2 additions & 0 deletions config/samples/mysql_v1alpha1_mysqlcluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ spec:
# if you want create mysqlcluster from S3, uncomment and fill the directory in S3 bucket below:
# restoreFrom:

# Restore from NFS, uncomment below and set the ip of NFS server
# restoreFromNFS:
mysqlOpts:
rootPassword: "RadonDB@123"
rootHost: localhost
Expand Down
32 changes: 32 additions & 0 deletions config/samples/nfs_rc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
apiVersion: v1
kind: ReplicationController
metadata:
name: nfs-server
spec:
replicas: 1
selector:
role: nfs-server
template:
metadata:
labels:
role: nfs-server
spec:
containers:
- name: nfs-server
image: gcr.azk8s.cn/google_containers/volume-nfs:0.8
ports:
- name: nfs
containerPort: 2049
- name: mountd
containerPort: 20048
- name: rpcbind
containerPort: 111
securityContext:
privileged: true
volumeMounts:
- mountPath: /exports
name: nfs-export-fast
volumes:
- name: nfs-export-fast
persistentVolumeClaim:
claimName: neosan1
14 changes: 14 additions & 0 deletions config/samples/nfs_server.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
kind: Service
apiVersion: v1
metadata:
name: nfs-server
spec:
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
selector:
role: nfs-server
56 changes: 56 additions & 0 deletions docs/deploy_backup_restore_nfs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# mysql-operator

## Quickstart for NFS backup

### Create NFS server
first create your PVC, such as "neosan1", fill it to `config/samples/nfs_rc.yaml `
```yaml
...
volumes:
- name: nfs-export-fast
persistentVolumeClaim:
claimName: neosan1
```
```shell
# create the nfs pod
kubectl apply -f config/samples/nfs_rc.yaml
# create the nfs service
kubectl apply -f config/samples/nfs_server.yaml
```
if create the nfs server successful, get the then:

## config `mysql_v1alpha1_backup.yaml ` and backup
Add field in `mysql_v1alpha1_backup.yaml ` as follow:
```yaml
BackupToNFS: "IP of NFS server"
```
use commadn as follow to backup
```shell
kubectl apply -f config/samples/mysql_v1alpha1_backup.yaml
```

## Restore cluster from exist NFS backup
first, configure the `mysql_v1alpha1_cluster.yaml`, uncomment the `restoreFromNFS` field:
```yaml
....
restoreFrom: "backup_202196152239"
restoreFromNFS : 10.96.253.82
```
`backup_202196152239` is the nfs server backup path, change it to yours.
the `10.96.253.82` is the NFS server ip, change it to yours.
use command as follow to create cluster from NFS server backup copy:

## build your own image
such as :
```
docker build -f Dockerfile.sidecar -t acekingke/sidecar:0.1 . && docker push acekingke/sidecar:0.1
docker build -t acekingke/controller:0.1 . && docker push acekingke/controller:0.1
```
you can replace acekingke/sidecar:0.1 with your own tag

## deploy your own manager
```shell
make manifests
make install
make deploy IMG=acekingke/controller:0.1 KUSTOMIZE=~/radondb-mysql-kubernetes/bin/kustomize
```
45 changes: 43 additions & 2 deletions docs/deploy_backup_restore_s3.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# mysql-operator

## Quickstart for backup
## Quickstart for backup S3

Install the operator named `test`:

```shell
helm install test charts/mysql-operator
```

### configure backup
### configure backup for S3

add the secret file
```yaml
Expand Down Expand Up @@ -110,6 +110,47 @@ kubectl apply -f config/samples/mysql_v1alpha1_cluster.yaml
```
could restore a cluster from the `backup_2021720827 ` copy in the S3 bucket.

if you want backup to NFS server or restore from NFS server, do it as follow:

## Quickstart for NFS backup

### Create NFS server
first create your PVC, such as "neosan1", fill it to `config/samples/nfs_rc.yaml `
```yaml
...
volumes:
- name: nfs-export-fast
persistentVolumeClaim:
claimName: neosan1
```
```shell
# create the nfs pod
kubectl apply -f config/samples/nfs_rc.yaml
# create the nfs service
kubectl apply -f config/samples/nfs_server.yaml
```
if create the nfs server successful, get the then:

## config `mysql_v1alpha1_backup.yaml ` and backup
Add field in `mysql_v1alpha1_backup.yaml ` as follow:
```yaml
BackupToNFS: "IP of NFS server"
```
use commadn as follow to backup
```shell
kubectl apply -f config/samples/mysql_v1alpha1_backup.yaml
```

## Restore cluster from exist NFS backup
first, configure the `mysql_v1alpha1_cluster.yaml`, uncomment the `restoreFromNFS` field:
```yaml
....
restoreFrom: "backup_202196152239"
restoreFromNFS : 10.96.253.82
```
`backup_202196152239` is the nfs server backup path, change it to yours.
the `10.96.253.82` is the NFS server ip, change it to yours.
use command as follow to create cluster from NFS server backup copy:

## build your own image
such as :
Expand Down
21 changes: 19 additions & 2 deletions mysqlcluster/container/init_sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ func (c *initSidecar) getEnvVars() []corev1.EnvVar {
Name: "RESTORE_FROM",
Value: c.Spec.RestoreFrom,
},

{
Name: "CLUSTER_NAME",
Value: c.Name,
},
getEnvVarFromSecret(sctName, "MYSQL_ROOT_PASSWORD", "root-password", false),
getEnvVarFromSecret(sctName, "MYSQL_DATABASE", "mysql-database", true),
getEnvVarFromSecret(sctName, "MYSQL_USER", "mysql-user", true),
Expand All @@ -124,7 +127,12 @@ func (c *initSidecar) getEnvVars() []corev1.EnvVar {
getEnvVarFromSecret(sctNamebackup, "S3_BUCKET", "s3-bucket", true),
)
}

if len(c.Spec.RestoreFromNFS) != 0 {
envs = append(envs, corev1.EnvVar{
Name: "RESTORE_FROM_NFS",
Value: c.Spec.RestoreFromNFS,
})
}
if c.Spec.MysqlOpts.InitTokuDB {
envs = append(envs, corev1.EnvVar{
Name: "INIT_TOKUDB",
Expand Down Expand Up @@ -194,6 +202,15 @@ func (c *initSidecar) getVolumeMounts() []corev1.VolumeMount {
)
}

if len(c.Spec.RestoreFromNFS) != 0 {
volumeMounts = append(volumeMounts,
corev1.VolumeMount{
Name: utils.XtrabackupPV,
MountPath: utils.XtrabckupLocal,
},
)
}

if c.Spec.Persistence.Enabled {
volumeMounts = append(volumeMounts,
corev1.VolumeMount{
Expand Down
Loading

0 comments on commit 8c61da3

Please sign in to comment.