覚書。
初めてAnsibleを触ってて少し躓いたところがあったので。
環境
・Ansible 2.3.0
・Percona server 5.7 (MySQL 5.7_
my.cnfを配置
Master用とSlave用のmy.cnfをリモート先へ送る。
- name: Copy my.cnf to master
copy: src="roles/dbtier/files/my.cnf.master" dest="/etc/percona-server.conf.d/mysqld.cnf" owner=root group=root mode=0644
when: hostname.stdout.find('db-master') == 0
- name: Copy my.cnf to slave
copy: src="roles/dbtier/files/my.cnf.slave" dest="/etc/percona-server.conf.d/mysqld.cnf" owner=root group=root mode=0644
when: hostname.stdout.find('db-slave') == 0
rootパスワードを取得
MySQL 5.7から/var/log/mysqld.logにパスワードが記載されているので
これを使って初期設定を行うらしい。
- name: Get percona server password
shell: cat /var/log/mysqld.log | grep "temporary password" | awk '{print $11}'
register: mysql_temp_pass
.my.cnfを/rootに設置
Ansibleのmysqlモジュールを使うために/root/.my.cnfにファイルを設置
- name: Copy .my.cnf file template: src=temp_my.cnf.j2 dest=/root/.my.cnf owner=root group=root mode=0644
temp_my.cnf.j2
connect-expired-passwordが地味に大事
[client]
user=root
password={{ mysql_temp_pass.stdout }}
connect-expired-password
rootパスワードを設定する
一時的なパスワードでは覚えられないので変更します。
パスワードの要件が厳しくなって大文字小文字記号数字で8桁以上とかだった気がする(覚えてない)
- name: Set root password
mysql_user: name=root host=localhost password="{{ mysql_root_pass }}"
ignore_errors: True
新しい.my.cnfを/rootに設置
- name: Override .my.cnf file template: src=new_my.cnf.j2 dest=/root/.my.cnf owner=root group=root mode=0644
new_my.cnf.j2
connect-expired-passwordを削除したバージョン
[client]
user=root
password={{ mysql_root_pass }}
anonymousユーザーを削除
- name: Remove all anonymous user mysql_user: name='' host=localhost state=absent
レプリケーションユーザーを作成
- name: Semi-synchronous - Create replication user
mysql_user: >
name="{{ mysql_rep_user }}"
password="{{ mysql_rep_pass }}"
priv="{{ mysql_rep_priv }}"
host="{{ mysql_rep_host }}"
when: hostname.stdout.find('db-master') == 0
FlushコマンドってAnsibleじゃ使えないよね…?
- name: Semi-synchronous - Flush
shell: mysql --defaults-file=/root/.my.cnf -e "FLUSH PRIVILEGES";
shell: mysql --defaults-file=/root/.my.cnf -e "FLUSH TABLES WITH READ LOCK";
when: hostname.stdout.find('db-master') == 0
マスターDBからダンプして、スレーブにインポート
- name: Semi-synchronous - Dump all database
mysql_db: state=dump name=all target=/root/all_db_dump.sql
when: hostname.stdout.find('db-master') == 0
- name: Semi-synchronous - Send all_db_dump.sql
shell: sshpass -p '' scp -o StrictHostKeyChecking=no all_db_dump.sql root@db-slave.local:~/
when: hostname.stdout.find('db-master') == 0
- name: Semi-synchronous - Stop slave if running
mysql_replication: mode=stopslave
when: hostname.stdout.find('db-slave') == 0
- name: Semi-synchronous - Import all_db_dump.sql
shell: mysql --defaults-file=/root/.my.cnf < /root/all_db_dump.sql
when: hostname.stdout.find('db-slave') == 0
マスターのファイル名とポジションの取得
ここが一番詰まった。
Ansibleは異なるホスト間で変数の参照ができないので
ファイル名とポジションの取得はスレーブのときに実行して、実際に実行するコマンドはマスター側で処理をする。
- name: Semi-synchronous - Get the master status
mysql_replication: mode=getmaster
delegate_to: "{{ mysql_master }}"
register: binlog
when: hostname.stdout.find('db-slave') == 0
Change master
- name: Semi-synchronous - Change the master
mysql_replication: >
mode=changemaster
master_host="{{ mysql_master }}"
master_user="{{ mysql_rep_user }}"
master_password="{{ mysql_rep_pass }}"
master_log_file={{ binlog.File }}
master_log_pos={{ binlog.Position }}
when: hostname.stdout.find('db-slave') == 0
スレーブの開始
- name: Semi-synchronous - Start slave
mysql_replication: mode=startslave
when: hostname.stdout.find('db-slave') == 0
スレーブの状況確認
Slave_IO_Running と Slave_SQL_RunningがどっちもYesであることを確認
- name: Semi-synchronous - Get Slave_IO_Running
shell: mysql --defaults-file=/root/.my.cnf -e "SHOW SLAVE STATUS\G" | grep "Slave_IO_Running" | awk '{print $2}'
register: SIOR
failed_when: SIOR.stdout not in ["Yes"]
when: hostname.stdout.find('db-slave') == 0
- name: Semi-synchronous - Get Slave_SQL_Running
shell: mysql --defaults-file=/root/.my.cnf -e "SHOW SLAVE STATUS\G" | grep "Slave_SQL_Running:" | awk '{print $2}'
register: SSQLR
failed_when: SSQLR.stdout not in ["Yes"]
when: hostname.stdout.find('db-slave') == 0
マスターでロックしていたのを解除
- name: Semi-synchnorous - Unlock tables
shell: mysql --defaults-file=/root/.my.cnf -e "UNLOCK TABLES"
when: hostname.stdout.find('db-master') == 0
- name: Semi-synchronous - Flush privileges
shell: mysql --defaults-file=/root/.my.cnf -e "FLUSH PRIVILEGES"
when: hostname.stdout.find('db-master') == 0