Configuring the MySQL-slave

To install a MySQL slave database with the gerrit-slave chart, set database.provider to mysql and mysql.enabledto true in the values.yaml. This will then install the mysql chart onto the Kubernetes cluster as a dependency of the gerrit-slave chart.

Configuring the master DB instance

For the replication to work, the MySQL database master has to be configured accordingly and some data about the database state has to be collected. The necessary steps are detailed in this section. If it is not planned to replicate the master database, skip this section.

Create technical user

Connect to the MySQL database master and create a technical user to handle the replication:

CREATE USER 'repl' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'
  IDENTIFIED BY 'password'
  REQUIRE SUBJECT '/C=DE/O=Gerrit/CN=gerrit-db-slave';
FLUSH PRIVILEGES;

The username, password and certificate subject can be chosen as needed, but should be written down, since they are needed in coming steps.

Create certificates for SSL-encrypted communication

For SSL-encrypted communication, a set of certificates is needed. If the master does not yet possess a CA, private- and public key, use the following commands to create them after adjusting the subject strings:

openssl genrsa -out ./ca.key.pem 4096

openssl req \
    -key ./ca.key.pem \
    -new \
    -x509 \
    -days 7300 \
    -sha256 \
    -out ./ca.cert.pem \
    -subj "/C=DE/O=Gerrit/CN=gerrit-db-master" \
    -nodes

openssl genrsa -out ./master.key.pem 4096

openssl req \
    -key ./master.key.pem \
    -new \
    -sha256 \
    -out ./master.csr.pem \
    -subj "/C=DE/O=Gerrit/CN=gerrit-db-master" \
    -nodes

openssl x509 \
    -req \
    -CA ./ca.cert.pem \
    -CAkey ./ca.key.pem \
    -CAcreateserial \
    -in ./master.csr.pem \
    -out ./master.cert.pem

Then a private and a public key for the slave has to be created. If the master did already possess a CA, change the corresponding paths in the commands below. The subject string has to be the same as the one used, when creating the MySQL user for replication. The content of the CA-certificate and the slave's private and public key (here: slave.key.pem and slave.cert.pem) have to be noted for later use.

openssl genrsa -out ./slave.key.pem 4096

openssl req \
    -key ./slave.key.pem \
    -new -sha256 \
    -out ./slave.csr.pem \
    -subj "/C=DE/O=Gerrit/CN=gerrit-db-slave" \
    -nodes

openssl x509 \
    -req \
    -CA ./ca.cert.pem \
    -CAkey ./ca.key.pem \
    -CAcreateserial \
    -in ./slave.csr.pem \
    -out ./slave.cert.pem

Configure the master database

The master DB has to be configured for replication by adding the following entries to the configuration-file of the MySQL instance:

[mysqld]
server-id=1                     # Has to be unique under all masters/slaves.
log_bin=mysql-bin               # Name of the logs used for replication

ssl-ca=/ssl/ca.pem              # Location of the CA-certificate
ssl-cert=/ssl/server-cert.pem   # Location of the public key
ssl-key=/ssl/server-key.pem     # Location of the private key

Create database dump and note database state

In the next steps the content of the database has to be retrieved and the corresponding status of the transaction logs has to be retrieved. Depending on the traffic the database receives, the master DB should be stopped for these steps, since the information could get out off sync, if the data is changed inbetween the steps:

STOP MASTER;

Retrieve the status of the master:

SHOW MASTER STATUS;

  +------------------+----------+--------------+------------------+-------------------+
  | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
  +------------------+----------+--------------+------------------+-------------------+
  | mysql-bin.000004 | 69444891 |              |                  |                   |
  +------------------+----------+--------------+------------------+-------------------+

The filename and position should be written down, since they will be needed for the configuration of the slave.

Dump the content of the database:

mysqldump --user=root -p --all-databases > ./master_dump.sql

Afterwards, the master can be started again:

START MASTER;

Configuration

mysql-chart

The configuration of the database is done in the values.yamlof the gerrit-slave chart under the mysql-key. The complete list of options for the mysql-chart can be viewed in the chart‘s documentation. The options referenced in the gerrit-slave chart’s values.yaml are listed here:

