83ba9575f9
The data dir should not be at the root of the volume, because many volume types create files or directories there automatically. The database initialization script requires the data dir to be empty, and we shouldn't try to guess which files may exist. In particular, by retaining lost+found, it also becomes possible to recover files that end up there.
165 lines
5.6 KiB
YAML
165 lines
5.6 KiB
YAML
apiVersion: apps/v1beta1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: mysql
|
|
spec:
|
|
serviceName: mysql
|
|
replicas: 3
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: mysql
|
|
annotations:
|
|
pod.beta.kubernetes.io/init-containers: '[
|
|
{
|
|
"name": "init-mysql",
|
|
"image": "mysql:5.7",
|
|
"command": ["bash", "-c", "
|
|
set -ex\n
|
|
# Generate mysql server-id from pod ordinal index.\n
|
|
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1\n
|
|
ordinal=${BASH_REMATCH[1]}\n
|
|
echo [mysqld] > /mnt/conf.d/server-id.cnf\n
|
|
# Add an offset to avoid reserved server-id=0 value.\n
|
|
echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf\n
|
|
# Copy appropriate conf.d files from config-map to emptyDir.\n
|
|
if [[ $ordinal -eq 0 ]]; then\n
|
|
cp /mnt/config-map/master.cnf /mnt/conf.d/\n
|
|
else\n
|
|
cp /mnt/config-map/slave.cnf /mnt/conf.d/\n
|
|
fi\n
|
|
"],
|
|
"volumeMounts": [
|
|
{"name": "conf", "mountPath": "/mnt/conf.d"},
|
|
{"name": "config-map", "mountPath": "/mnt/config-map"}
|
|
]
|
|
},
|
|
{
|
|
"name": "clone-mysql",
|
|
"image": "gcr.io/google-samples/xtrabackup:1.0",
|
|
"command": ["bash", "-c", "
|
|
set -ex\n
|
|
# Skip the clone if data already exists.\n
|
|
[[ -d /var/lib/mysql/mysql ]] && exit 0\n
|
|
# Skip the clone on master (ordinal index 0).\n
|
|
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1\n
|
|
ordinal=${BASH_REMATCH[1]}\n
|
|
[[ $ordinal -eq 0 ]] && exit 0\n
|
|
# Clone data from previous peer.\n
|
|
ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql\n
|
|
# Prepare the backup.\n
|
|
xtrabackup --prepare --target-dir=/var/lib/mysql\n
|
|
"],
|
|
"volumeMounts": [
|
|
{"name": "data", "mountPath": "/var/lib/mysql", "subPath": "mysql"},
|
|
{"name": "conf", "mountPath": "/etc/mysql/conf.d"}
|
|
]
|
|
}
|
|
]'
|
|
spec:
|
|
containers:
|
|
- name: mysql
|
|
image: mysql:5.7
|
|
env:
|
|
- name: MYSQL_ALLOW_EMPTY_PASSWORD
|
|
value: "1"
|
|
ports:
|
|
- name: mysql
|
|
containerPort: 3306
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /var/lib/mysql
|
|
subPath: mysql
|
|
- name: conf
|
|
mountPath: /etc/mysql/conf.d
|
|
resources:
|
|
requests:
|
|
cpu: 1
|
|
memory: 1Gi
|
|
livenessProbe:
|
|
exec:
|
|
command: ["mysqladmin", "ping"]
|
|
initialDelaySeconds: 30
|
|
timeoutSeconds: 5
|
|
readinessProbe:
|
|
exec:
|
|
# Check we can execute queries over TCP (skip-networking is off).
|
|
command: ["mysql", "-h", "127.0.0.1", "-e", "SELECT 1"]
|
|
initialDelaySeconds: 5
|
|
timeoutSeconds: 1
|
|
- name: xtrabackup
|
|
image: gcr.io/google-samples/xtrabackup:1.0
|
|
ports:
|
|
- name: xtrabackup
|
|
containerPort: 3307
|
|
command:
|
|
- bash
|
|
- "-c"
|
|
- |
|
|
set -ex
|
|
cd /var/lib/mysql
|
|
|
|
# Determine binlog position of cloned data, if any.
|
|
if [[ -f xtrabackup_slave_info ]]; then
|
|
# XtraBackup already generated a partial "CHANGE MASTER TO" query
|
|
# because we're cloning from an existing slave.
|
|
mv xtrabackup_slave_info change_master_to.sql.in
|
|
# Ignore xtrabackup_binlog_info in this case (it's useless).
|
|
rm -f xtrabackup_binlog_info
|
|
elif [[ -f xtrabackup_binlog_info ]]; then
|
|
# We're cloning directly from master. Parse binlog position.
|
|
[[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
|
|
rm xtrabackup_binlog_info
|
|
echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
|
|
MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
|
|
fi
|
|
|
|
# Check if we need to complete a clone by starting replication.
|
|
if [[ -f change_master_to.sql.in ]]; then
|
|
echo "Waiting for mysqld to be ready (accepting connections)"
|
|
until mysql -h 127.0.0.1 -e "SELECT 1"; do sleep 1; done
|
|
|
|
echo "Initializing replication from clone position"
|
|
# In case of container restart, attempt this at-most-once.
|
|
mv change_master_to.sql.in change_master_to.sql.orig
|
|
mysql -h 127.0.0.1 <<EOF
|
|
$(<change_master_to.sql.orig),
|
|
MASTER_HOST='mysql-0.mysql',
|
|
MASTER_USER='root',
|
|
MASTER_PASSWORD='',
|
|
MASTER_CONNECT_RETRY=10;
|
|
START SLAVE;
|
|
EOF
|
|
fi
|
|
|
|
# Start a server to send backups when requested by peers.
|
|
exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
|
|
"xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root"
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /var/lib/mysql
|
|
subPath: mysql
|
|
- name: conf
|
|
mountPath: /etc/mysql/conf.d
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 100Mi
|
|
volumes:
|
|
- name: conf
|
|
emptyDir: {}
|
|
- name: config-map
|
|
configMap:
|
|
name: mysql
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: data
|
|
annotations:
|
|
volume.alpha.kubernetes.io/storage-class: default
|
|
spec:
|
|
accessModes: ["ReadWriteOnce"]
|
|
resources:
|
|
requests:
|
|
storage: 10Gi
|
|
|