Deploy MySQL replication statefulset on Kubernetes

  Uncategorized
---
kind: PersistentVolume
apiVersion: v1
metadata:
    name: data-mysql-0
spec:
    capacity:
        storage: 5G
    volumeMode: Filesystem
    accessModes:
        - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    storageClassName: efs
    claimRef:
        namespace: default
        name: data-mysql-0
    csi:
        driver: efs.csi.aws.com
        volumeHandle: fs-030fec758ffe09bc9:/mysql/data0
---
kind: PersistentVolume
apiVersion: v1
metadata:
    name: data-mysql-1
spec:
    capacity:
        storage: 5G
    volumeMode: Filesystem
    accessModes:
        - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    storageClassName: efs
    claimRef:
        namespace: default
        name: data-mysql-1
    csi:
        driver: efs.csi.aws.com
        volumeHandle: fs-030fec758ffe09bc9:/mysql/data1
---
kind: PersistentVolume
apiVersion: v1
metadata:
    name: data-mysql-2
spec:
    capacity:
        storage: 5G
    volumeMode: Filesystem
    accessModes:
        - ReadWriteMany
    persistentVolumeReclaimPolicy: Retain
    storageClassName: efs
    claimRef:
        namespace: default
        name: data-mysql-2
    csi:
        driver: efs.csi.aws.com
        volumeHandle: fs-030fec758ffe09bc9:/mysql/data2
---
apiVersion: v1
kind: ConfigMap
metadata:
    name: mysql
    labels:
        app: mysql
        app.kubernetes.io/name: mysql
data:
    primary.cnf: |
        [mysqld]
        log_bin
        sql-mode="STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER"
        max_connections=100
        interactive_timeout=600
        query_cache_type=1
        query_cache_limit=256K
        query_cache_min_res_unit=2k
        query_cache_size = 32M
        innodb_file_per_table=1
        wait_timeout=600
        expire_logs_days=7
        innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:10G
        innodb_data_home_dir = /var/lib/mysql
        innodb_log_group_home_dir = /var/lib/mysql
    replica.cnf: |
        [mysqld]
        super-read-only
        sql-mode="STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER"
        max_connections=100
        interactive_timeout=600
        query_cache_type=1
        query_cache_limit=256K
        query_cache_min_res_unit=2k
        query_cache_size = 32M
        innodb_file_per_table=1
        wait_timeout=600
        expire_logs_days=7
        innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:10G
        innodb_data_home_dir = /var/lib/mysql
        innodb_log_group_home_dir = /var/lib/mysql
---
apiVersion: v1
kind: Service
metadata:
    name: mysql
    labels:
        app: mysql
spec:
    ports:
        -   name: mysql
            port: 3306
    clusterIP: None
    selector:
        app: mysql
---
apiVersion: v1
kind: Service
metadata:
    name: mysql-read
    labels:
        app: mysql
        readonly: "true"
spec:
    ports:
        -   name: mysql
            port: 3306
    selector:
        app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
    name: mysql
spec:
    selector:
        matchLabels:
            app: mysql
    serviceName: mysql
    replicas: 3
    template:
        metadata:
            labels:
                app: mysql
        spec:
            initContainers:
                -   name: init-mysql
                    image: mysql:5.7
                    command:
                        - bash
                        - "-c"
                        - |
                            [[ $HOSTNAME =~ -([0-9]+)$ ]] || exit 1
                            ordinal=${BASH_REMATCH[1]}
                            echo [mysqld] > /mnt/conf.d/server-id.cnf
                            echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf

                            if [[ $ordinal -eq 0 ]]; then
                              cp /mnt/config-map/primary.cnf /mnt/conf.d/
                            else
                              cp /mnt/config-map/replica.cnf /mnt/conf.d/
                            fi
                    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"
                        - |
                            [[ -d /var/lib/mysql/mysql ]] && exit 0
                            [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
                            ordinal=${BASH_REMATCH[1]}
                            [[ $ordinal -eq 0 ]] && exit 0
                            ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
                            xtrabackup --prepare --target-dir=/var/lib/mysql
                    volumeMounts:
                        -   name: conf
                            mountPath: /mnt/conf.d
                        -   name: config-map
                            mountPath: /mnt/config-map
                        -   name: data
                            mountPath: /var/lib/mysql
                            subPath: mysql
            containers:
                -   name: mysql
                    image: mysql:5.7
                    env:
                        -   name: MYSQL_ROOT_PASSWORD
                            value: "123456"
                    ports:
                        -   name: mysql
                            containerPort: 3306
                    volumeMounts:
                        -   name: data
                            mountPath: /var/lib/mysql
                            subPath: mysql
                        -   name: conf
                            mountPath: /etc/mysql/conf.d
                    livenessProbe:
                        exec:
                            command: [ "mysqladmin", "--host=localhost","--user=root","--password=123456", "ping" ]
                        initialDelaySeconds: 30
                        periodSeconds: 10
                        timeoutSeconds: 5
                    readinessProbe:
                        exec:
                            command: [ "mysql", "--host=localhost","--user=root","--password=123456", "-e", "SELECT 1" ]
                        initialDelaySeconds: 5
                        periodSeconds: 2
                        timeoutSeconds: 1
                -   name: xtrabackup
                    image: gcr.io/google-samples/xtrabackup:1.0
                    ports:
                        -   name: xtrabackup
                            containerPort: 3307
                    volumeMounts:
                        -   name: data
                            mountPath: /var/lib/mysql
                            subPath: mysql
                        -   name: conf
                            mountPath: /etc/mysql/conf.d
                    command:
                        - bash
                        - "-c"
                        - |
                            cd /var/lib/mysql
                            if [[ -f xtrabackup_slave_info && "x$(<xtrabackup_slave_info)" != "x" ]]; then
                                cat xtrabackup_slave_info | sed -E 's/;$//g' > change_master_to.sql.in
                                rm -f xtrabackup_slave_info xtrabackup_binlog_info
                            elif [[ -f xtrabackup_binlog_info ]]; then
                                [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
                                rm -f xtrabackup_binlog_info xtrabackup_slave_info
                                echo "CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
                                    MASTER_LOG_POS=${BASH_REMATCH[2]}" > change_master_to.sql.in
                            fi
                    
                            if [[ -f change_master_to.sql.in ]]; then
                                until mysql -h 127.0.0.1 --user=root --password=123456 -e "SELECT 1"; do sleep 1; done
                                mysql -h 127.0.0.1 --user=root --password=123456 \
                                    -e "$(<change_master_to.sql.in), \
                                        MASTER_HOST='mysql-0.mysql', \
                                        MASTER_USER='root', \
                                        MASTER_PASSWORD='123456', \
                                        MASTER_CONNECT_RETRY=10; \
                                        START SLAVE;" || exit 1
                                mv change_master_to.sql.in change_master_to.sql.orig
                            fi
                            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 --password=123456"
            volumes:
                -   name: conf
                    emptyDir: { }
                -   name: config-map
                    configMap:
                        name: mysql
    volumeClaimTemplates:
        -   metadata:
                name: data
            spec:
                accessModes:
                    - ReadWriteMany
                storageClassName: efs
                resources:
                    requests:
                        storage: 5G