ParameterDescriptionDefault
mysql.enabledWhether to install the MySQL databasetrue
mysql.imageWhich container image containing MySQL to usemysql
mysql.imageTagTag of container image (usually the database version)5.5.61
mysql.mysqlRootPasswordPassword of the database root userbig_secret
mysql.mysqlUserDatabase user (The technical user used by the Gerrit slave)gerrit
mysql.mysqlPasswordPassword of the database usersecret
mysql.livenessProbe.initialDelaySecondsDelay before liveness probe is initiated30
mysql.livenessProbe.periodSecondsHow often to perform the probe10
mysql.livenessProbe.timeoutSecondsWhen the probe times out5
mysql.livenessProbe.successThresholdMinimum consecutive successes for the probe to be considered successful after having failed.1
mysql.livenessProbe.failureThresholdMinimum consecutive failures for the probe to be considered failed after having succeeded.3
mysql.readinessProbe.initialDelaySecondsDelay before readiness probe is initiated5
mysql.readinessProbe.periodSecondsHow often to perform the probe10
mysql.readinessProbe.timeoutSecondsWhen the probe times out1
mysql.readinessProbe.successThresholdMinimum consecutive successes for the probe to be considered successful after having failed.1
mysql.readinessProbe.failureThresholdMinimum consecutive failures for the probe to be considered failed after having succeeded.3
mysql.persistence.enabledCreate a volume to store datatrue
mysql.persistence.sizeSize of persistent volume claim8Gi
mysql.persistence.storageClassType of persistent volume claimdefault
mysql.persistence.accessModeReadWriteOnce or ReadOnlyReadWriteOnce
mysql.resourcesConfigure the amount of resources the pod requests/is allowedrequests.cpu: 250m
requests.memory: 1Gi
limits.cpu: 250m
limits.memory: 1Gi
mysql.configurationFilesAdd configuration files for MySQLmysql.cnf (check the mysql.cnf-section for configuration options)
mysql.initializationFilesAdd scripts that are executed, when the database is started the first timeinitialize_reviewdb.sql (Should not be changed)
mysql.service.typeType of the Service used to expose the databaseNodePort
mysql.service.portThe port used to expose the database3306
ssl.enabledSetup and use SSL for MySQL connectionsfalse
ssl.secretName of the secret containing the SSL certificatesslave-ssl-certs
ssl.certificates[0].nameName of the secret containing the SSL certificatesslave-ssl-certs
ssl.certificates[0].caCA certificate (if using replication use the CA created peviously)-----BEGIN CERTIFICATE-----
ssl.certificates[0].certServer certificate (public key) (if using replication use the certificate created peviously)-----BEGIN CERTIFICATE-----
ssl.certificates[0].keyServer key (private key) (if using replication use the key created peviously)-----BEGIN RSA PRIVATE KEY-----

mysql.cnf

The configuration file for the MySQL-server is provided under the key mysql.configurationsFiles.mysql.cnf. The provided values provide necessary configuration to receive replicated databases from the master database. The following options should normally not be changed:

[mysqld]

log-bin=/var/lib/mysql/bin.log
log-bin-index=/var/lib/mysql/log-bin.index
log-error=/var/lib/mysql/error.log

relay-log=/var/lib/mysql/relay.log
relay-log-info-file=/var/lib/mysql/relay-log.info
relay-log-index=/var/lib/mysql/relay-log.index

log-error=/var/lib/mysql/error.log
log_slave_updates = 1

sql_mode="ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

The other provided options should be adapted to the respective setup:

ParameterDescriptionDefault
read_onlyToggle read only mode. In production this should be on (1). The test mode of the Gerrit slave expects it to be off (0).0
replicate-ignore-dbDatabases not to replicate (replicating the mysql-DB for example would overwrite database users)mysql
binlog_formatFormat of the binlogs (Has to be the same as on master)row
server-idID unique in the MySQL setup42

In addition, if using SSL for MySQL-requests the following options have to be made available by uncommenting them. The values must not be changed, when using the chart:

ssl-ca=/ssl/ca.pem
ssl-cert=/ssl/server-cert.pem
ssl-key=/ssl/server-key.pem

Replication

The replication of the MySQL database from master to slave is performed using the replication functionality provided by MySQL. To start replication a database dump from the master has to be loaded into the database slave. Then the slave has to be configured for replication and replication has to be started. This is done by a job provided by the chart.

The Job needs to be configured with the data retrieved from the database master by configuring the corresponding values in the values.yaml-file:

ParameterDescriptionDefault
database.replication.mysql.config.masterHostHostname of the Mysql database mastermysql.example.com
database.replication.mysql.config.masterPortPort of the Mysql database master3306
database.replication.mysql.config.masterUserUsername of technical user created previouslyrepl
database.replication.mysql.config.masterPasswordPassword of technical user created previouslypassword
database.replication.mysql.config.masterLogFileTransaction log file at timepoint of dump as retrieved previouslymysql-bin.000001
database.replication.mysql.config.masterLogPosTransaction log position at timepoint of dump as retrieved previously111
database.replication.mysql.dbDumpAcceptPathPath, where the replication init script will expect the database dump file to appear/var/data/db/master_dump.sql

Initialize replication

Deploying the gerrit-slave chart with the configuration detailed above, will create a MySQL database with a technical user to be used by the Gerrit slave and an empty ReviewDB database. In addition a Job will be deployed that waits for a database dump to be copied into the container to the location specified in database.replication.mysql.dbDumpAcceptPath. The dump file can be copied using kubectl:

JOB_POD=$(kubectl get pod -l app=mysql-replication-init -o jsonpath="{.items[0].metadata.name}")
kubectl cp <PATH_TO_DUMP> ${JOB_POD}:<DB_DUMP_ACCEPT_PATH>

As soon as the file is fully copied into the container, the script will load the dump into the database and initialize the replication in the slave. The database is then fully configured.