MySQLのmaster-slave構成を構築
MySQLをmaster-slave構成で起動するマニフェストのサンプルです。
MySQL
データベース本体のマニフェストです。
mysql-sts.yaml
- StatefulSetでMysql Podを2台起動し、それぞれにmaster / slaveの状態を持たせます。
- initContainerで、ボリュームを介してそれぞれのコンテナに設定ファイルを渡します:
- mysql-docker-entrypoint-initdb: データーベース初期構築向けSQL
- mysql-conf: master / slaveの設定を持たせるmy.cnf
- volumeClaimTemplatesを使って各Podのバックアップを取ります。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
serviceName: mysql-svc
replicas: 2
template:
metadata:
labels:
app: mysql
spec:
initContainers: # master, slave設定を各Podに投入するコンテナ
- name: mysql-setting
image: busybox:1.28
command: ["sh", "-c", "sh /scripts/mysql-setting.sh"]
volumeMounts:
- name: mysql-setting-cm
mountPath: /scripts
- name: mysql-master-temp
mountPath: /temp/master
- name: mysql-slave-temp
mountPath: /temp/slave
- name: mysql-docker-entrypoint-initdb
mountPath: /share/docker-entrypoint-initdb
- name: mysql-conf
mountPath: /share/conf
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-common-secret
key: MYSQL_ROOT_PASSWORD
volumeMounts:
- name: mysql-docker-entrypoint-initdb
mountPath: /docker-entrypoint-initdb.d
- name: mysql-conf
mountPath: /etc/mysql/conf.d
- name: backup
mountPath: /var/lib/mysql
volumes:
- name: mysql-setting-cm # master, slave設定スクリプトを格納
configMap:
name: mysql-setting-cm
items:
- key: mysql-setting.sh
path: mysql-setting.sh
- name: mysql-master-temp # master向け設定ファイルを格納
configMap:
name: mysql-master-temp
items:
- key: my.cnf
path: my.cnf
- key: init.sql
path: init.sql
- name: mysql-slave-temp # slave向け設定ファイルを格納
configMap:
name: mysql-slave-temp
items:
- key: my.cnf
path: my.cnf
- key: init.sql
path: init.sql
- name: mysql-docker-entrypoint-initdb # DB初期化向けスクリプトを格納
emptyDir:
sizeLimit: 500Mi
- name: mysql-conf # initContainerから各MySQLコンテナにmy.cnfを渡す
emptyDir:
sizeLimit: 500Mi
volumeClaimTemplates: # 各Podのバックアップ
- metadata:
name: backup
spec:
accessModes: [ReadWriteOnce]
storageClassName: standard
resources:
requests:
storage: 500Mi
mysql-common-secret.yaml
mysql-[0|1]に共通するSecretです。kubectlコマンドのdry-runによってマニフェストを生成しています(cf. Managing Secrets using kubectl)。
apiVersion: v1
data:
MYSQL_ROOT_PASSWORD: cGFzc3dvcmQ=
kind: Secret
metadata:
name: mysql-common-secret
mysql-setting-cm.yaml
initContainerで動かすスクリプトです。Podのホスト名によって適切な設定ファイルをMySQLコンテナに渡します。
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-setting-cm
data:
mysql-setting.sh: |
if [ "$(hostname)" = "mysql-0" ]; then
cp /temp/master/my.cnf /share/conf
cp /temp/master/init.sql /share/docker-entrypoint-initdb/init.sql
elif [ "$(hostname)" = "mysql-1" ]; then
cp /temp/slave/my.cnf /share/conf
cp /temp/slave/init.sql /share/docker-entrypoint-initdb/init.sql
fi
mysql-master-temp.yaml
master向けのmy.cnfおよびinit.sqlです。
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-master-temp
data:
my.cnf: |
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
gtid-mode = ON
enforce-gtid-consistency = ON
init.sql: |
-- レプリケーション担当ユーザ作成
CREATE USER IF NOT EXISTS 'repl'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'replpass';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
-- アプリケーションからアクセスするユーザ作成
CREATE USER IF NOT EXISTS 'appuser'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'appuserpass';
GRANT ALL PRIVILEGES ON *.* TO 'appuser'@'%';
-- proxysqlからの監視ユーザ作成
CREATE USER IF NOT EXISTS 'monitor'@'%' IDENTIFIED BY 'monitorpass';
GRANT USAGE ON *.* TO 'monitor'@'%';
-- 業務テーブル作成
CREATE DATABASE eadb;
USE eadb;
CREATE TABLE users (name VARCHAR(8) PRIMARY KEY, password VARCHAR(32));
INSERT INTO users (name, password) VALUES ('nob', 'passwd');
mysql-slave-temp.yaml
slave向けのmy.cnfおよびinit.sqlです。
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-slave-temp
data:
my.cnf: |
[mysqld]
server-id = 2
relay-log = relay-bin
read-only = 1
gtid-mode = ON
enforce-gtid-consistency = ON
init.sql: |
-- レプリカ設定
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='mysql-0.mysql-svc',
SOURCE_USER='repl',
SOURCE_PASSWORD='replpass',
SOURCE_AUTO_POSITION=1;
START REPLICA;
-- アプリケーション向けユーザ作成
CREATE USER IF NOT EXISTS 'appuser'@'%' IDENTIFIED WITH 'mysql_native_password' BY 'appuserpass';
GRANT ALL PRIVILEGES ON *.* TO 'appuser'@'%';
-- 監視向けユーザ作成
CREATE USER IF NOT EXISTS 'monitor'@'%' IDENTIFIED BY 'monitorpass';
GRANT USAGE ON *.* TO 'monitor'@'%';
mysql-svc.yaml
MySQL向けのサービスです。アプリケーションとの疎通は後述のProxySQLを介して行うため、ここでは Headless Serviceを作成して各Podに直接疎通が取れるようにしています。
apiVersion: v1
kind: Service
metadata:
name: mysql-svc
spec:
selector:
app: mysql
clusterIP: None
ProxySQL
アプリからデータベースへの疎通を担うProxySQLのマニフェストです。
proxysql-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxysql
labels:
app: proxysql
spec:
replicas: 2
selector:
matchLabels:
app: proxysql
template:
metadata:
labels:
app: proxysql
spec:
containers:
- name: proxysql
image: proxysql/proxysql:3.0.2
volumeMounts:
- name: proxysql-cm
mountPath: /etc/proxysql.cnf
subPath: proxysql.cnf
ports:
- containerPort: 3306
volumes:
- name: proxysql-cm
configMap:
name: proxysql-cm
items:
- key: proxysql.cnf
path: proxysql.cnf
proxysql-cm.yaml
master / slaveのルーティングを設定します。mysql-x.mysql-svcでPodに直接疎通します。
apiVersion: v1
kind: ConfigMap
metadata:
name: proxysql-cm
data:
proxysql.cnf: |
mysql_variables =
{
interfaces="0.0.0.0:3306"
server_version="8.0"
monitor_username="monitor"
monitor_password="monitorpass"
}
mysql_servers =
(
{
address="mysql-0.mysql-svc"
port=3306
hostgroup_id=10
max_connections=200
},
{
address="mysql-1.mysql-svc"
port=3306
hostgroup_id=20
max_connections=200
}
)
mysql_users =
(
{
username="appuser"
password="appuserpass"
default_hostgroup=10
transaction_persistent=true
active=1
}
)
mysql_query_rules =
(
{
rule_id=1
active=1
match_pattern="^SELECT"
destination_hostgroup=20
apply=1
},
{
rule_id=2
active=1
match_pattern=".*"
destination_hostgroup=10
apply=1
}
)
mysql_replication_hostgroups =
(
{
writer_hostgroup=10
reader_hostgroup=20
comment="master-slave replication setup"
}
)
proxysql-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: proxysql-svc
spec:
selector:
app: proxysql
ports:
- protocol: TCP
port: 3306
targetPort: 3306