k8s部署mysql一主两从

完整的脚本下载,前往gitee:https://gitee.com/qiaodaimadewangcai/study-notes/tree/master/k8s/k8s部署mysql主从/yaml

一、k8s部署mysql主从需要解决上面问题

问题

  1. 启动顺序有要求,master节点必须比slave节点先启动
  2. 节点挂掉了,新的pod启动必须使用原先pod的资源
  3. master与slave的配置不一样
  4. master启动之后需要设置主从授权账户,slave需要执行change master命令,以及加入主从的命令
  5. 希望客户账户名密码自己配置
  6. slave需要知道master节点的地址

解决方案

  1. 使用statefulSet可以使得pod副本按照编号顺序进行启动,只需要把pod-0作为master就可以了
  2. 使用pv和pvc解决,通过pvc与pod的标签进行绑定,一个pod对应一个pvc就可以保证重启后的pod依旧使用原先的资源
  3. 使用configmap可以在容器初始化的时候指定需要的配置信息,
  4. 使用initContainer可以在容器初始化的时候执行需要的脚本
  5. 使用secret可以将密码保密
  6. 使用headless service+dns可以让slave节点通过hostname访问master,hostname固定为podName.ServiceName,如:serviceName为mysql,则master的hostname为mysql-0.mysql

部署思路

  1. 编写namespace脚本,创建专门的namespace
  2. 编写configmap,将mysql的配置文件配置到里面
  3. 编写secret脚本,将需要的密码配置在里面
  4. 编写initContainer脚本(备用),根据hostname判断是master还是slave,进而执行对应的命令
  5. 编写pv和pvc脚本,申请磁盘资源(通过storageClass自动进行pv/pvc的创建)
  6. 编写headless service脚本,配置mysql之间的网络关系
  7. 编写StatefulSet脚本,初始化容器

二、部署

部署说明

软件名称 软件版本
mysql v8.0.21
kubernetes v20.10.17
docker v1.23.10

部署条件

  1. 有个k8s集群
  2. k8s集群集成了nfs之类的作为存储抽象

1、编写namespace脚本

01-mysql-namespace.yaml

apiVersion: v1
#创建Namespace类型资源
kind: Namespace
metadata:
  #资源名称
  name: mysql
  #标签为app:mysql
  labels:
    app: mysql

相关命令

#执行命令
kubectl apply -f 01-mysql-namespace.yaml
#查看命名空间
kubectl get ns

2、编写configmap脚本

02-mysql-configmap.yaml

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
    super-read-only
    skip-name-resolve
    log-bin=mysql-bin
    lower-case-table-names=1
    log_bin_trust_function_creators=1

相关命令

#执行命令
kubectl apply -f 02-mysql-configmap.yaml
#查看mysql命名空间下的configmap
kubectl get cm -n mysql
#查看mysql命名空间下名为mysql的configmap详情
kubectl describe configmap mysql -n mysql

3、编写secret脚本

03-mysql-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
  namespace: mysql
  labels:
    app: mysql
#Opaque 类型的数据是一个 map 类型,要求value是base64编码。
type: Opaque
data:
  password: YTEyMzQ1NiE= #123456转成base64 echo -n "a123456!" | base64
  #主从用的账号
  replicationUser: Y29weQ== #copy
  replicationPassword: YTEyMzQ1NiE= #a123456!

相关命令

#执行命令
kubectl apply -f 03-mysql-secret.yaml
#查看mysql命名空间下的configmap
kubectl get secret -n mysql
#查看mysql命名空间下名为mysql-secret的secret详情
kubectl describe secret mysql-secret -n mysql

4、编写initContainer脚本

ps:编写的脚本,最后会在创建StatefulSet中使用,这里只是为了展示的更清晰

1)将配置文件拷贝到对应的容器中

set -ex
#从pod的hostname中通过正则获取序号,如果没有截取到就退出程序
ordinal=`hostname | awk -F"-" '{print $2}'` || exit 1
#将serverId输入到对应的配置文件中,路径可以随意(与之后的对应上就行),但是文件名不能换
echo [mysqld] > /etc/mysql/conf.d/server-id.cnf
# 由于server-id不能为0,因此给ID加100来避开它
echo server-id=$((100 + $ordinal)) >> /etc/mysql/conf.d/server-id.cnf
if [[ ${ordinal} -eq 0 ]]; then
  # 如果Pod的序号为0,说明它是Master节点,从ConfigMap里把Master的配置文件拷贝到/mnt/conf.d目录下
  cp /mnt/config-map/master.cnf /etc/mysql/conf.d
else
  # 否则,拷贝ConfigMap里的Slave的配置文件
  cp /mnt/config-map/slave.cnf /etc/mysql/conf.d
fi

2)初始化mysql集群

set -ex
cd /var/lib/mysql
#查看是否存在名为mysqlInitOk的文件,我们自己生产的标识文件,防止重复初始化集群
if [ ! -f mysqlInitOk ]; then
  echo "Waiting for mysqld to be ready(accepting connections)"
  #执行一条mysql的命令,查看mysql是否初始化完毕,如果没有就反复执行直到可以运行
    until mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "use mysql;SELECT 1;"; do sleep 1; done
    echo "Initialize ready"
    #判断是master还是slave
    pod_seq=`hostname | awk -F"-" '{print $2}'`
    if [ $pod_seq -eq 0 ];then
      #创建主从账户
    mysql -uroot -p${MYSQL_ROOT_PASSWORD
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值