Skip to content

Commit 65ecfc5

Browse files
committed
New GaleraBackup CR to orchestrate backup of a running cluster
This CR sets up a cronjob whose purpose is to capture a consistent snapshot of a running Galera node (via garbd) and to convert the data internally into a regular SQL backup made with mysqldump. The restore part is out of scope of this CR and will be addressed in subsequent commits. Jira: OSPRH-10503
1 parent 65de595 commit 65ecfc5

34 files changed

+2016
-2
lines changed

PROJECT

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,13 @@ resources:
4242
kind: MariaDBAccount
4343
path: github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1
4444
version: v1beta1
45+
- api:
46+
crdVersion: v1
47+
namespaced: true
48+
controller: true
49+
domain: openstack.org
50+
group: mariadb
51+
kind: GaleraBackup
52+
path: github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1
53+
version: v1beta1
4554
version: "3"
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.14.0
7+
name: galerabackups.mariadb.openstack.org
8+
spec:
9+
group: mariadb.openstack.org
10+
names:
11+
kind: GaleraBackup
12+
listKind: GaleraBackupList
13+
plural: galerabackups
14+
singular: galerabackup
15+
scope: Namespaced
16+
versions:
17+
- additionalPrinterColumns:
18+
- description: Ready
19+
jsonPath: .status.conditions[0].status
20+
name: Ready
21+
type: string
22+
- description: Message
23+
jsonPath: .status.conditions[0].message
24+
name: Message
25+
type: string
26+
name: v1beta1
27+
schema:
28+
openAPIV3Schema:
29+
description: GaleraBackup is the Schema for the galerabackups API
30+
properties:
31+
apiVersion:
32+
description: |-
33+
APIVersion defines the versioned schema of this representation of an object.
34+
Servers should convert recognized schemas to the latest internal value, and
35+
may reject unrecognized values.
36+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
37+
type: string
38+
kind:
39+
description: |-
40+
Kind is a string value representing the REST resource this object represents.
41+
Servers may infer this from the endpoint the client submits requests to.
42+
Cannot be updated.
43+
In CamelCase.
44+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
45+
type: string
46+
metadata:
47+
type: object
48+
spec:
49+
description: GaleraBackupSpec defines the desired state of GaleraBackup
50+
properties:
51+
databaseInstance:
52+
description: Galera cluster to backup
53+
type: string
54+
retention:
55+
description: Time duration after which old backups must be reclaimed
56+
on disk
57+
type: string
58+
schedule:
59+
default: '@hourly'
60+
description: The schedule in Cron format
61+
type: string
62+
storageClass:
63+
description: Storage volume for backup data
64+
type: string
65+
storageRequest:
66+
description: Storage Request for backup data
67+
type: string
68+
transferStorage:
69+
description: Configuration of storage used for intermediate data transfer
70+
properties:
71+
storageClass:
72+
description: Storage volume for backup data
73+
type: string
74+
storageRequest:
75+
description: Storage Request for backup data
76+
type: string
77+
required:
78+
- storageRequest
79+
type: object
80+
required:
81+
- schedule
82+
type: object
83+
status:
84+
description: GaleraBackupStatus defines the observed state of GaleraBackup
85+
properties:
86+
conditions:
87+
description: Deployment Conditions
88+
items:
89+
description: Condition defines an observation of a API resource
90+
operational state.
91+
properties:
92+
lastTransitionTime:
93+
description: |-
94+
Last time the condition transitioned from one status to another.
95+
This should be when the underlying condition changed. If that is not known, then using the time when
96+
the API field changed is acceptable.
97+
format: date-time
98+
type: string
99+
message:
100+
description: A human readable message indicating details about
101+
the transition.
102+
type: string
103+
reason:
104+
description: The reason for the condition's last transition
105+
in CamelCase.
106+
type: string
107+
severity:
108+
description: |-
109+
Severity provides a classification of Reason code, so the current situation is immediately
110+
understandable and could act accordingly.
111+
It is meant for situations where Status=False and it should be indicated if it is just
112+
informational, warning (next reconciliation might fix it) or an error (e.g. DB create issue
113+
and no actions to automatically resolve the issue can/should be done).
114+
For conditions where Status=Unknown or Status=True the Severity should be SeverityNone.
115+
type: string
116+
status:
117+
description: Status of the condition, one of True, False, Unknown.
118+
type: string
119+
type:
120+
description: Type of condition in CamelCase.
121+
type: string
122+
required:
123+
- lastTransitionTime
124+
- status
125+
- type
126+
type: object
127+
type: array
128+
hash:
129+
additionalProperties:
130+
type: string
131+
description: Map of hashes to track input changes
132+
type: object
133+
observedGeneration:
134+
description: |-
135+
ObservedGeneration - the most recent generation observed for this
136+
service. If the observed generation is less than the spec generation,
137+
then the controller has not processed the latest changes injected by
138+
the opentack-operator in the top-level CR (e.g. the ContainerImage)
139+
format: int64
140+
type: integer
141+
type: object
142+
type: object
143+
served: true
144+
storage: true
145+
subresources:
146+
status: {}

