Kubernetes安装Mysql集群
默认已配置好kubernetes与storageClass(本文使用directpv-min-io)
文章部署未使用helm和operator,慎用
kubernetes1.25 mysql5.7
1、namsSpace
apiVersion: v1
kind: Namespace
metadata:
name: mysql
labels:
app: mysql
2、configMap
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
namespace: mysql
labels:
app: mysql
data:
master.cnf: |
# Master配置
[mysqld]
datadir=/var/lib/mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysql/mysql.sock
log-error=/var/log/mysql/error.log
log-bin=mysqllog
skip-name-resolve
lower-case-table-names=1
log_bin_trust_function_creators=1
slave.cnf: |
# Slave配置
[mysqld]
datadir=/var/lib/mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysql/mysql.sock
log-error=/var/log/mysql/error.log
skip-name-resolve
log-bin=mysql-bin
lower-case-table-names=1
log_bin_trust_function_creators=1
3、secret
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: mysql
labels:
app: mysql
type: Opaque
data:
# 需使用base64编码
password: MTIzNDU2 # 123456
# 主从用的账号
replicationUser: Y29weQ== # copy
replicationPassword: MTIzNDU2 # 123456
4、service
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: mysql
labels:
app: mysql
spec:
selector:
# 匹配带有app: mysql标签的pod
app: mysql
clusterIP: None
ports:
- name: mysql
port: 3306
---
apiVersion: v1
kind: Service
metadata:
labels:
app: mysql-master-node
name: mysql-master-node
namespace: mysql
spec:
type: NodePort
ports:
- name: mysql
port: 3306
# 可使用此端口在外部访问
nodePort: 30000
selector:
# 匹配带有mysql-role=master标签的pod
mysql-role: master
5、statefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: mysql
spec:
replicas: 3
selector:
matchLabels:
app: mysql
# 需与service name保持一致
serviceName: mysql
template:
metadata:
labels:
app: mysql
spec:
volumes:
# 将configMap中的数据挂载到容器
- name: configmap
configMap:
name: mysql
# 初始化容器,为mysql准备配置文件
initContainers:
- name: init-mysql
image: mysql:5.7
# 需要将mysql数据和配置文件挂载出去,因为initContainers与containers数据不互通
volumeMounts:
- name: configmap
mountPath: /app
- name: conf
mountPath: /etc/mysql/conf.d
- name: data
mountPath: /var/lib/mysql
# mysql用户配置
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
- name: MYSQL_REPLICATION_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: replicationUser
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: replicationPassword
# 启动命令为sh脚本文件
command:
- /bin/bash
- -c
- |
set -ex
# 获取mysql-0后面的0,如果pod名称不是mysql-x,需要修改此处获取方法
ordinal=`hostname | awk -F"-" '{print $2}'`
# 为mysql准备server-id
echo [mysqld] > /etc/mysql/conf.d/server-id.cnf
# server-id不能是0,所以添加偏移
echo server-id=$((100 + $ordinal)) >> /etc/mysql/conf.d/server-id.cnf
# 如果是主节点,则用master.cnf,否则使用slave.cnf
if [[ ${ordinal} -eq 0 ]]; then
cp /app/master.cnf /etc/mysql/conf.d
else
cp /app/slave.cnf /etc/mysql/conf.d
fi
containers:
- name: mysql
image: mysql:5.7
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3306
protocol: TCP
# mysql用户配置
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
- name: MYSQL_REPLICATION_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: replicationUser
- name: MYSQL_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: replicationPassword
# 需要将mysql数据和配置文件挂载出去,这里用来获取initContainers初始化好的配置文件
volumeMounts:
- name: configmap
mountPath: /app
- name: conf
mountPath: /etc/mysql/conf.d
- name: data
mountPath: /var/lib/mysql
lifecycle:
postStart:
exec:
command:
- bash
- -c
- |
set -ex
cd /var/lib/mysql
# 判断是否已经初始化
if [ ! -f mysqlInitOk ]; then
# 一直尝试执行mysql命令,直到成功
until mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "use mysql;SELECT 1;"; do sleep 1; done
echo "Initialize ready"
# 判断是否为主节点
pod_seq=$(hostname | awk -F"-" '{print $2}')
# 如果是主节点
if [ $pod_seq -eq 0 ]; then
# 创建主从用户
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "create user '${MYSQL_REPLICATION_USER}'@'%' identified by '${MYSQL_REPLICATION_PASSWORD}';"
# 为用户添加权限
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "grant replication slave on *.* to '${MYSQL_REPLICATION_USER}'@'%' with grant option;"
# 刷新配置
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "flush privileges;"
# 重启
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "reset master;"
# 如果是从节点
else
# 连接主节点,mysql-0.mysql.mysql表示{pod-name}.{service-name}.{namespace}
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e \
"change master to master_host='mysql-0.mysql.mysql',master_port=3306, \
master_user='${MYSQL_REPLICATION_USER}',master_password='${MYSQL_REPLICATION_PASSWORD}', \
master_log_file='mysql-bin.000001',master_log_pos=156;"
# 重置slave
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "reset slave;"
# 重启
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "start slave;"
# 设置从节点只读
mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "set global super_read_only=on;"
fi
# 标识已初始化
touch mysqlInitOk
fi
# 卷申请模版
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
storageClassName: directpv-min-io
resources:
requests:
storage: 5Gi
- metadata:
name: conf
spec:
accessModes:
- ReadWriteOnce
storageClassName: directpv-min-io
resources:
requests:
storage: 50Mi
# 为主节点打标记
kubectl label -n mysql pod mysql-0 mysql-role=master
6、测试
# 查看initContainers日志
kubectl logs -n mysql mysql-0 -c init-mysql
# 进入指定容器(主节点无法查看从节点连接情况)
kubectl exec -it -n mysql mysql-0 -c mysql -- /bin/bash
# 查看从节点连接情况
mysql -uroot -p123456
show slave status\G;
# 可以自己尝试在主节点创建数据库、表,查看从节点是否同步创建