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 13, 2021
1 parent 2d61f59 commit 6621a02
Show file tree
Hide file tree
Showing 25 changed files with 417 additions and 25 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"`

// Cluster represents the cluster name to backup
ClusterName string `json:"clustname"`
Expand Down
4 changes: 4 additions & 0 deletions api/v1alpha1/cluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ type ClusterSpec 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: Cluster 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 charts/mysql-operator/crds/mysql.radondb.com_clusters.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
13 changes: 12 additions & 1 deletion cluster/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,18 @@ func (c *Cluster) EnsureVolumes() []corev1.Volume {
},
},
)

// add the nfs volumn mount
if len(c.Spec.RestoreFromNFS) != 0 {
volumes = append(volumes, corev1.Volume{
Name: utils.XtrabackupPV,
VolumeSource: corev1.VolumeSource{
NFS: &corev1.NFSVolumeSource{
Server: c.Spec.RestoreFromNFS,
Path: "/",
},
},
})
}
return volumes
}

Expand Down
21 changes: 19 additions & 2 deletions cluster/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
8 changes: 6 additions & 2 deletions cluster/syncer/follower_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ func NewFollowerSVCSyncer(cli client.Client, c *cluster.Cluster) syncer.Interfac
service.Spec.Selector["role"] = "follower"
service.Spec.Selector["healthy"] = "yes"

if len(service.Spec.Ports) != 1 {
service.Spec.Ports = make([]corev1.ServicePort, 1)
if len(service.Spec.Ports) != 2 {
service.Spec.Ports = make([]corev1.ServicePort, 2)
}

service.Spec.Ports[0].Name = utils.MysqlPortName
service.Spec.Ports[0].Port = utils.MysqlPort
service.Spec.Ports[0].TargetPort = intstr.FromInt(utils.MysqlPort)
// xtrabackup
service.Spec.Ports[1].Name = utils.XBackupPortName
service.Spec.Ports[1].Port = utils.XBackupPort
service.Spec.Ports[1].TargetPort = intstr.FromInt(utils.XBackupPort)
return nil
})
}
9 changes: 7 additions & 2 deletions cluster/syncer/leader_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,18 @@ func NewLeaderSVCSyncer(cli client.Client, c *cluster.Cluster) syncer.Interface
service.Spec.Selector = c.GetSelectorLabels()
service.Spec.Selector["role"] = "leader"

if len(service.Spec.Ports) != 1 {
service.Spec.Ports = make([]corev1.ServicePort, 1)
if len(service.Spec.Ports) != 2 {
service.Spec.Ports = make([]corev1.ServicePort, 2)
}

service.Spec.Ports[0].Name = utils.MysqlPortName
service.Spec.Ports[0].Port = utils.MysqlPort
service.Spec.Ports[0].TargetPort = intstr.FromInt(utils.MysqlPort)

// xtrabackup
service.Spec.Ports[1].Name = utils.XBackupPortName
service.Spec.Ports[1].Port = utils.XBackupPort
service.Spec.Ports[1].TargetPort = intstr.FromInt(utils.XBackupPort)
return nil
})
}
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: Cluster 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_clusters.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
10 changes: 8 additions & 2 deletions config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ generatorOptions:
disableNameSuffixHash: true

configMapGenerator:
- name: manager-config
files:
- files:
- controller_manager_config.yaml
name: manager-config
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
images:
- name: controller
newName: acekingke/controller
newTag: "0.1"
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
3 changes: 3 additions & 0 deletions config/samples/mysql_v1alpha1_backup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ 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"

5 changes: 4 additions & 1 deletion config/samples/mysql_v1alpha1_cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ spec:
# if you want S3 backup or restore, please create backup_secret.yaml, uncomment below and fill secret name:
# backupSecretName:

# if you want create cluster from S3 , uncomment and fill the directory in S3 bucket below:
# if you want create cluster from S3 ,if you want create cluser from NFS
# uncomment and fill the directory in S3 bucket or NFS server diectory below:
# restoreFrom:

# Restore from NFS, uncomment below and set the ip of NFS server
# restoreFromNFS:
mysqlOpts:
rootPassword: "RadonDB@123"
rootHost: localhost
Expand Down
33 changes: 33 additions & 0 deletions config/samples/nfs_rc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

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
Loading

0 comments on commit 6621a02

Please sign in to comment.