現在位置: ホーム / OSSブログ / [Backnumber] OSSよろず研究室 第1回:Ansibleのマスターサーバが壊れた時のアレコレ

[Backnumber] OSSよろず研究室 第1回:Ansibleのマスターサーバが壊れた時のアレコレ

OSSよろず相談室にご契約頂いておりますお客様限定で公開している「OSSよろず契約者 Ch. 」のコンテンツよりバックナンバーを公開します。

こんにちは。SIOS OSSエバンジェリスト/セキュリティ担当の面です。

こちらの「OSSよろず研究室」では、OSSよろず相談室に関わるエンジニアの、興味がある技術分野について「実際に試してみた」事を中心にご紹介させて頂きます。

第一回は「Ansibleのマスターサーバが壊れた時のアレコレ」です。

Ansibleについて

Ansibleに関しては、既にあちこちの技術情報サイトや雑誌などで取り上げられていますので、皆様御存じだと思います。

弊社のサイトでも、Azure上での展開などについての記事が執筆されています。

Ansibleは

  • デプロイメントツール

  • オーケストレーションツール

  • 構成管理ツール

の3つの役割が統合されたツールになっています。

特に、構成管理ツールとしての側面では、ChefやPuppetに比べて

  • エージェントレス(ssh/Pythonを使用)

  • PlaybookというYAMLを用いたファイルにタスクを記載(直感的)

  • モジュールによる拡張性の高さ

が挙げられます。

調べてみること

Ansibleに関しては色々な記事で取り上げられていますが、ここでは現実の運用を考えて

  1. Ansible環境をバックアップからリストアして正常に動くのか

  2. Ansible環境で構成を変更している際に通信断が発生した場合にはどうなるのか

を実際に確認してみたいと思います。それぞれですが、

  1. 過去にエージェントを利用した構成管理ツールを利用していた時に、バックアップからリストアして酷い目にあった(管理サーバが2台いる事になってしまった)ので気になった

  2. エージェントレスの場合、通信が常に確立されている状態での構成管理を行っていると、現実に通信断が発生した際にエラー処理が正しく行えるのか気になった

というのが、今回調査してみたかった理由になります。

検証環境

下記が今回の検証環境になります。検証にはVMWare環境を使用しています。

  • Ansible管理サーバ(Cent7)

    • OS: CentOS 7

    • IP: 172.16.148.130

    • MAC: 00:0c:29:43:a6:0d

    • Ansible User: sios

  • Ansible管理クライアント(Cent7Agent)

  • OS: CentOS 7

  • IP: 172.16.148.131

  • MAC: 00:0c:29:45:4c:dc

検証環境構築

