使用Puppet配置MySQL复制
我们将使用Puppet安装MySQL并配置Master/Master复制。
本文是KVM,Katelo和Puppet系列测试环境项目的一部分。
测试环境
我们安装了两个要配置的CentOS 7服务器,如下所示:
db1.hl.local(10.11.1.17)–将配置为MySQL主数据库
db2.hl.local(10.11.1.18)–将配置为MySQL主数据库
SELinux设置为强制模式。
用Puppet配置
Puppet Master 在Katello服务器上运行。
Puppet模块
我们使用puppetlabs-mysql Puppet模块来配置服务器。
请参阅模块文档以获取支持的功能和可用的配置选项。
Katello存储库
MySQL存储库由Katello提供(我们在此处配置了它们)。
配置防火墙
必须确保MySQL服务器可以相互通信。
以下要求适用于两个MySQL主服务器:
firewall { '007 allow MySQL': dport => [3306], source => '10.11.1.0/24', proto => tcp, action => accept, }
这也将允许Apache连接到数据库。
在db1.hl.local上配置MySQL Master
此处确实没有什么突破性的内容,但请注意自动递增偏移量。
这有助于防止以下情况:两个查询同时在两个服务器db1和db2的同一数据库和同一表中插入数据,并且不同的条目以相同的id结 tail。
class { 'mysql::server': package_name => 'mysql-community-server', service_name => 'mysqld', root_password => 'PleaseChangeMe', create_root_my_cnf => true, manage_config_file => true, config_file => '/etc/my.cnf', purge_conf_dir => true, restart => true, override_options => { mysqld => { bind-address => '0.0.0.0', datadir => '/var/lib/mysql', log-error => '/var/log/mysqld.log', pid-file => '/var/run/mysqld/mysqld.pid', wait_timeout => '600', interactive_timeout => '600', server-id => '1', log-bin => 'mysql-bin', relay-log => 'mysql-relay-log', auto-increment-offset => '1', auto-increment-increment => '2', }, mysqld_safe => { log-error => '/var/log/mysqld.log', }, }, remove_default_accounts => true, }-> ## MySQL admin user who can connect remotely mysql_user { 'Hyman@theitroad%': ensure => 'present', password_hash => mysql_password('PleaseChangeMe'), }-> mysql_grant { 'Hyman@theitroad%/*.*': ensure => 'present', options => ['GRANT'], privileges => ['ALL'], table => '*.*', user => 'Hyman@theitroad%', }-> ## MySQL user for replication mysql_user { 'Hyman@theitroad%': ensure => 'present', password_hash => mysql_password('PleaseChangeMe'), }-> mysql_grant { 'Hyman@theitroad%/*.*': ensure => 'present', privileges => ['REPLICATION SLAVE'], table => '*.*', user => 'Hyman@theitroad%', }
在db2.hl.local上配置MySQL Master
第二台服务器的配置几乎与第一台服务器相同,但有两个例外:server-id和auto-increment-offset。
class { 'mysql::server': package_name => 'mysql-community-server', service_name => 'mysqld', root_password => 'PleaseChangeMe', create_root_my_cnf => true, manage_config_file => true, config_file => '/etc/my.cnf', purge_conf_dir => true, restart => true, override_options => { mysqld => { bind-address => '0.0.0.0', datadir => '/var/lib/mysql', log-error => '/var/log/mysqld.log', pid-file => '/var/run/mysqld/mysqld.pid', wait_timeout => '600', interactive_timeout => '600', server-id => '2', log-bin => 'mysql-bin', relay-log => 'mysql-relay-log', auto-increment-offset => '2', auto-increment-increment => '2', }, mysqld_safe => { log-error => '/var/log/mysqld.log', }, }, remove_default_accounts => true, }-> ## MySQL admin user who can connect remotely mysql_user { 'Hyman@theitroad%': ensure => 'present', password_hash => mysql_password('PleaseChangeMe'), }-> mysql_grant { 'Hyman@theitroad%/*.*': ensure => 'present', options => ['GRANT'], privileges => ['ALL'], table => '*.*', user => 'Hyman@theitroad%', }-> ## MySQL user for replication mysql_user { 'Hyman@theitroad%': ensure => 'present', password_hash => mysql_password('PleaseChangeMe'), }-> mysql_grant { 'Hyman@theitroad%/*.*': ensure => 'present', privileges => ['REPLICATION SLAVE'], table => '*.*', user => 'Hyman@theitroad%', }
配置主/主复制
简单的部分已经完成,我们应该在此阶段配置我们的MySQL节点。
我们还没有创建任何数据库,因此,目前我们没有太多要在两个服务器之间同步的信息。
让我们继续并将手动配置MySQL复制所需的步骤放入Bash脚本'start_mysql_repl.sh'中。
请注意,该脚本是使MySQL复制正常工作的一种快速而肮脏的方法,但这不是正确的方法。
理想情况下,我们应该使用带有参数的Puppet模板,以便我们可以通过将参数哈希传递给函数来为其提供值,而不必对主机名,用户名等进行硬编码。
#!/bin/bash ## Author: igi at www.theitroad.com # Configure MySQL Replication with Puppet ## Variables below must match with the ones # defined in the Puppet manifest #master1_host="db1.hl.local"; master2_host="db2.hl.local"; repl_user="dbrepl"; repl_pass="PleaseChangeMe"; db_user="dbadmin"; db_pass="PleaseChangeMe"; master1_status="/tmp/master1.status"; master2_status="/tmp/master2.status"; if ! [ -f "/root/.replication1.done" ];then mysql -h"$master1_host" -u"$db_user" -p"$db_pass" -ANe "SHOW MASTER STATUS;"|awk '{print " " }' >"$master1_status" && \ log_file=$(cut -d" " -f1 "$master1_status") && \ log_pos=$(cut -d" " -f2 "$master1_status") && \ mysql -h"$master2_host" -u"$db_user" -p"$db_pass" < <-EOSQL & STOP SLAVE; CHANGE MASTER TO MASTER_HOST='$master1_host', \ MASTER_USER='$repl_user', MASTER_PASSWORD='$repl_pass', \ MASTER_LOG_FILE='$log_file', MASTER_LOG_POS=$log_pos; START SLAVE; EOSQL sleep 5; rm -f "$master1_status"; master2_status=$(mysql -h"$master2_host" -u"$db_user" -p"$db_pass" -e "SHOW SLAVE STATUS\G;"|grep -c "Waiting for master"); if [ "$master2_status" -eq "1" ];then touch /root/.replication1.done; echo "OK - master2 was configured as a slave for master1"; else echo "ERROR - failed to configure master2 as a slave for master1"; exit 1; fi else echo "Note - master2 is already configured as a slave for master1"; fi if ! [ -f "/root/.replication2.done" ];then mysql -h"$master2_host" -u"$db_user" -p"$db_pass" -ANe "SHOW MASTER STATUS;"|awk '{print " " }' >"$master2_status" && \ log_file=$(cut -d" " -f1 "$master2_status") && \ log_pos=$(cut -d" " -f2 "$master2_status") && \ mysql -h"$master1_host" -u"$db_user" -p"$db_pass" < <-EOSQL & STOP SLAVE; CHANGE MASTER TO MASTER_HOST='$master2_host', \ MASTER_USER='$repl_user', MASTER_PASSWORD='$repl_pass', \ MASTER_LOG_FILE='$log_file', MASTER_LOG_POS=$log_pos; START SLAVE; EOSQL sleep 5; rm -f "$master2_status"; master1_status=$(mysql -h"$master1_host" -u"$db_user" -p"$db_pass" -e "SHOW SLAVE STATUS\G;"|grep -c "Waiting for master"); if [ "$master1_status" -eq "1" ];then touch /root/.replication2.done; echo "OK - master1 was configured as a slave for master2"; else echo "ERROR - failed to configure master1 as a slave for master2"; exit 1; fi else echo "Note - master1 is already configured as a slave for master2"; fi
注意:EOSQL前面的'<''<'之间没有空格。
WordPress有时会通过格式化来做有趣的事情。
该脚本将主控主机db1.hl.local配置为主控主机db2.hl.local的从属服务器。
该脚本还将主机db2.hl.local配置为主机db1.hl.local的从机。
将以下Puppet配置应用于服务器db1.hl.local(不得将其应用于第二台服务器)。
请注意我们如何部署脚本,配置复制然后创建数据库。
该数据库的名称为“教程 ”,主要是因为我们将其用于WordPress。
file { '/root/start_mysql_repl.sh': ensure => 'file', source => 'puppet:///homelab_files/start_mysql_repl.sh', owner => '0', group => '0', mode => '0700', notify => Exec['configure_replication'], } exec { 'configure_replication': command => '/root/start_mysql_repl.sh', path => '/usr/bin:/usr/sbin:/bin:/sbin', provider => shell, unless => ['test -f /root/.replication1.done', 'test -f /root/.replication2.done'], notify => Exec['create_database'], } ## We want to create the database after ## the replication has been established exec { 'create_database': command => 'mysql --defaults-file=/root/.my.cnf -e "DROP DATABASE IF EXISTS blog; CREATE DATABASE blog; GRANT ALL PRIVILEGES ON blog.* TO \'dbuser1\'@\'10.11.1.%\' IDENTIFIED BY \'PleaseChangeMe\'; FLUSH PRIVILEGES;"', path => '/usr/bin:/usr/sbin:/bin:/sbin', provider => shell, refreshonly => true, notify => Exec['import_database'], } ## We want to import the database from a dump file exec { 'import_database': command => 'mysql --defaults-file=/root/.my.cnf blog < blog.sql', path => '/usr/bin:/usr/sbin:/bin:/sbin', provider => shell, onlyif => ['test -f /root/blog.sql'], refreshonly => true, } file { '/root/blog.sql': ensure => file, source => 'puppet:///homelab_files/blog.sql', owner => '0', group => '0', mode => '0600', }
数据库导入部分将还原我们的WordPress数据库的内容。
由于导入是在建立复制后执行的,因此该数据库在两个MySQL主数据库上均可用。