使用ansible自动化安装MySQL8的mysql-router+mysql-shell+mysql架构InnoDB ReplicaSet
【说明】
当前数据库5.7版本不再更新,关注MySQL Community Server 8版本已经发行,使用InnoDB ReplicaSet(主从)架构自动化搭建
【自动化安装】
使用ansible安装mysql-router+mysql-shell+mysql
tree mysql8/
mysql8/
├── mysql_ms.yaml
└── roles
└── mysql_ms
├── tasks
│ └── main.yml
├── templates
│ ├── auto_mysqlroute_pass.sh
│ ├── my.cnf
│ ├── readme.md
│ ├── replicaset_addinstance.js
│ ├── replicaset_configure.js
│ ├── replicaset_create.js
│ └── replicaset_sleep.sql
└── vars
└── main.yml【剧本说明】
环境变量信息,填写对应的介质及路径 cat main.yml --- mysql_tgz: mysql-8.4.0-linux-glibc2.17-x86_64.tar.xz tgz_extracted: mysql-8.4.0-linux-glibc2.17-x86_64 mysqlsh_tgz: mysql-shell-8.4.0-linux-glibc2.17-x86-64bit.tar.gz shtgz_extracted: mysql-shell-8.4.0-linux-glibc2.17-x86-64bit mysql_router: mysql-router-community-8.4.0-1.el7.x86_64.rpm db_data: /db/mysql monitor_user: monitor download_target: /tmp/deployer
ansible的hosts配置文件,这里将密码汇总是方便hosts文件加密
[mysql_ms] 10.x.x.xx7 ansible_user=root ansible_ssh_pass=xxxxxxxx cluster_role=master server_id=103306 10.x.x.xx8 ansible_user=root ansible_ssh_pass=xxxxxxxx cluster_role=slave server_id=103307 [mysql_ms:vars] mysql_pass='xxxxxxxx' dbadmin_pass='xxxxxxxx' repl_pass='xxxxxxxx' monitor_pass='xxxxxxxx'
主要运行的剧本信息
cat main.yml
---
- name: create mysql user and group
user:
name: mysql
shell: /sbin/nologin
- name: download installation media
copy:
src: "{{download_target}}/{{mysql_tgz}}"
dest: /tmp/{{mysql_tgz}}
- name: decompress mysql package
shell: tar -xf /tmp/{{mysql_tgz}} -C /usr/local/
- name: add mysql conf
template:
src: my.cnf
dest: /etc/my.cnf
owner: mysql
group: mysql
- name: link mysql
file:
src: /usr/local/{{tgz_extracted}}
dest: /usr/local/mysql
owner: mysql
group: mysql
state: link
- name: create data directory
file:
path: '{{db_data}}/{{item}}'
state: directory
owner: mysql
group: mysql
recurse: yes
loop:
- mysql
- logs
- relaylog
- binlog
- name: init mysql
shell: /usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql
- name: copy mysql server script
copy:
src: /usr/local/mysql/support-files/mysql.server
dest: /etc/init.d/mysql
owner: mysql
group: mysql
mode: "0755"
- name: checkconfig mysql
shell: chkconfig --add mysql
- name: Ensure mysql is enabled
systemd:
daemon_reload: yes
name: mysql
enabled: yes
- name: Start mysql
service:
name: mysql
state: restarted
enabled: yes
- name: Pause for 5 seconds
pause:
seconds: 5
- name: set mysql root password
shell: /usr/local/mysql/bin/mysqladmin -uroot password {{mysql_pass}}
- name: add profile for mysql
lineinfile: dest=/etc/profile line='{{ item.line }}'
with_items:
- line: " "
- line: "### for mysql "
- line: "export PATH=/usr/local/mysql/bin:$PATH"
- name: download installation mysqlsh media
copy:
src: "{{download_target}}/{{mysqlsh_tgz}}"
dest: /tmp/{{mysqlsh_tgz}}
- name: decompress mysqlsh package
shell: tar -xf /tmp/{{mysqlsh_tgz}} -C /usr/local/
- name: link mysqlsh
file:
src: /usr/local/{{shtgz_extracted}}
dest: /usr/local/mysqlsh
owner: mysql
group: mysql
state: link
- name: add profile for mysqlsh
lineinfile: dest=/etc/profile line='{{ item.line }}'
with_items:
- line: " "
- line: "### for mysqlsh "
- line: "export PATH=/usr/local/mysqlsh/bin:$PATH"
- name: add dbadmin user
command: /usr/local/mysql/bin/mysql -uroot -p{{mysql_pass}} -e "create user root@'%' identified by '{{mysql_pass}}';GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO `root`@`%` WITH GRANT OPTION;GRANT ALLOW_NONEXISTENT_DEFINER,APPLICATION_PASSWORD_ADMIN,AUDIT_ABORT_EXEMPT,AUDIT_ADMIN,AUTHENTICATION_POLICY_ADMIN,BACKUP_ADMIN,BINLOG_ADMIN,BINLOG_ENCRYPTION_ADMIN,CLONE_ADMIN,CONNECTION_ADMIN,ENCRYPTION_KEY_ADMIN,FIREWALL_EXEMPT,FLUSH_OPTIMIZER_COSTS,FLUSH_STATUS,FLUSH_TABLES,FLUSH_USER_RESOURCES,GROUP_REPLICATION_ADMIN,GROUP_REPLICATION_STREAM,INNODB_REDO_LOG_ARCHIVE,INNODB_REDO_LOG_ENABLE,PASSWORDLESS_USER_ADMIN,PERSIST_RO_VARIABLES_ADMIN,REPLICATION_APPLIER,REPLICATION_SLAVE_ADMIN,RESOURCE_GROUP_ADMIN,RESOURCE_GROUP_USER,ROLE_ADMIN,SENSITIVE_VARIABLES_OBSERVER,SERVICE_CONNECTION_ADMIN,SESSION_VARIABLES_ADMIN,SET_ANY_DEFINER,SHOW_ROUTINE,SYSTEM_USER,SYSTEM_VARIABLES_ADMIN,TABLE_ENCRYPTION_ADMIN,TELEMETRY_LOG_ADMIN,XA_RECOVER_ADMIN ON *.* TO `root`@`%` WITH GRANT OPTION;GRANT PROXY ON ``@`` TO `root`@`%` WITH GRANT OPTION ;"
- name: mysql cluster
set_fact:
mysql_cluster_servers_group: []
- name: declare host group
set_fact:
mysql_cluster_servers_group: "{{mysql_cluster_servers_group}} + [ '{{ item }}' ]"
with_items: "{{ groups['mysql_ms'] }}"
- name: copy db replicatset files
template:
src: ../templates/{{ item }}
dest: /tmp/{{ item }}
mode: 0775
with_items:
['replicaset_configure.js','replicaset_sleep.sql','replicaset_create.js','replicaset_addinstance.js','auto_mysqlroute_pass.sh']
- name: replicaset configure
shell: /usr/local/mysqlsh/bin/mysqlsh -uroot -p{{mysql_pass}} -S /db/mysql/mysql/mysqld.sock --file=/tmp/replicaset_configure.js
when: cluster_role == "master"
- name: replicaset sleep
shell: /usr/local/mysqlsh/bin/mysqlsh -uroot -p{{mysql_pass}} -S /db/mysql/mysql/mysqld.sock --file=/tmp/replicaset_sleep.sql
when: cluster_role == "master"
- name: replicaset create
shell: /usr/local/mysqlsh/bin/mysqlsh -uroot -p{{mysql_pass}} -S /db/mysql/mysql/mysqld.sock --file=/tmp/replicaset_create.js
when: cluster_role == "master"
- name: replicaset sleep
shell: /usr/local/mysqlsh/bin/mysqlsh -uroot -p{{mysql_pass}} -S /db/mysql/mysql/mysqld.sock --file=/tmp/replicaset_sleep.sql
when: cluster_role == "master"
- name: replicaset addinstance
shell: /usr/local/mysqlsh/bin/mysqlsh -uroot -p{{mysql_pass}} -S /db/mysql/mysql/mysqld.sock --file=/tmp/replicaset_addinstance.js
when: cluster_role == "master"
- name: download installation mysql router media
copy:
src: "{{download_target}}/{{mysql_router}}"
dest: /tmp/{{mysql_router}}
- name: install mysql router rpm on all node
yum:
name: '/tmp/{{ item }}'
state: present
with_items:
- "{{ mysql_router }}"
- name: mysqlrouter add replicaset
shell: /usr/bin/expect -f /tmp/auto_mysqlroute_pass.sh
- name: ensure mysqlrouter is enabled
systemd:
daemon_reload: yes
name: mysqlrouter
enabled: yes
- name: start mysqlrouter
service:
name: mysqlrouter
state: restarted
enabled: yes
使用mysql shell创建集群的步骤,这里有sleep原因是太快执行会导致初始化元数据还没有加载导致异常报错
这里需要注意如果是低版本的话,configureReplicaSetInstance时候需要添加一个password参数,代表传入root密码,8.4.0版本不需要这个参数
1 2 3 4 5 6 7 8 9 10 11 12 | cat replicaset_configure.jsdba.configureReplicaSetInstance('root@{{ mysql_cluster_servers_group[0] }}:3306', {clusterAdmin: "'repl'@'%'", clusterAdminPassword: 'Repl_xxxx'});cat replicaset_sleep.sqlselect sleep(10);cat replicaset_create.jsrs = dba.createReplicaSet("replicaset");cat replicaset_addinstance.jsvar rs =dba.getReplicaSet();rs.addInstance('{{ mysql_cluster_servers_group[1] }}:3306',{recoveryMethod: "clone"}); |
使用mysql router命令添加集群脚本,因为查看到没有参数直接添加root密码,当前使用expect命令方式自动输入密码,防止交互式中断
cat auto_mysqlroute_pass.sh
#!/usr/bin/expect -f
set timeout 30
spawn mysqlrouter --bootstrap root@{{ mysql_cluster_servers_group[0] }}:3306 --user=mysqlrouter
expect "Please enter MySQL password for root:"
send {{ mysql_pass }}\n
expect off
【脚本运行情况】
ansible-playbook mysql_ms.yaml
PLAY [mysql_ms] ******************************************************************************************************************************************************************************************
TASK [mysql_ms : create mysql user and group] ************************************************************************************************************************************************************
ok: [10.x.x.xx7]
ok: [10.x.x.xx8]
TASK [mysql_ms : download installation media] ************************************************************************************************************************************************************
ok: [10.x.x.xx8]
ok: [10.x.x.xx7]
TASK [mysql_ms : decompress mysql package] ***************************************************************************************************************************************************************
[WARNING]: Consider using the unarchive module rather than running 'tar'. If you need to use command because unarchive is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : add mysql conf] *************************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : link mysql] *****************************************************************************************************************************************************************************
ok: [10.x.x.xx7]
ok: [10.x.x.xx8]
TASK [mysql_ms : create data directory] ******************************************************************************************************************************************************************
changed: [10.x.x.xx8] => (item=mysql)
changed: [10.x.x.xx8] => (item=logs)
changed: [10.x.x.xx8] => (item=relaylog)
changed: [10.x.x.xx8] => (item=binlog)
changed: [10.x.x.xx7] => (item=mysql)
changed: [10.x.x.xx7] => (item=logs)
changed: [10.x.x.xx7] => (item=relaylog)
changed: [10.x.x.xx7] => (item=binlog)
TASK [mysql_ms : init mysql] *****************************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : copy mysql server script] ***************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : checkconfig mysql] **********************************************************************************************************************************************************************
changed: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : Ensure mysql is enabled] ***************************************************************************************************************************************************************
ok: [10.x.x.xx8]
ok: [10.x.x.xx7]
TASK [mysql_ms : Start mysql] ****************************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : Pause for 5 seconds] ********************************************************************************************************************************************************************
Pausing for 5 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [10.x.x.xx7]
TASK [mysql_ms : set mysql root password] ***************************************************************************************************************************************************************
changed: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : add profile for mysql] ******************************************************************************************************************************************************************
ok: [10.x.x.xx8] => (item={u'line': u' '})
ok: [10.x.x.xx8] => (item={u'line': u'### for mysql '})
ok: [10.x.x.xx8] => (item={u'line': u'export PATH=/usr/local/mysql/bin:$PATH'})
ok: [10.x.x.xx7] => (item={u'line': u' '})
ok: [10.x.x.xx7] => (item={u'line': u'### for mysql '})
ok: [10.x.x.xx7] => (item={u'line': u'export PATH=/usr/local/mysql/bin:$PATH'})
TASK [mysql_ms : download installation mysqlsh media] ****************************************************************************************************************************************************
ok: [10.x.x.xx7]
ok: [10.x.x.xx8]
TASK [mysql_ms : decompress mysqlsh package] *************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : link mysqlsh] ***************************************************************************************************************************************************************************
changed: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : add profile for mysqlsh] ****************************************************************************************************************************************************************
ok: [10.x.x.xx8] => (item={u'line': u' '})
ok: [10.x.x.xx7] => (item={u'line': u' '})
ok: [10.x.x.xx8] => (item={u'line': u'### for mysqlsh '})
ok: [10.x.x.xx7] => (item={u'line': u'### for mysqlsh '})
ok: [10.x.x.xx8] => (item={u'line': u'export PATH=/usr/local/mysqlsh/bin:$PATH'})
ok: [10.x.x.xx7] => (item={u'line': u'export PATH=/usr/local/mysqlsh/bin:$PATH'})
TASK [mysql_ms : add dbadmin user] ***********************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
TASK [mysql_ms : mysql cluster] **************************************************************************************************************************************************************************
ok: [10.x.x.xx7]
ok: [10.x.x.xx8]
TASK [mysql_ms : declare host group] *********************************************************************************************************************************************************************
ok: [10.x.x.xx7] => (item=10.x.x.xx7)
ok: [10.x.x.xx7] => (item=10.x.x.xx8)
ok: [10.x.x.xx8] => (item=10.x.x.xx7)
ok: [10.x.x.xx8] => (item=10.x.x.xx8)
TASK [mysql_ms : copy db replicatset files] **************************************************************************************************************************************************************
changed: [10.x.x.xx8] => (item=replicaset_configure.js)
ok: [10.x.x.xx7] => (item=replicaset_configure.js)
changed: [10.x.x.xx8] => (item=replicaset_sleep.sql)
ok: [10.x.x.xx7] => (item=replicaset_sleep.sql)
changed: [10.x.x.xx8] => (item=replicaset_create.js)
ok: [10.x.x.xx7] => (item=replicaset_create.js)
ok: [10.x.x.xx7] => (item=replicaset_addinstance.js)
ok: [10.x.x.xx7] => (item=auto_mysqlroute_pass.sh)
changed: [10.x.x.xx8] => (item=replicaset_addinstance.js)
changed: [10.x.x.xx8] => (item=auto_mysqlroute_pass.sh)
TASK [mysql_ms : replicaset configure] *******************************************************************************************************************************************************************
skipping: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : replicaset sleep] ***********************************************************************************************************************************************************************
skipping: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : replicaset create] **********************************************************************************************************************************************************************
skipping: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : replicaset sleep] ***********************************************************************************************************************************************************************
skipping: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : replicaset addinstance] *****************************************************************************************************************************************************************
skipping: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : download installation mysql router media] ***********************************************************************************************************************************************
ok: [10.x.x.xx8]
ok: [10.x.x.xx7]
TASK [mysql_ms : download installation mysql router media] ***********************************************************************************************************************************************
ok: [10.x.x.xx8]
ok: [10.x.x.xx7]
TASK [mysql_ms : install mysql router rpm on all node] **************************************************************************************************************************************************
changed: [10.x.x.xx8] => (item=[u'/tmp/mysql-router-community-8.4.0-1.el7.x86_64.rpm'])
changed: [10.x.x.xx7] => (item=[u'/tmp/mysql-router-community-8.4.0-1.el7.x86_64.rpm'])
TASK [mysql_ms : mysqlrouter add replicaset] *************************************************************************************************************************************************************
changed: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : ensure mysqlrouter is enabled] **********************************************************************************************************************************************************
changed: [10.x.x.xx8]
changed: [10.x.x.xx7]
TASK [mysql_ms : start mysqlrouter] **********************************************************************************************************************************************************************
changed: [10.x.x.xx7]
changed: [10.x.x.xx8]
PLAY RECAP ***********************************************************************************************************************************************************************************************
10.x.x.xx7 : ok=32 changed=20 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.x.x.xx8 : ok=26 changed=16 unreachable=0 failed=0 skipped=5 rescued=0 ignored=0
【查看状态】
MySQL localhost JS > var rs=dba.getReplicaSet();
You are connected to a member of replicaset 'replicaset'.
MySQL localhost JS >
MySQL localhost JS > rs.status()
{
"replicaSet": {
"name": "replicaset",
"primary": "xxx01:3306",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"rac01:3306": {
"address": "xxx01:3306",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
},
"rac02:3306": {
"address": "xxx02:3306",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Waiting for an event from Coordinator",
"applierWorkerThreads": 6,
"receiverStatus": "ON",
"receiverThreadState": "Waiting for source to send event",
"replicationLag": null,
"replicationSsl": "TLS_AES_128_GCM_SHA256 TLSv1.3",
"replicationSslMode": "REQUIRED"
},
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
MySQL localhost JS >
【测试同步】
MySQL localhost JS > \sql Switching to SQL mode... Commands end with ; MySQL localhost SQL > create database sbtest; Query OK, 1 row affected (0.0071 sec) MySQL localhost SQL > use sbtest; Default schema set to `sbtest`. Fetching global names, object names from `sbtest` for auto-completion... Press ^C to stop. MySQL localhost sbtest SQL > create table sbtest(id int primary key,v_name varchar(20)); Query OK, 0 rows affected (0.0486 sec) MySQL localhost sbtest SQL > insert into sbtest values(1,'sbtest1'); Query OK, 1 row affected (0.0064 sec) MySQL localhost sbtest SQL > select * from sbtest.sbtest; +----+---------+ | id | v_name | +----+---------+ | 1 | sbtest1 | +----+---------+ 1 row in set (0.0008 sec)
【测试读写分离】
## MySQL Classic protocol - Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447 - Read/Write Split Connections: localhost:6450 写测试 mysql -uroot -pxxxxxx -hx.x.x.xxx -P6447 -e 'select @@hostname,@@port' 读测试 mysql -uroot -pxxxxxx -hx.x.x.xxx -P6446 -e "START TRANSACTION; SELECT @@hostname,@@port; ROLLBACK;" 自动读写分离测试 mysql -uroot -pxxxxxx -hx.x.x.xxx -P6450 -e 'select @@hostname,@@port' mysql -uroot -pxxxxxx -hx.x.x.xxx -P6450 -e "START TRANSACTION; SELECT @@hostname,@@port; ROLLBACK;"
【高可用切换测试】
MySQL localhost JS > var rs =dba.getReplicaSet();
You are connected to a member of replicaset 'replicaset'.
MySQL localhost JS > rs.status()
{
"replicaSet": {
"name": "replicaset",
"primary": "xxx01:3306",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"xxx01:3306": {
"address": "xxx01:3306",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
},
"xxx02:3306": {
"address": "xxx02:3306",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Waiting for an event from Coordinator",
"applierWorkerThreads": 6,
"receiverStatus": "ON",
"receiverThreadState": "Waiting for source to send event",
"replicationLag": null,
"replicationSsl": "TLS_AES_128_GCM_SHA256 TLSv1.3",
"replicationSslMode": "REQUIRED"
},
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
MySQL localhost JS > rs.setPrimaryInstance("xxx02:3306");
xxx02:3306 will be promoted to PRIMARY of 'replicaset'.
The current PRIMARY is xxx01:3306.
* Connecting to replicaset instances
** Connecting to xxx01:3306
** Connecting to xxx02:3306
** Connecting to xxx01:3306
** Connecting to xxx02:3306
* Performing validation checks
** Checking async replication topology...
** Checking transaction state of the instance...
* Synchronizing transaction backlog at xxx02:3306
** Transactions replicated ############################################################ 100%
* Updating metadata
* Acquiring locks in ReplicaSet instances
** Pre-synchronizing SECONDARIES
** Acquiring global lock at PRIMARY
** Acquiring global lock at SECONDARIES
* Updating replication topology
** Changing replication source of xxx01:3306 to xxx02:3306
xxx02:3306 was promoted to PRIMARY.
MySQL localhost JS > rs.status()
{
"replicaSet": {
"name": "replicaset",
"primary": "xxx02:3306",
"status": "AVAILABLE",
"statusText": "All instances available.",
"topology": {
"xxx01:3306": {
"address": "xxx01:3306",
"instanceRole": "SECONDARY",
"mode": "R/O",
"replication": {
"applierStatus": "APPLIED_ALL",
"applierThreadState": "Waiting for an event from Coordinator",
"applierWorkerThreads": 4,
"receiverStatus": "ON",
"receiverThreadState": "Waiting for source to send event",
"replicationLag": null,
"replicationSsl": "TLS_AES_128_GCM_SHA256 TLSv1.3",
"replicationSslMode": "REQUIRED"
},
"status": "ONLINE"
},
"xxx02:3306": {
"address": "xxx02:3306",
"instanceRole": "PRIMARY",
"mode": "R/W",
"status": "ONLINE"
}
},
"type": "ASYNC"
}
}
MySQL localhost JS > 文章转载自Tuang·誌團·纸團,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