下記が今回の検証環境になります。検証にはVMWare環境を使用しています。

  1. yumを用いて、epel-release, python-devel, sshpassをインストールします。

    yum -y install epel-release python-devel sshpass
    
  2. yumを用いて、epel-testingからansibleをインストールします。

    yum --enablerepo=epel-testing install ansible
    
  3. インベントリファイルを作成します。今回は、管理端末(Cent7agent:172.16.148.131)に対して"sios"というユーザでログインし、sudoを使ってroot権限を持った操作を行います。以下のようなファイルを作成します。

    172.16.148.131	ansible_user=sios	ansible_ssh_pass=sios123	ansible_become_pass=sios123
    
  4. known_hostsに管理端末を登録するために、管理端末にsshで普通にログインしてみます。ログイン後、exitします。

    [sios@cent7 playbooks]$ ssh -l sios 172.16.148.131
    The authenticity of host '172.16.148.131 (172.16.148.131)' can't be established.
    ECDSA key fingerprint is XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '172.16.148.131' (ECDSA) to the list of known hosts.
    sios@172.16.148.131's password: 
    Last login: Sun Jul 24 17:20:57 2016 from cent7.localdomain
    [sios@cent7agent ~]$ exit
    
  5. テストとしてpingを打ってみます。

    [sios@cent7 playbooks]$ ansible -i ansible_hosts all -m ping
    172.16.148.131 | SUCCESS => {
        "changed": false, 
        "ping": "pong"
    }
    
  6. テストとしてplaybook(ntp.yml)を作成します。ntpdをインストールし、ローカルにある設定ファイル(ntp.conf.sios)を/etc/ntp.confとして配布するものになります。

    [sios@cent7 playbooks]$ more ntp.yml 
    - hosts: all
      become: yes
      become_user: root
      tasks:
    
        - name: be sure ntp is installed
          yum: name=ntp state=installed
          tags: ntp
    
        - name: be sure ntp is configured
          template: src=ntp.conf.sios dest=/etc/ntp.conf
          notify:
            - restart ntpd
          tags: ntp
    
        - name: be sure ntpd is running and enabled
          service: name=ntpd state=started enabled=yes
          tags: ntp
    
    [sios@cent7 playbooks]$ more ntp.conf.sios 
    server ntp1.jst.mfeed.ad.jp
    server ntp2.jst.mfeed.ad.jp
    server ntp3.jst.mfeed.ad.jp
    
    driftfile /var/log/ntp.drift
    
    broadcastdelay	0.008
    
    authenticate no
    
  7. playbookがきちんと動くか確認します。

    [sios@cent7 playbooks]$ ansible-playbook -i ~/ansible_hosts ntp.yml 
    
    PLAY [all] *********************************************************************
    
    TASK [setup] *******************************************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntp is installed] ************************************************
    changed: [172.16.148.131]
    
    TASK [be sure ntp is configured] ***********************************************
    changed: [172.16.148.131]
    
    TASK [be sure ntpd is running and enabled] *************************************
    changed: [172.16.148.131]
    
    PLAY RECAP *********************************************************************
    172.16.148.131             : ok=4    changed=3    unreachable=0    failed=0   
    
  8. 管理端末にsshでログインし、ntpdが動作していることと/etc/ntp.confが設定したとおりになっていることを確認します。

    [root@cent7agent ~]# ps ax|grep ntp
      4981 ?        Ss     0:00 /usr/sbin/ntpd -u ntp:ntp -g
      4997 pts/0    S+     0:00 grep --color=auto ntp
    [root@cent7agent ~]# cat /etc/ntp.conf
    server ntp1.jst.mfeed.ad.jp
    server ntp2.jst.mfeed.ad.jp
    server ntp3.jst.mfeed.ad.jp
    
    driftfile /var/log/ntp.drift
    
    broadcastdelay	0.008
    
    authenticate no
    [root@cent7agent ~]# 
    

Ansible環境のバックアップとリストア

バックアップ対象は、ansible関連の設定ファイルと、管理サーバで作業するエンジニアの設定ファイルになりますので

- /etc/ansible以下
- /home/sios/.ssh以下(known_hostsが入っているため)
- /home/sios/ansible_test(ansible_hostsファイルや、playbookなどを入れたディレクトリ)

をtarで取得しておきます。

Ansible管理サーバのバックアップとリストア

