Skip to content

Commit 5cd8861

Browse files
committed
*: add backup gtid and fix some bugs #698
1 parent a64d2af commit 5cd8861

File tree

11 files changed

+1814
-7
lines changed

11 files changed

+1814
-7
lines changed

api/v1alpha1/backup_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ type BackupStatus struct {
6464
BackupDate string `json:"backupDate,omitempty"`
6565
// Get the backup Type
6666
BackupType string `json:"backupType,omitempty"`
67+
// Get the Gtid
68+
Gtid string `json:"gtid,omitempty"`
6769
// Conditions represents the backup resource conditions list.
6870
Conditions []BackupCondition `json:"conditions,omitempty"`
6971
}

api/v1alpha1/mysqlcluster_types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,9 @@ type MysqlClusterStatus struct {
469469
ReadyNodes int `json:"readyNodes,omitempty"`
470470
// State
471471
State ClusterState `json:"state,omitempty"`
472+
// LastBackup
473+
LastBackup string `json:"lastbackup,omitempty"`
474+
LastBackupGtid string `json:"lastbackupGtid,omitempty"`
472475
// Conditions contains the list of the cluster conditions fulfilled.
473476
Conditions []ClusterCondition `json:"conditions,omitempty"`
474477
// Nodes contains the list of the node status fulfilled.

backup/cronbackup.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,22 @@ func (j *CronJob) scheduledBackupsRunningCount() int {
7575
backupsList := &apiv1alpha1.BackupList{}
7676
// select all backups with labels recurrent=true and and not completed of the cluster
7777
selector := j.backupSelector()
78-
client.MatchingFields{"status.completed": "false"}.ApplyToList(selector)
78+
// Because k8s do not support fieldSelector with custom resources
79+
// https://github.com/kubernetes/kubernetes/issues/51046
80+
// So this cannot use fields selector.
81+
// client.MatchingFields{"status.completed": "false"}.ApplyToList(selector)
7982

80-
if err := j.Client.List(context.TODO(), backupsList, selector); err != nil {
83+
if err := j.Client.List(context.TODO(), backupsList); err != nil {
8184
log.Error(err, "failed getting backups", "selector", selector)
8285
return 0
8386
}
84-
85-
return len(backupsList.Items)
87+
var rest []apiv1alpha1.Backup
88+
for _, b := range backupsList.Items {
89+
if !b.Status.Completed {
90+
rest = append(rest, b)
91+
}
92+
}
93+
return len(rest)
8694
}
8795

8896
func (j *CronJob) backupSelector() *client.ListOptions {
@@ -151,10 +159,12 @@ func (j *CronJob) createBackup() (*apiv1alpha1.Backup, error) {
151159
//RemoteDeletePolicy: j.BackupRemoteDeletePolicy,
152160
HostName: fmt.Sprintf("%s-mysql-0", j.ClusterName),
153161
},
162+
Status: apiv1alpha1.BackupStatus{Completed: false},
154163
}
155164
if len(j.NFSServerAddress) > 0 {
156165
backup.Spec.NFSServerAddress = j.NFSServerAddress
157166
}
167+
158168
return backup, j.Client.Create(context.TODO(), backup)
159169
}
160170

backup/syncer/job.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626
"k8s.io/apimachinery/pkg/runtime"
2727
"sigs.k8s.io/controller-runtime/pkg/client"
28+
"sigs.k8s.io/controller-runtime/pkg/log"
2829

2930
v1alpha1 "github.com/radondb/radondb-mysql-kubernetes/api/v1alpha1"
3031
"github.com/radondb/radondb-mysql-kubernetes/backup"
@@ -101,6 +102,9 @@ func (s *jobSyncer) updateStatus(job *batchv1.Job) {
101102
if backType := s.job.Annotations[utils.JobAnonationType]; backType != "" {
102103
s.backup.Status.BackupType = backType
103104
}
105+
if gtid := s.job.Annotations[utils.JobAnonationGtid]; gtid != "" {
106+
s.backup.Status.Gtid = gtid
107+
}
104108
}
105109

106110
// check for failed condition
@@ -154,10 +158,12 @@ func (s *jobSyncer) ensurePodSpec(in corev1.PodSpec) corev1.PodSpec {
154158
"/bin/bash", "-c", "--",
155159
}
156160
backupToDir, DateTime := utils.BuildBackupName(s.backup.Spec.ClusterName)
161+
// add the gtid script
157162
strAnnonations := fmt.Sprintf(`curl -X PATCH -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" -H "Content-Type: application/json-patch+json" \
158163
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_PORT_443_TCP_PORT/apis/batch/v1/namespaces/%s/jobs/%s \
159-
-d '[{"op": "add", "path": "/metadata/annotations/backupName", "value": "%s"}, {"op": "add", "path": "/metadata/annotations/backupDate", "value": "%s"}, {"op": "add", "path": "/metadata/annotations/backupType", "value": "NFS"}]';`,
160-
s.backup.Namespace, s.backup.GetNameForJob(), backupToDir, DateTime)
164+
-d "[{\"op\": \"add\", \"path\": \"/metadata/annotations/backupName\", \"value\": \"%s\"}, {\"op\": \"add\", \"path\": \"/metadata/annotations/backupDate\", \"value\": \"%s\"},{\"op\": \"add\", \"path\": \"/metadata/annotations/gtid\", \"value\": \"$( cat /backup/%s/xtrabackup_binlog_info|awk '{print $3}')\"}, {\"op\": \"add\", \"path\": \"/metadata/annotations/backupType\", \"value\": \"NFS\"}]";`,
165+
s.backup.Namespace, s.backup.GetNameForJob(), backupToDir, DateTime, backupToDir)
166+
log.Log.Info(strAnnonations)
161167
// Add the check DiskUsage
162168
// use expr because shell cannot compare float number
163169
checkUsage := `[ $(echo "$(df /backup|awk 'NR>1 {print $4}') > $(du /backup |awk 'END {if (NR > 1) {print $1 /(NR-1)} else print 0}')"|bc) -eq '1' ] || { echo disk available may be too small; exit 1;};`
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
2+
---
3+
apiVersion: apiextensions.k8s.io/v1
4+
kind: CustomResourceDefinition
5+
metadata:
6+
annotations:
7+
controller-gen.kubebuilder.io/version: v0.4.1
8+
creationTimestamp: null
9+
name: backups.mysql.radondb.com
10+
spec:
11+
group: mysql.radondb.com
12+
names:
13+
kind: Backup
14+
listKind: BackupList
15+
plural: backups
16+
singular: backup
17+
scope: Namespaced
18+
versions:
19+
- additionalPrinterColumns:
20+
- description: The Backup name
21+
jsonPath: .status.backupName
22+
name: BackupName
23+
type: string
24+
- description: The Backup Date time
25+
jsonPath: .status.backupDate
26+
name: BackupDate
27+
type: string
28+
- description: The Backup Type
29+
jsonPath: .status.backupType
30+
name: Type
31+
type: string
32+
- description: Whether the backup Success?
33+
jsonPath: .status.conditions[?(@.type=="Complete")].status
34+
name: Success
35+
type: string
36+
name: v1alpha1
37+
schema:
38+
openAPIV3Schema:
39+
description: Backup is the Schema for the backups API
40+
properties:
41+
apiVersion:
42+
description: 'APIVersion defines the versioned schema of this representation
43+
of an object. Servers should convert recognized schemas to the latest
44+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
45+
type: string
46+
kind:
47+
description: 'Kind is a string value representing the REST resource this
48+
object represents. Servers may infer this from the endpoint the client
49+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
50+
type: string
51+
metadata:
52+
type: object
53+
spec:
54+
description: This is the backup Job CRD. BackupSpec defines the desired
55+
state of Backup
56+
properties:
57+
clusterName:
58+
description: ClusterName represents the cluster name to backup
59+
type: string
60+
historyLimit:
61+
default: 3
62+
description: History Limit of job
63+
format: int32
64+
type: integer
65+
hostName:
66+
description: HostName represents the host for which to take backup
67+
If is empty, is use leader HostName
68+
type: string
69+
image:
70+
default: radondb/mysql57-sidecar:v2.3.0
71+
description: To specify the image that will be used for sidecar container.
72+
type: string
73+
nfsServerAddress:
74+
description: Represents the ip address of the nfs server.
75+
type: string
76+
required:
77+
- clusterName
78+
type: object
79+
status:
80+
description: BackupStatus defines the observed state of Backup
81+
properties:
82+
backupDate:
83+
description: Get the backup Date
84+
type: string
85+
backupName:
86+
description: Get the backup path.
87+
type: string
88+
backupType:
89+
description: Get the backup Type
90+
type: string
91+
completed:
92+
default: false
93+
description: Completed indicates whether the backup is in a final
94+
state, no matter whether its' corresponding job failed or succeeded
95+
type: boolean
96+
conditions:
97+
description: Conditions represents the backup resource conditions
98+
list.
99+
items:
100+
description: BackupCondition defines condition struct for backup
101+
resource
102+
properties:
103+
lastTransitionTime:
104+
description: LastTransitionTime
105+
format: date-time
106+
type: string
107+
message:
108+
description: Message
109+
type: string
110+
reason:
111+
description: Reason
112+
type: string
113+
status:
114+
description: Status of the condition, one of (\"True\", \"False\",
115+
\"Unknown\")
116+
type: string
117+
type:
118+
description: type of cluster condition, values in (\"Ready\")
119+
type: string
120+
required:
121+
- lastTransitionTime
122+
- message
123+
- reason
124+
- status
125+
- type
126+
type: object
127+
type: array
128+
gtid:
129+
description: Get the Gtid
130+
type: string
131+
required:
132+
- completed
133+
type: object
134+
type: object
135+
served: true
136+
storage: true
137+
subresources:
138+
status: {}
139+
status:
140+
acceptedNames:
141+
kind: ""
142+
plural: ""
143+
conditions: []
144+
storedVersions: []

0 commit comments

Comments
 (0)