搭建MySQL高可用集群

项目描述

项目名称:MySQL高可用主从复制集群
项目环境:CentOS(7.6.2003),MySQL(5.7.29),MySQL Router(8.0.21),Keepalived (v1.3.5),Ansible(2.9.13),Zabbix(4.4.6),nginx(1.19.2)
项目描述:利用Keepalived构建一个高可用MySQL集群,提供读写分离、主从复制、自动故障切换功能,使用Ansible实现自动化运维,使用Zabbix对集群进行监控。
项目步骤:
1. 准备6台虚拟机,做好初试化,如修改主机名、关闭防火墙、配置静态ip;
2. 管理主机ADMIN安装Ansible,配置管理服务器到其它所有机器的ssh免密通道;
3. 在所有主机上安装好相应的服务
	* 所有服务器上安装Zabbix-agent
	* 管理主机上安装Zabbix-server
	* MYSQL-ROUTER-* 上安装MySQL-router
	* MYSQL-MASTER、MYSQL-SLAVE-*上安装MySQL
4. 在MySQL集群服务器上配置好主从复制,一主二从;
5. 在MYSQL-ROUTER节点上配置读写分离;
6. 在MYSQL-ROUTER节点上安装好Keepalived,做好相关配置,设置好vip,实现高可用;
7. 在zabbix里配置好监控所有机器的cpu,内存,磁盘,网络带宽,MySQL服务的自定义监控项目(并发等参数的监控)以及微信告警。
8. 模拟MHA的思路,编写主从切换的监控脚本,实现自动的主从切换,提升另外的一台slave为master,其他的slave成为新的master的从。
遇到的问题:配置MySQL主从复制时Slave_IO_Running状态为No
		  故障原因:主从服务器上的MySQL来自同一个镜像,UUID一致
		  解决方式:删除auto.cnf,重新获取UUID
项目心得:通过这个项目对HA和负载均衡,读写分离有了更加深刻的认识,因为步骤比较多,需要细心,也锻炼了自己的troubleshooting的能力,编写类似MHA的主从切换故障转移的脚本,对主从复制有了更加深刻的了解。

拓扑结构

环境配置

配置 参数
OS CentOS Linux release 7.8.2003 (Core)
disk 20G
memory 512M
MySQL 5.7.29
MySQL Router 8.0.21
Keepalived Keepalived v1.3.5 (03/19,2017)
Ansible ansible 2.9.13
Zabbix 4.4.6
NGINX 1.19.2
ADMIN 192.168.1.101
MYSQL-ROUTER 1 192.168.1.102
MYSQL-ROUTER 2 192.168.1.103
MYSQL-MASTER 192.168.1.104
MYSQL-SLAVE-1 192.168.1.105
MSYQL-SLAVE-2 192.168.1.106
VIP(virtual ip) 192.168.1.111

详细操作

一、准备工作

# 修改主机名
# 临时修改
hostname xxx
# 永久修改
hostnamectl set-hostname xxx

# 关闭NetworkManager,并禁止开机自启
systemctl stop NetworkManager
systemctl disable NetworkManager
# 修改网卡脚本,配置静态ip
yum install vim -y
vim /etc/sysconfig/network-scripts/ifcfg-ens33
# 重启服务
service network restart

# 关闭防火墙和selinux,并禁止开机自启
service firewalld stop
systemctl disable firewalld.service
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config

二、安装Ansible

1. 配置免密通道

# 在主机A上使用命令将主机A的公钥传输至主机B,以实现主机A免密访问主机B
ssh-keygen
ssh-copy-id -i ~/.ssh/id_rsa.put root@192.168.8.101

# 或将主机A的公钥复制到主机B的~/.ssh/authorized_keys文件中实现主机A免密访问主机B

2. 安装Ansible

# 安装epel源
[root@admin ~]# yum install epel-release -y
# 安装ansible
[root@admin ~]#  yum install ansible -y
# 查看ansible版本,是否安装成功
[root@admin ~]# ansible --version

3. 配置主机清单

[root@admin ~]# cat >> /etc/ansible/hosts <<EOF
[HA]
192.168.8.102
192.168.8.103

[MySQL]
192.168.1.104
192.168.1.105
192.168.1.106
EOF

三、安装在各主机上安装相应的服务

1. 编写MySQL编译安装脚本mysql_setup.sh

echo '#################################################'
echo '开始安装MySQL'

# 下载依赖包
yum install cmake ncurses-devel gcc gcc-c++ bzip2 openssl-devel -y

# 新建一个无家目录且禁止登录的用户mysql,这个用户是linux系统用来启动MySQL的。
useradd -r -s /sbin/nologin mysql
# 新建一个给MySQL存放数据的目录
mkdir -p /data/mysql
# 修改数据目录的属主为mysql用户
chown mysql:mysql /data/mysql

