[![logo](https://www.hongsnet.net/images/logo.gif)](https://www.hongsnet.net)

# Ansible을 이용한 MHA Manager 구성 및 설치

> 복잡한 MHA Manager 구성 및 설치를 자동화 한다.


## Inventory 설정

```bash
# cat hosts
[ALL_HOSTS]
172.16.0.100 managed_ip=172.16.0.100 des="2020-12-03" roles="manager"
172.16.0.200 managed_ip=172.16.0.100 des="2020-12-03" roles="node"
172.16.0.201 managed_ip=172.16.0.100 des="2020-12-03" roles="node"
172.16.0.202 managed_ip=172.16.0.100 des="2020-12-03" roles="node"

[ALL_HOSTS_OK]
```

대상 호스트는 172.16.0.100이며, 추가는 2020-12-03에 수행한다. 참고적으로 **ALL_HOSTS_OK** 호스트 그룹은 작업이 완료된 호스트의 history를 위한 그룹이다.


## Host Variables 설정

```bash
# cat host_vars/172.16.0.100
ansible_ssh_host: 172.16.0.100
ansible_ssh_port: SSH_포트번호
ansible_ssh_user: 사용자 아이디
ansible_ssh_pass: "사용자 패스워드"
ansible_become: yes
ansible_become_method: su
ansible_become_user: root
ansible_become_pass: "!root_패스워드"
ansible_python_interpreter: python2.7
```

172.16.0.100 외의 서버들도 위와 같은 형식으로 작성된다.


## Playbook 설정

- **SSH RSA Key 인증 수행**

```python
---
- name: MHA Pre-Requirement Working
  hosts: ALL_HOSTS
  vars:
    user_name: 'mhauser'
    user_password: '패스워드'
    new_user0: 'AllowUsers mhauser@172.16.0.100'
    new_user1: 'AllowUsers mhauser@172.16.0.200'
    new_user2: 'AllowUsers mhauser@172.16.0.201'
    new_user3: 'AllowUsers mhauser@172.16.0.202'
  tasks:
   - name: mysql Group Add
     group:
       name: mysql
       state: present

   - name: MHA User Add
     user:
        name: "mhauser"
        password: "{{ user_password | password_hash('sha512') }}"
        shell: /bin/bash
        home: /MHA

   - name: User Add mysql Group
     shell: usermod -G mysql {{ user_name }}

   - name: MHA Manager Requirement Direcotry Check
     stat:
       path: "{{ item }}"
     with_items:
       ['/MHA/conf', '/MHA/script', '/MHA/log' ]
     register: mha_manager_directory_check

   - name: MHA Manager Requirement Directorys Making
     command: "{{ item }}"
     with_items:
        - mkdir -p /MHA/conf
        - mkdir -p /MHA/script
        - mkdir -p /MHA/log
        - chown -R mhauser.mysql /MHA
     when: mha_manager_directory_check == False

   - name: /etc/ssh/sshd_config AllowUsers Adding
     lineinfile:
        path: /etc/ssh/sshd_config
        line: "{{ item }}"
        insertafter: EOF
     with_items:
       - "{{ new_user0 }}"
       - "{{ new_user1 }}"
       - "{{ new_user2 }}"
       - "{{ new_user3 }}"

   - name: ssh-keygen Local to Remote
     command: "ssh-keygen -b 2048 -t rsa -f /MHA/.ssh/id_rsa.pub -q -N ''"
     run_once: true

   - name: Remote Import id_rsa.pub
     command: "cat /MHA/.ssh/id_rsa.pub"
     register: ssh_rsa_pub
     run_once: true

   - name: Remote SSH Directory Create
     file:
       path: /MHA/.ssh
       state: directory
       mode: '0700'

   - name: Remote SSH authorized_keys file touch
     file:
       path: /MHA/.ssh/authorized_keys
       state: touch
       mode: '0600'

   - name: Remote Node Add authrized keys
     lineinfile:
       dest: /MHA/.ssh/authorized_keys
       line: "{{ ssh_rsa_pub.stdout }}"
```

- **MHA Manager 구성**

```python
---
- name: MHA Manager and Node Installer(Debian Based)
  hosts: ALL_HOSTS
  vars:
    time: "{{lookup('pipe','date \"+%Y%m%d_%H%M\"')}}"
    repl_user: 'Replication_유저'
    repl_password: 'Replication_패스워드'
    mha_vip: '172.16.0.254'
    mha_vip_netmask: '255.255.255.0'
    mha_vip_broadcast: '172.16.0.255'
    ssh_port: SSH_포트번호
    dbms_master01: '172.16.0.100'
    dbms_master02: '172.16.0.200'
    dbms_slave01: '172.16.0.201'
    dbms_slave02: '172.16.0.202'
  environment:
    LANG: ko_KR.UTF-8
  tasks:
   - name: MHA Manager and Node file Check
     stat:
       path: "{{ item }}"
     with_items:
       ['/root/mha/mha4mysql-manager-0.57.tar.gz', '/root/mha/mha4mysql-node-0.57.tar.gz']
     register: mha_manager_file_check

   - name: MHA Manager and Node tar file Upload
     copy:
       src: "{{ item }}"
       dest: /root/mha
       owner: 'root'
       group: 'root'
       mode: 0644
     with_items:
       ['templates/mha4mysql-manager-0.57.tar.gz', 'templates/mha4mysql-node-0.57.tar.gz']
     when: mha_manager_file_check == False

   - name: Install a list of packages
     apt:
       pkg:
         - sudo
         - libmodule-install-perl
         - libdbd-mysql-perl
         - libconfig-tiny-perl
         - liblog-dispatch-perl
         - libparallel-forkmanager-perl
         - arping
       update_cache: yes

   - name: MHA Node untar Directory Check
     stat:
       path: /root/mha/mha4mysql-node-0.57
     register: mha_node_untar_check

   - name: MHA Node File Unarchive
     unarchive:
        src: "/root/mha/mha4mysql-node-0.57.tar.gz"
        dest: "/root/mha/"
        remote_src: yes
     when: mha_node_untar_check == False

   - name: MHA Manager untar Directory Check
     stat:
       path: /root/mha/mha4mysql-manager-0.57
     register: mha_manager_untar_check

   - name: MHA Manager File Unarchive
     unarchive:
        src: "/root/mha/mha4mysql-manager-0.57.tar.gz"
        dest: "/root/mha/"
        remote_src: yes
     when: mha_manager_untar_check == False

   - name: MHA Node compile binary Check
     stat:
       path: /usr/local/bin/apply_diff_relay_logs
     register: mha_node_binary_check

   - name: Compiling MHA Node
     shell: "{{ item }}"
     args:
       chdir: "/root/mha/mha4mysql-node-0.57"
     with_items:
        - perl Makefile.PL
        - make
        - make install
     when: mha_node_binary_check == False

   - name: MHA Manager compile binary Check
     stat:
       path: /usr/local/bin/masterha_check_ssh
     register: mha_manager_binary_check

   - name: Compiling MHA Manager
     shell: "{{ item }}"
     args:
       chdir: "/root/mha/mha4mysql-manager-0.57"
     with_items:
        - perl Makefile.PL
        - make
        - make install
     when: mha_manager_binary_check == False

   - name: MHA Manager and Node file Remove
     file:
       path: "{{ item }}"
       state: absent
     with_items:
       - /root/mha/mha4mysql-manager-0.57.tar.gz
       - /root/mha/mha4mysql-manager-0.57
       - /root/mha/mha4mysql-node-0.57.tar.gz
       - /root/mha/mha4mysql-node-0.57

   - name: MHA mha.cnf configuration Copy
     template: src=templates/mha.cnf.j2 dest=/MHA/conf/mha.cnf mode=0644

   - name: MHA FailOver Script Copy
     template: src=templates/master_ip_failover.j2 dest=/usr/local/bin/master_ip_failover mode=0755

   - name: MHA IP Online Change Script Copy
     template: src=templates/master_ip_online_change.j2 dest=/usr/local/bin/master_ip_online_change mode=0755

```

위의 **master_ip_failover** 및 **master_ip_online_change** 스크립트에 대한 핵심적인 내역은 다음과 같다.

```bash
my $vip = '{{ mha_vip }}';
my $netmask = '{{ mha_vip_netmask }}';
my $broadcast = '{{ mha_vip_broadcast }}';
...중략
ssh -p {{ ssh_port }} $ssh_user\@$orig_master_host \" $ssh_start_vip \"`;
```

`MHA Manager 설치`에 대한 Playbook 분석

* [ ] MHA 설치 패키지의 업로드를 수행한다. 단, 파일이 존재할 경우는 Skip 한다.
* [ ] MHA의 복잡한 작업인 SSH RSA 키기반 인증을 먼저 수행한 후 Manager 설치를 진행해야 한다.
* [ ] MHA Manager의 설정 시 서비스 IP주소 등을 직접 수정하지않고, Jinja2 템플릿을 사용하여 배포한다.


## playbook 실행

```bash
# ansible-playbook -i hosts mha_manager_install.yml
```