1.リストア先のIPアドレスが元のIPアドレス(172.16.148.130)と同じ場合

  1. ホスト名・IPアドレスも全く同じにしておき、管理ユーザ(sios)も作成しておきます。MACアドレスだけが異なります。

    [sios@cent7 ~]$ ip addr
    1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eno16777736:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:89:59:57 brd ff:ff:ff:ff:ff:ff
        inet 172.16.148.130/24 brd 172.16.148.255 scope global eno16777736
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:fe89:5957/64 scope link 
           valid_lft forever preferred_lft forever
    [sios@cent7 ~]$ 
    
  2. backupファイルからリストアします。

    [root@cent7 /]# tar -xvzf /root/ansible_backup.tar.gz
    etc/ansible/
    etc/ansible/ansible.cfg
    etc/ansible/roles/
    etc/ansible/hosts
    home/sios/.ssh/
    home/sios/.ssh/known_hosts
    home/sios/ansible_test/
    home/sios/ansible_test/playbooks/
    home/sios/ansible_test/playbooks/ansible_hosts
    home/sios/ansible_test/playbooks/ntp.yml
    home/sios/ansible_test/playbooks/ntp.conf.sios
    [root@cent7 /]# 
    
  3. playbookがきちんと動くか確認します。

    [sios@cent7 playbooks]$ ansible-playbook -i ansible_hosts ntp.yml
    
    PLAY [all] *********************************************************************
    
    TASK [setup] *******************************************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntp is installed] ************************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntp is configured] ***********************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntpd is running and enabled] *************************************
    ok: [172.16.148.131]
    
    PLAY RECAP *********************************************************************
    172.16.148.131             : ok=4    changed=0    unreachable=0    failed=0
    

    となり、きちんと動作することがわかります。

2.リストア先のIPアドレスが元のIPアドレス(172.16.148.130)と異なる場合

  1. ホスト名なども全く同じにしておき、IPアドレスだけ異なる設定(172.16.148.130)にしておきます。管理ユーザ(sios)も作成しておきます。

    [sios@cent7 ~]$ ip addr
    1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eno16777736:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:89:59:57 brd ff:ff:ff:ff:ff:ff
        inet 172.16.148.140/24 brd 172.16.148.255 scope global eno16777736
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:fe89:5957/64 scope link 
           valid_lft forever preferred_lft forever
    [sios@cent7 ~]$ 
    
  2. backupファイルからリストアします。

    [root@cent7 /]# tar -xvzf /root/ansible_backup.tar.gz
    etc/ansible/
    etc/ansible/ansible.cfg
    etc/ansible/roles/
    etc/ansible/hosts
    home/sios/.ssh/
    home/sios/.ssh/known_hosts
    home/sios/ansible_test/
    home/sios/ansible_test/playbooks/
    home/sios/ansible_test/playbooks/ansible_hosts
    home/sios/ansible_test/playbooks/ntp.yml
    home/sios/ansible_test/playbooks/ntp.conf.sios
    [root@cent7 /]# 
    
  3. playbookがきちんと動くか確認します。

    [sios@cent7 playbooks]$ ansible-playbook -i ansible_hosts ntp.yml
    
    PLAY [all] *********************************************************************
    
    TASK [setup] *******************************************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntp is installed] ************************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntp is configured] ***********************************************
    ok: [172.16.148.131]
    
    TASK [be sure ntpd is running and enabled] *************************************
    ok: [172.16.148.131]
    
    PLAY RECAP *********************************************************************
    

    となり、リストアする管理サーバのIPアドレスが異なる場合でも、リストアしたansibleはきちんと動作することがわかります。

Ansible管理対象端末のバックアップとリストア

1.リストア先のIPアドレスが元のIPアドレス(172.16.148.131)と同じ場合

  1. ホスト名、IPアドレスなども全く同じにした管理対象端末をインストールしておきます。リモートログインで使用するユーザ(sios)も作成しておきます。

    [sios@cent7agent ~]$ ip addr
    1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eno16777736:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
        link/ether 00:0c:29:b7:a0:8f brd ff:ff:ff:ff:ff:ff
        inet 172.16.148.131/24 brd 172.16.148.255 scope global eno16777736
           valid_lft forever preferred_lft forever
        inet6 fe80::20c:29ff:feb7:a08f/64 scope link 
           valid_lft forever preferred_lft forever
    
  2. 管理サーバからplaybookを実行すると、下記のようにエラーになります。これは、管理サーバの.ssh/known_hostsに登録されているキーが、新たに入れた管理対象端末のものと異なるためです。

    [sios@cent7 ~]$ ansible-playbook -i ~/ansible_hosts ntp.yml 
    
    PLAY [all] *********************************************************************
    
    TASK [setup] *******************************************************************
    fatal: [172.16.148.131]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh.", "unreachable": true}
    	to retry, use: --limit @main.retry
    
    PLAY RECAP *********************************************************************
    172.16.148.131             : ok=0    changed=0    unreachable=1    failed=0   
    
  3. この状態を修正するには、.ssh/known_hostsの該当のキーを削除して再度sshでログインし直します。

    [sios@cent7 ~]$ more ~/.ssh/known_hosts 
    127.0.0.1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA
    BBBLiHOQXG241wLeX+w8EwU65Pt/QVf5axbtl+qEr3L2DDluUUUmiz4BR3yXrIfNWG0OVN5py90wX92k
    2kpmzdVes=
    172.16.148.131 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyN
    TYAAABBBLiHOQXG241wLeX+w8EwU65Pt/QVf5axbtl+qEr3L2DDluUUUmiz4BR3yXrIfNWG0OVN5py90
    wX92k2kpmzdVes=    <---- ここを削除して、再度sshで管理対象端末にログインして登録し直す。
    