# 下载源码包
curl -O https://downloads.mysql.com/archives/get/p/23/file/mysql-community-5.7.29-1.el7.src.rpm
# 解压源码包
rpm -ivh mysql-community-5.7.29-1.el7.src.rpm
# 进入存放真正源码包的目录
cd rpmbuild/SOURCES
# 解压mysql-5.7.29.tar.gz,就是源码所在的压缩包。还有一个boost_1_59_0.tar.bz2包,Boost是为C++语言标准库提供扩展的一些C++程序库的总称。
tar xf mysql-5.7.29.tar.gz
tar xf boost_1_59_0.tar.bz2
# 将解压后的boost包目录移动到解压后的mysql包目录下
mv boost_1_59_0 mysql-5.7.29

# 进入解压后的mysql包
cd mysql-5.7.29


#进行编译前的配置
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql  -DSYSCONFDIR=/etc  -DMYSQL_USER=mysql  -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci  -DWITH_BOOST=boost_1_59_0

# 编译
make
# 安装
make install

# 备份,并清空配置文件
cp /etc/my.cnf /root/mysql.cnf.bak	&>/dev/null
>/etc/my.cnf

# 重置配置文件
cat >/etc/my.cnf << EOF
[mysqld_safe]
log-error=/var/log/mysql/mysql.log

[client]
socket=/tmp/mysql.sock

[mysqld]
socket=/tmp/mysql.sock
port = 3306
open_files_limit = 8192
innodb_buffer_pool_size = 512M

[mysql]
auto-rehash
prompt=\u@\d \R:\m  mysql>
EOF

# 创建MySQL日志文件目录
mkdir -p /var/log/mysql
chown mysql:mysql /var/log/mysql

# 初始化MySQL
# 进入编译安装好的mysql的目录(安装目录)
cd /usr/local/mysql/bin
# 执行mysqld这个程序,初始化mysql,并且将日志和临时密码重定向到/root/temp_password.txt文件里
./mysqld --initialize  --user=mysql --basedir=/usr/local/mysql/  --datadir=/data/mysql  &>/root/temp_password.txt

# 将新的PATH变量重定向到/etc/bashrc文件(下次开机生效)
echo 'PATH=$PATH:/usr/local/mysql/bin' >>/etc/bashrc
# 刷新环境变量
#source /etc/bashrc
PATH=$PATH:/usr/local/mysql/bin

# 拷贝mysqld的程序文件到指定的目录,方便后面设置mysqld服务开机启动。
# 加斜杠直接覆盖不提示
cp ../support-files/mysql.server /etc/init.d/mysqld

#关闭防火墙firewalld服务
service firewalld stop &>/dev/null
#设置firewalld服务开机不启动
systemctl  disable firewalld &>/dev/null
#临时关闭selinux
setenforce 0 &>/dev/null
#永久修改selinux配置文件里的内容
sed -i 's/=enforcing/=disabled/g' /etc/selinux/config &>/dev/null

# 设置开机启动MySQL
chkconfig --add mysqld
# 启动MySQL
service mysqld start

#从保存的临时密码文件里,截取出临时密码,赋值给一个变量temp_pwd
temp_pwd=$(cat /root/temp_password.txt |tail -1|awk '{print $11}')
#给MySQL设置密码为MySqlroot123#
mysql -uroot -p$temp_pwd  --connect-expired-password -e "set password='MySqlroot123#'"

echo '###### congratulation! your mysql has be installed successfully ######'

2. 编写MySQL-router安装脚本

MySQL Router安装脚本mysql_router_setup.sh。

# 下载安装CentOS7版本的rpm包
wget https://dev.mysql.com/get/Downloads/MySQL-Router/mysql-router-community-8.0.21-1.el7.x86_64.rpm
rpm -ivh mysql-router-community-8.0.21-1.el7.x86_64.rpm

3. 安装Zabbix

在ADMIN上搭建LNMP环境,安装Zabbix-server

# 下载所需要的包
[root@admin ~]# mkdir -p zabbix
[root@admin ~]# cd zabbix

