Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 NFS ip address where cluster restore from.
// +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)
}
}
40 changes: 37 additions & 3 deletions backup/syncer/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,43 @@ 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 = fmt.Sprintf("%s%s", mysqlcluster.GetPrefixFromEnv(), 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(s.backup.Spec.ClusterName)
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/mysql57-sidecar:v2.2.0
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 @@ -1245,6 +1245,9 @@ spec:
description: Represents the name of the cluster restore from backup
path
type: string
restoreFromNFS:
description: Represents NFS ip address where cluster restore from.
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/mysql57-sidecar:v2.2.0
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 @@ -1245,6 +1245,9 @@ spec:
description: Represents the name of the cluster restore from backup
path
type: string
restoreFromNFS:
description: Represents NFS ip address where cluster restore from.
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mysql57-sidecar:v2.2.0

# hostname if empty, use the leader as hostname
hostname: sample-mysql-0
clustname: sample
# BackupToNFS: "IP of NFS server"
4 changes: 4 additions & 0 deletions config/samples/mysql_v1alpha1_mysqlcluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ spec:
# backupSecretName:

# if you want create mysqlcluster from S3, uncomment and fill the directory in S3 bucket below:
# such as restoreFrom: "backup_202241423817"
# restoreFrom:

# Restore from NFS, uncomment below and set the ip of NFS server
# such as restoreFromNFS: "10.233.55.172"
# 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: backup-pv-claim
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
11 changes: 11 additions & 0 deletions config/samples/pv-claim.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: backup-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Gi
33 changes: 33 additions & 0 deletions config/samples/pv-volume.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
name: manual
provisioner: kubernetes.io/no-provisioner
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
---

apiVersion: v1
kind: PersistentVolume
metadata:
name: backup-pv-volume
labels:
type: local
spec:
storageClassName: manual
# you can set affinity ,for example:
# nodeAffinity:
# required:
# nodeSelectorTerms:
# - matchExpressions:
# - key: kubernetes.io/hostname
# operator: In
# values:
# - node2
capacity:
storage: 40Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/backup"
64 changes: 64 additions & 0 deletions docs/deploy_backup_restore_nfs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# mysql-operator

## Quickstart for NFS backup
### Create NFS server
First create your PVC, such as "neosan1",
Or use local storage pvc, see `config/sample/pv-claim.yaml`
and `pv-volume.yaml` for more details.
Then create NFS server, such as "nfs-server",
```yaml
fill it to `config/samples/nfs_rc.yaml `
```yaml
...
volumes:
- name: nfs-export-fast
persistentVolumeClaim:
claimName: neosan1 // or backup-pv-claim
```
```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 command as follow to backup
```shell
kubectl apply -f config/samples/mysql_v1alpha1_backup.yaml
```
> Notice: backup cr and mysqlcluster cr must be in the same namespace.
## Restore cluster from exist NFS backup
first, configure the `mysql_v1alpha1_cluster.yaml`, uncomment the `restoreFromNFS` field:
```yaml
....
restoreFrom: "sample_202196152239"
restoreFromNFS : 10.96.253.82
```
`sample_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.

> Notice: you can find the `sample_202196152239` in the nfs_server pod, at `/exports` path
or find it in node `/mnt/backup` path if you use the local pesistent volume with `sample/pv-volume.yaml`.

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
```
Loading