api/v1beta1/conditions.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import (
2121

2222
// MariaDB Condition Types used by API objects.
2323
const (
24+
// MariaDBCreatedCondition Status=True indicates if there a Galera CR already exists
25+
MariaDBResourceExistsCondition condition.Type = "MariaDBResourceExists"
26+
2427
// MariaDBInitializedCondition Status=True condition which indicates if the MariaDB dbinit has completed
2528
MariaDBInitializedCondition condition.Type = "MariaDBInitialized"
2629

@@ -35,6 +38,9 @@ const (
3538

3639
// MariaDB Reasons used by API objects.
3740
const (
41+
// ReasonResourceNotFound - Galera CR not found
42+
ReasonResourceNotFound condition.Reason = "Galera CR not found"
43+
3844
// ReasonDBError - DB error
3945
ReasonDBError condition.Reason = "DatabaseError"
4046
// ReasonDBPatchError - new resource set to reason Init
@@ -57,6 +63,10 @@ const (
5763
//
5864
// MariaDBReady condition messages
5965
//
66+
MariaDBResourceInitMessage = "MariaDB / Galera resource not yet available"
67+
68+
MariaDBResourceExistsMessage = "MariaDB / Galera resource exists"
69+
6070
// MariaDBInitializedInitMessage
6171
MariaDBInitializedInitMessage = "MariaDB dbinit not started"
6272

@@ -98,3 +108,30 @@ const (
98108

99109
MariaDBAccountReadyForDeleteMessage = "MariaDBAccount ready for delete"
100110
)
111+
112+
// GaleraBackup Condition Types used by API objects.
113+
const (
114+
PersistentVolumeClaimReadyCondition condition.Type = "PersistentVolumeClaimReady"
115+
116+
CronjobReadyCondition condition.Type = "CronjobReady"
117+
)
118+
119+
const (
120+
// PersistentVolumeClaimReadyErrorMessage
121+
PersistentVolumeClaimReadyErrorMessage = "PersistentVolumeClaim error occurred %s"
122+
123+
// PersistentVolumeClaimReadyInitMessage
124+
PersistentVolumeClaimReadyInitMessage = "PersistentVolumeClaim not created"
125+
126+
// PersistentVolumeClaimReadyMessage
127+
PersistentVolumeClaimReadyMessage = "PersistentVolumeClaim created"
128+
129+
// CronjobReadyErrorMessage
130+
CronjobReadyErrorMessage = "Cronjob error occurred %s"
131+
132+
// CronjobReadyInitMessage
133+
CronjobReadyInitMessage = "Cronjob not created"
134+
135+
// CronjobReadyMessage
136+
CronjobReadyMessage = "Cronjob created"
137+
)

api/v1beta1/galerabackup_types.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
Copyright 2022.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
)
23+
24+
// GaleraBackupSpec defines the desired state of GaleraBackup
25+
type GaleraBackupSpec struct {
26+
// Galera cluster to backup
27+
DatabaseInstance string `json:"databaseInstance,omitempty"`
28+
// Storage volume for backup data
29+
StorageClass string `json:"storageClass,omitempty"`
30+
// Storage Request for backup data
31+
StorageRequest string `json:"storageRequest,omitempty"`
32+
// Configuration of storage used for intermediate data transfer
33+
TransferStorage *GaleraBackupTransferStorageSpec `json:"transferStorage,omitempty"`
34+
// The schedule in Cron format
35+
// +kubebuilder:default="@hourly"
36+
Schedule string `json:"schedule"`
37+
// Time duration after which old backups must be reclaimed on disk
38+
// +optional
39+
Retention *metav1.Duration `json:"retention,omitempty"`
40+
}
41+
42+
type GaleraBackupTransferStorageSpec struct {
43+
// Storage volume for backup data
44+
StorageClass string `json:"storageClass,omitempty"`
45+
// Storage Request for backup data
46+
StorageRequest string `json:"storageRequest"`
47+
}
48+
49+
// GaleraBackupStatus defines the observed state of GaleraBackup
50+
type GaleraBackupStatus struct {
51+
// Map of hashes to track input changes
52+
Hash map[string]string `json:"hash,omitempty"`
53+
// Deployment Conditions
54+
Conditions condition.Conditions `json:"conditions,omitempty" optional:"true"`
55+
// ObservedGeneration - the most recent generation observed for this
56+
// service. If the observed generation is less than the spec generation,
57+
// then the controller has not processed the latest changes injected by
58+
// the opentack-operator in the top-level CR (e.g. the ContainerImage)
59+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
60+
}
61+
62+
//+kubebuilder:object:root=true
63+
//+kubebuilder:subresource:status
64+
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[0].status",description="Ready"
65+
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[0].message",description="Message"
66+
67+
// GaleraBackup is the Schema for the galerabackups API
68+
type GaleraBackup struct {
69+
metav1.TypeMeta `json:",inline"`
70+
metav1.ObjectMeta `json:"metadata,omitempty"`
71+
72+
Spec GaleraBackupSpec `json:"spec,omitempty"`
73+
Status GaleraBackupStatus `json:"status,omitempty"`
74+
}
75+
76+
//+kubebuilder:object:root=true
77+
78+
// GaleraBackupList contains a list of GaleraBackup
79+
type GaleraBackupList struct {
80+
metav1.TypeMeta `json:",inline"`
81+
metav1.ListMeta `json:"metadata,omitempty"`
82+
Items []GaleraBackup `json:"items"`
83+
}
84+
85+
func init() {
86+
SchemeBuilder.Register(&GaleraBackup{}, &GaleraBackupList{})
87+
}
88+
89+
// // IsReady - returns true if service is ready to serve requests
90+
// func (instance Galera) IsReady() bool {
91+
// return instance.Status.Conditions.IsTrue(condition.DeploymentReadyCondition)
92+
// }
93+
94+
// RbacConditionsSet - sets the conditions for the rbac object
95+
func (instance GaleraBackup) RbacConditionsSet(c *condition.Condition) {
96+
instance.Status.Conditions.Set(c)
97+
}
98+
99+
// RbacNamespace - returns the namespace name
100+
func (instance GaleraBackup) RbacNamespace() string {
101+
return instance.Namespace
102+
}
103+
104+
// RbacResourceName - return the name to be used for rbac objects (serviceaccount, role, rolebinding)
105+
func (instance GaleraBackup) RbacResourceName() string {
106+
return "galerabackup-" + instance.Name
107+
}

0 commit comments

Comments
 (0)