[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-agent-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-get-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-java-gateway-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-js-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-proxy-mysql-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-sender-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/zabbix-server-mysql-4.4.6-1.el7.x86_64.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/frontend/zabbix-nginx-conf-scl-4.4.6-1.el7.noarch.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/frontend/zabbix-web-4.4.6-1.el7.noarch.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/frontend/zabbix-web-japanese-4.4.6-1.el7.noarch.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/frontend/zabbix-web-mysql-scl-4.4.6-1.el7.noarch.rpm
[root@admin ~]# curl -O https://mirrors.aliyun.com/zabbix/zabbix/4.4/rhel/7/x86_64/frontend/zabbix-web-deps-scl-4.4.6-1.el7.noarch.rpm

[root@admin ~]# yum install zabbix-* -y

# 安装MySQL(Mariadb)
[root@admin ~]# yum install mariadb mariadb-server -y
[root@admin ~]# service mariadb restart
[root@admin ~]# ps -ef | grep mysqld

# 授权zabbix这个用户可以进入mariadb
[root@admin ~]# mysql
> create database zabbix character set utf8 collate utf8_bin;
> grant all privileges on zabbix.* to zabbix@localhost identified by 'zabbix123';

# 导入数据到zabbix库
[root@admin ~]# cd /usr/share/doc/zabbix-server-mysql-4.4.6/
[root@admin ~]# gunzip create.sql.gz
[root@admin ~]# mysql -uzabbix -p'zabbix123' zabbix < create.sql

# 修改zabbix_server.conf的数据库配置
[root@admin ~]# vim /etc/zabbix/zabbix_server.conf
DBHost=localhost
DBName=zabbix
DBUser=zabbix
DBPassword=zabbix123

DBSocket=/data/mysql/mysql.sock
DBPort=3306

# 启动服务
[root@admin ~]# service zabbix-server start
[root@admin ~]# systemctl enable zabbix-server

# 查看10051端口是否启动
[root@admin ~]# netstat -ntpl | grep 10051

其他主机作为被监控机,安装zabbix-agent

# 管理主机上使用ansible批量安装zabbix-agent
ansible all -m copy -a "src=./zabbix/zabbix-agent-4.4.6-1.el7.x86_64.rpm dest=/root/"
ansible all -m shell -a "yum install ~/zabbix-agent-* -y"

# 修改配置文件,运行zabbix-server过来采集数据
ansible all -m shell -a "sed -i 's/Server=127.0.0.1/Server=192.168.1.101/g' /etc/zabbix/zabbix_agentd.conf"
ansible all -m shell -a "sed -i 's/ServerActive=127.0.0.1/ServerActive=192.168.1.101/g' /etc/zabbix/zabbix_agentd.conf"

# 启动服务
ansible all -m service -a 'name=zabbix-agent state=started'

# 查看10050端口是否启动
ansible all -m shell -a "netstat -ntpl | grep 10050"

启动zabbix-web服务

# 管理主机安装nginx(这里直接粘贴我之前写的脚本)
!/bin/bash

yum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ autoconf automake make

useradd nginx -s /sbin/nologin

curl -O http://nginx.org/download/nginx-1.19.2.tar.gz
tar xf nginx-1.19.2.tar.gz
cd nginx-1.19.2
./configure --prefix=/usr/local/nginx  --with-http_stub_status_module --with-http_realip_module  --with-http_ssl_module  --with-pcre --with-stream
make -j2 && make install

export PATH=$PATH:/usr/local/nginx/sbin/
echo 'export PATH=$PATH:/usr/local/nginx/sbin/' >>/etc/profile

# 启动nginx
/usr/local/nginx/sbin/nginx
echo 'nginx' >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local
netstat -ntpl | grep 80

# 修改管理主机上zabbix前端配置的时区
[root@admin ~]# vim /etc/php-fpm.d/zabbix.conf
php_value[date.timezone] = Asia/Shanghai

# 使用nginx——》LNMP环境
[root@admin ~]# systemctl restart php-fpm
[root@admin ~]# systemctl enable php-fpm

# 修改nginx配置
[root@admin ~]# vim /etc/nginx/conf.d/zabbix.conf

server {
	listen 80;
	server_name	www.Charramma.com
	...
}

[root@admin ~]# vim /etc/nginx/conf.d/zabbix.conf
http {
	include /etc/nginx/conf.d/zabbix.conf
	...
}

# 重启nginx服务
[root@admin ~]# /usr/local/nginx/sbin/nginx -s reload

# 测试连通性
[root@admin ~]# zabbix_get -s 192.168.1.73 -p 10050 -k "system.cpu.load[all,avg1]"
0.060000

在Windows主机上的hosts文件中添加192.168.1.101 www.charramma.com

访问http://charramma.com/setup.php






账户:Admin
密码:zabbix

4. 编写playbook

编写playbook,安装MySQL、Keepalived、MySQL Router

service_setup.yml

- hosts: MySQL,HA
  remote_user: root
  tasks:
  - name: install epel
  	yum:
  	  name: epel-release
  	  state: latest
  	  
- hosts: HA
  remote_user: root
  tasks:
  - name: install keepalived
    yum: 
      name: keepalived
      state: latest
  - name: keepalived service start
    service:
      name: keepalived
      state: started
      enabled: true   
  - name: mysql router setup
    script: ./mysql_router_setup.sh
  
- hosts: MySQL
  remote_user: root
  tasks:
  - name: mysql setup script copy
    copy:
      src: ./mysql_setup.sh
      dest: /root
  - name: mysql setup
    shell: source /root/mysql_setup.sh

执行yml

[root@admin ~]# ansible-playbook service-setup.yml

至此,所需要的服务全部安装完成

四、MySQL集群配置主从复制

在MySQL集群上配置主从复制、一主二从

1. 开启二进制日志

mkdir -p /data/mysql/bin_log
chown -R mysql.mysql /data/mysql

vim /etc/my.cnf
[mysqld]
log_bin=/data/mysql/bin_log/myql_binlog
server_id=1

# 三台主机server_id各不相同

service mysqld restart

2. 配置主从复制

mysql-master上添加用于复制的用户

> grant replication slave on *.* to 'Tom'@'192.168.1.105' identified by 'MySqlTom123#';
> grant replication slave on *.* to 'Tom'@'192.168.1.106' identified by 'MySqlTom123#';
> flush privileges;

备份主服务器上的数据

[root@mysql-master ~]# mysqldump -uroot -p -B --all-databases > backup.sql
[root@mysql-master ~]# scp backup.sql root@192.168.1.105
[root@mysql-master ~]# scp backup.sql root@192.168.1.106

从服务器上导入数据

[root@mysql-slave-1 ~]# mysql -uroot -p < backup.sql
[root@mysql-slave-2 ~]# mysql -uroot -p < backup.sql

主服务器上查看当前二进制文件的名字和位置号

[root@mysql-master ~]# mysql -uroot -p
mysql>flush logs;
mysql>show master status;
+---------------------+----------+--------------+------------------+-------------------+
| File                | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------------+----------+--------------+------------------+-------------------+
| mysql_binlog.000001 |      154 |              |                  |                   |
+---------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

从服务器配置主服务器信息

[root@mysql-slave ~]# mysql -uroot -p
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.73',
	-> MASTER_USER='Tom',
	-> MASTER_PASSWORD='MySqlTom123#',
	-> MASTER_PORT=3306,
	-> MASTER_LOG_FILE='mysql_binlog.000001',
	-> MASTER_LOG_POS=154;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

mysql> start slave;

mysql> show slave status G;
*************************** 1. row ***************************
			...
            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
			...
1 row in set (0.00 sec)

Slave_IO_RunningSlave_SQL_Running都是Yes,说明主从复制已经配置好了

五、配置读写分离

修改mysql-router的配置文件

[root@mysql-router-1 ~]# cat >> /etc/mysqlrouter/mysqlrouter.conf << EOF
[routing:read_write]
bind_address = 192.168.1.112		# mysql-router节点的ip
bind_port = 7001
mode = read-write
destinations = 192.168.1.114:3306	# mysql-master 用于读写
max_connect_errors = 65535
max_connetc_timeout = 9

[routing:read_only]
bind_address = 192.168.1.112		# mysql-router节点的ip
bing_port = 7002
mode = read-only
destinations = 192.168.1.115:3306,192.168.1.116:3306
max_connect_errors = 65535
max_connetc_timeout = 9
EOF

启动服务

[root@mysql-router-1 ~]# systemctl start mysqlrouter

[root@mysql-router-1 ~]# netstat -ntpl | grep mysqlrouter
tcp        0      0 192.168.1.112:7001      0.0.0.0:*               LISTEN      4511/mysqlrouter    
tcp        0      0 192.168.1.112:7002      0.0.0.0:*               LISTEN      4511/mysqlrouter

mysql-router-2同样如此操作

六、配置高可用

mysql-router节点上配置keepalievd实现高可用

[root@mysql-router-1 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
   # 注释掉下面这一行
   vrrp_strict
}

vrrp_instance VI_1 {
    state MASTER
    interface ens33
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.111
    }
}
# 删掉下面所有内容
[root@mysql-router-2 ~]# vim /etc/keepalived/keepalived.conf
global_defs {
   # 注释掉下面这一行
   vrrp_strict
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 99
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.1.111
    }
}
# 删掉下面所有内容

重启服务

service keepalived start

将vip绑定到MySQL-router上

vim /etc/mysqlrouter/mysqlrouter.conf
# 将bind_address改为192.168.1.111

# 重启mysql-router
systemctl restart mysql-router

未完成,有时间再补全。。。-_-||

原文地址:https://www.cnblogs.com/CharrammaBlog/p/14587375.html