Ansibleでの管理中に通信障害が発生した際の挙動を調べる

この環境で、通信障害が発生した際にAnsibleがどうなるかを確認してみます。

1. Ansible管理対象端末にファイルを送っている最中にネットワークが切れた場合

Ansible管理対象端末にファイルをコピーしている最中にネットワークが切れた場合、エージェントと管理サーバがどうなるかを確認してみます。

  1. 簡単なplaybookとして、下記のconnection_test.ymlを作成します。

    [omok@cent7 playbooks]$ cat connection_test.yml 
    - hosts: all
      become: yes
      become_user: root
      tasks:
    
        - copy: src=/home/omok/ansible_test/playbooks/CentOS-7-x86_64-Minimal-1511.iso dest=/var/tmp
    
    

    コピーするファイルとして、テストを簡単にするために、大きなファイル(テストではCentOS7のMinimalファイル:約600MB)を使用しています。

  2. それでは、実際にplaybookを実行してみます。

    [sios@cent7 playbooks]$ ansible-playbook -i ~/ansible_hosts connection_test.yml 
     
    PLAY [all] *********************************************************************
    
    TASK [setup] *******************************************************************
    ok: [172.16.148.131]
    
    TASK [copy] ********************************************************************
    
  3. [copy]が出力された所でネットワークを切り離します。出力は下記で止まっています

    TASK [copy] ********************************************************************
    
  4. この時、管理対象端末の方はどうなっているのかを確認します。リモート(管理対象端末上)のユーザ(ここではsios)の/home/sios/.ansible/tmp以下に一時ディレクトリが出来ており、一時ファイルが生成されているが止まっている状態になっているのがわかります。

    [sios@cent7agent ~]$ cd .ansible/
    [sios@cent7agent .ansible]$ ls
    tmp
    [sios@cent7agent .ansible]$ cd tmp
    [sios@cent7agent tmp]$ ls -lha
    合計 0
    drwx------. 3 sios sios 54  7月 24 22:20 .
    drwx------. 3 sios sios 16  7月 24 20:20 ..
    drwx------. 2 sios sios 19  7月 24 22:20 ansible-tmp-1469359616.58-239744997515517
    [sios@cent7agent tmp]$ cd ansible-tmp-1469359616.58-239744997515517/
    [sios@cent7agent ansible-tmp-1469359616.58-239744997515517]$ ls
    source
    [sios@cent7agent ansible-tmp-1469359616.58-239744997515517]$ ls -lha
    合計 68M
    drwx------. 2 sios sios  19  7月 24 22:20 .
    drwx------. 3 sios sios  54  7月 24 22:20 ..
    -rw-r--r--. 1 sios sios 68M  7月 24 22:20 source
    [sios@cent7agent ansible-tmp-1469359616.58-239744997515517]$ file source
    source: # ISO 9660 CD-ROM filesystem data 'CentOS 7 x86_64' (bootable)
    
  5. しばらく(約15分程度)待っていると、sftpの時間制限でタイムアウトが発生し、管理サーバのほうで、ansible playbookの実行エラーが表示されます。

    TASK [copy] ********************************************************************
         
    fatal: [172.16.148.131]: UNREACHABLE! => {"changed": false, "msg": "SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh", "unreachable": true}
    	to retry, use: --limit @connection_test.retry
    
    PLAY RECAP *********************************************************************
    172.16.148.131             : ok=1    changed=0    unreachable=1    failed=0   
    
    [omok@cent7 playbooks]$ 
    

