diff --git a/api/bases/mariadb.openstack.org_galeras.yaml b/api/bases/mariadb.openstack.org_galeras.yaml index d745246f..2819ce91 100644 --- a/api/bases/mariadb.openstack.org_galeras.yaml +++ b/api/bases/mariadb.openstack.org_galeras.yaml @@ -78,6 +78,13 @@ spec: secret: description: Name of the secret to look for password keys type: string + sst: + default: rsync + description: Snapshot State Transfer method to use for full node synchronization + enum: + - rsync + - mariabackup + type: string storageClass: description: Storage class to host the mariadb databases type: string diff --git a/api/v1beta1/galera_types.go b/api/v1beta1/galera_types.go index c9becfc4..6c44530c 100644 --- a/api/v1beta1/galera_types.go +++ b/api/v1beta1/galera_types.go @@ -80,8 +80,21 @@ type GaleraSpecCore struct { // +kubebuilder:validation:Optional // Log Galera pod's output to disk LogToDisk bool `json:"logToDisk"` + // +kubebuilder:validation:Optional + // +kubebuilder:default=rsync + // +kubebuilder:validation:Enum=rsync;mariabackup + // Snapshot State Transfer method to use for full node synchronization + SST GaleraSST `json:"sst"` } +// Supported SST type +type GaleraSST string + +const ( + RSync GaleraSST = "rsync" + MariaBackup GaleraSST = "mariabackup" +) + // GaleraAttributes holds startup information for a Galera host type GaleraAttributes struct { // Last recorded replication sequence number in the DB diff --git a/config/crd/bases/mariadb.openstack.org_galeras.yaml b/config/crd/bases/mariadb.openstack.org_galeras.yaml index d745246f..2819ce91 100644 --- a/config/crd/bases/mariadb.openstack.org_galeras.yaml +++ b/config/crd/bases/mariadb.openstack.org_galeras.yaml @@ -78,6 +78,13 @@ spec: secret: description: Name of the secret to look for password keys type: string + sst: + default: rsync + description: Snapshot State Transfer method to use for full node synchronization + enum: + - rsync + - mariabackup + type: string storageClass: description: Storage class to host the mariadb databases type: string diff --git a/config/samples/mariadb_v1beta1_galera_sst.yaml b/config/samples/mariadb_v1beta1_galera_sst.yaml new file mode 100644 index 00000000..8b0d5c2d --- /dev/null +++ b/config/samples/mariadb_v1beta1_galera_sst.yaml @@ -0,0 +1,10 @@ +apiVersion: mariadb.openstack.org/v1beta1 +kind: Galera +metadata: + name: openstack +spec: + secret: osp-secret + storageClass: local-storage + storageRequest: 500M + replicas: 3 + sst: mariabackup diff --git a/pkg/mariadb/volumes.go b/pkg/mariadb/volumes.go index 67593d08..94be2a6d 100644 --- a/pkg/mariadb/volumes.go +++ b/pkg/mariadb/volumes.go @@ -37,6 +37,13 @@ func getGaleraVolumes(g *mariadbv1.Galera) []corev1.Volume { } } + if g.Spec.SST == mariadbv1.MariaBackup { + configTemplates = append(configTemplates, corev1.KeyToPath{ + Key: "galera_sst_mariabackup.cnf.in", + Path: "galera_sst_mariabackup.cnf.in", + }) + } + volumes := []corev1.Volume{ { Name: "secrets", diff --git a/templates/galera/bin/mysql_bootstrap.sh b/templates/galera/bin/mysql_bootstrap.sh index fbbff7e8..2664a4d1 100755 --- a/templates/galera/bin/mysql_bootstrap.sh +++ b/templates/galera/bin/mysql_bootstrap.sh @@ -1,5 +1,10 @@ #!/bin/bash -set +eux +set +eu + +init_error() { + echo "Container initialization failed at $(caller)." >&2 +} +trap init_error ERR if [ -e /var/lib/mysql/mysql ]; then echo -e "Database already exists. Reuse it." @@ -27,24 +32,34 @@ if [ "$(sysctl -n crypto.fips_enabled)" == "1" ]; then else SSL_CIPHER='AES128-SHA256' fi +export SSL_CIPHER PODNAME=$(hostname -f | cut -d. -f1,2) PODIPV4=$(grep "${PODNAME}" /etc/hosts | grep -v ':' | cut -d$'\t' -f1) PODIPV6=$(grep "${PODNAME}" /etc/hosts | grep ':' | cut -d$'\t' -f1) +if [[ "" = "${PODIPV6}" ]]; then + PODIP="${PODIPV4}" + IPSTACK="IPV4" +else + PODIP="[::]" + IPSTACK="IPV6" +fi +export PODNAME PODIP + +# mariabackup: default credentials if no configuration was provided +: ${MARIABACKUP_USER=root} +: ${MARIABACKUP_PASSWORD=$DB_ROOT_PASSWORD} +export MARIABACKUP_USER MARIABACKUP_PASSWORD cd /var/lib/config-data/default for cfg in *.cnf.in; do if [ -s "${cfg}" ]; then - - if [[ "" = "${PODIPV6}" ]]; then - PODIP="${PODIPV4}" - IPSTACK="IPV4" - else - PODIP="[::]" - IPSTACK="IPV6" - fi - echo "Generating config file from template ${cfg}, will use ${IPSTACK} listen address of ${PODIP}" - sed -e "s/{ PODNAME }/${PODNAME}/" -e "s/{ PODIP }/${PODIP}/" -e "s/{ SSL_CIPHER }/${SSL_CIPHER}/" "/var/lib/config-data/default/${cfg}" > "/var/lib/config-data/generated/${cfg%.in}" + # replace all occurrences of "{ xxx }" with their value from environment + awk '{ +patsplit($0,markers,/{ (PODNAME|PODIP|SSL_CIPHER|MARIABACKUP_USER|MARIABACKUP_PASSWORD) }/); +for(i in markers){ m=markers[i]; gsub(/\W/,"",m); gsub(markers[i], ENVIRON[m])}; +print $0 +}' "/var/lib/config-data/default/${cfg}" > "/var/lib/config-data/generated/${cfg%.in}" fi done diff --git a/templates/galera/bin/mysql_probe.sh b/templates/galera/bin/mysql_probe.sh index a1b262f3..20360867 100755 --- a/templates/galera/bin/mysql_probe.sh +++ b/templates/galera/bin/mysql_probe.sh @@ -2,7 +2,7 @@ set -u # This secret is mounted by k8s and always up to date -read -s -u 3 3< /var/lib/secrets/dbpassword MYSQL_PWD || true +read -s -u 3 3< <(cat /var/lib/secrets/dbpassword; echo) MYSQL_PWD export MYSQL_PWD PROBE_USER=root diff --git a/templates/galera/config/config.json b/templates/galera/config/config.json index f0ea0cb9..65370907 100644 --- a/templates/galera/config/config.json +++ b/templates/galera/config/config.json @@ -28,6 +28,13 @@ "perm": "0644", "optional": true }, + { + "source": "/var/lib/config-data/generated/galera_sst_mariabackup.cnf", + "dest": "/etc/my.cnf.d/galera_mariabackup.cnf", + "owner": "root", + "perm": "0644", + "optional": true + }, { "source": "/var/lib/operator-scripts", "dest": "/usr/local/bin", diff --git a/templates/galera/config/galera_sst_mariabackup.cnf.in b/templates/galera/config/galera_sst_mariabackup.cnf.in new file mode 100644 index 00000000..8420e61a --- /dev/null +++ b/templates/galera/config/galera_sst_mariabackup.cnf.in @@ -0,0 +1,3 @@ +[mysqld] +wsrep_sst_method = mariabackup +wsrep_sst_auth = root:{ MARIABACKUP_PASSWORD } diff --git a/templates/galera/config/init_config.json b/templates/galera/config/init_config.json new file mode 100644 index 00000000..7984f1fe --- /dev/null +++ b/templates/galera/config/init_config.json @@ -0,0 +1,10 @@ +{ + "command": "/usr/bin/true", + "permissions": [ + { + "path": "/var/lib/mysql", + "owner": "mysql:mysql", + "recurse": "true" + } + ] +} diff --git a/templates/galera/config/my.cnf.in b/templates/galera/config/my.cnf.in new file mode 100644 index 00000000..065d0f59 --- /dev/null +++ b/templates/galera/config/my.cnf.in @@ -0,0 +1,4 @@ +[client] +user=root +host=localhost +password={ DB_ROOT_PASSWORD }