覚書。
初めてAnsibleを触ってて少し躓いたところがあったので。
TOC
環境
・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 [email protected]:~/ 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