2. Ansible管理対象端末上でPlaybookによる作業を行っている最中にネットワークが切れた場合

Ansible管理対象端末上でPlaybookによる作業を行っている最中にネットワークが切れた場合、エージェントと管理サーバがどうなるかを確認してみます。

  1. 簡単なplaybookとして、下記の内容をファイルtask_hang_test.ymlとして作成します。

    - hosts: all
      become: yes
      become_user: root
      tasks:
    
        - name: Copy 1st file
          copy: src=/home/omok/ansible_test/playbooks/file_1 dest=/var/tmp
    
          template: src=ntp.conf.sios dest=/etc/ntp.conf
          notify:
            - restart ntpd
          tags: ntp
    
        - name: Just wait 30 sec.
          command: sleep 30
    
        - name: Copy 2nd file
          copy: src=/home/omok/ansible_test/playbooks/file_2 dest=/var/tmp
    
  2. playbookを実行します。

    [omok@cent7 playbooks]$ time ansible-playbook -i ./ansible_hosts ./task_hang_test.yml 
    
    PLAY [all] *********************************************************************
    
    TASK [setup] *******************************************************************
    ok: [172.16.148.131]
    
    TASK [Copy 1st file] ***********************************************************
    changed: [172.16.148.131]
    
    
  3. 30秒スリープの間に、管理対象端末のネットワークを切り離します。下記の表示でハングします

    TASK [Just wait 30 sec.] *******************************************************
    
  4. ansible-playbookはsshクライアントのタイムアウトが発生しも、エラーにならず、ハングアップしたままになります。

  5. 管理対象端末を確認すると、ネットワーク切り離し時(ひとつ目のファイルコピー実施後のsleep中)に完了していた作業(file_1のコピー)のみが完了していて、切り離し後の作業は実施されていないことがわかります。

    [omok@cent7agent /var/tmp]$ ls -ltrh
    合計 0
    -rw-rw-r--. 1 omok omok   11  7月 25 07:17 file_1
    

今回の実験のまとめ

今回の実験の結果から、下記のことが言えます

  1. Ansible管理サーバのバックアップは

    • /etc/ansible以下のAnsibleの設定ファイル

    • /home/[管理ユーザ]/.ssh以下のssh情報

    • Ansbileのインベントリファイル、その他作業ファイル

    をtarなどで取得しておけば良いことがわかりました。また、リストア先は、同じIPアドレスにしても異なるIPアドレスにしても問題なく動作することがわかりました。

  2. Ansible管理対象端末のバックアップは、sshのキーが異なってしまうため、再登録してあげる(Ansible管理サーバ上の管理ユーザの.ssh/known_hostsファイルを再作成してあげる)必要があることがわかりました。

  3. Ansible管理サーバからファイルをcopyモジュールなどで転送中にネットワーク障害が発生した場合には、sftpのタイムアウトを待ってansible_playbookがエラーになることがわかりました。

  4. Ansible管理サーバ上でタスクを実行時にネットワーク障害が発生した場合には、タイムアウトを超えた状態でもansible_playbookがエラーにならない(ハングアップしたままである)ことがわかりました。やはり、Ansibleはエージェントレスという利点の反面、ネットワーク障害には弱いため、別途自前で対応策を考える必要があるようです。

サイオスOSSよろず相談室

サイオスOSSよろず相談室(1)

問い合わせボタン