SoftLayerの無料ベアメタルでOpenStackの学習をする(12) - 第11章「Ansibleを利用した構成管理の自動化」


[前回はこちら](http://qiita.com/orz/items/957f15eabaedf312b1a4) - [次回はこちら](http://qiita.com/orz/items/b303c0145f3b9be486bd)
***
#これはなに
[「OpenStackクラウドインテグレーション オープンソースクラウドによるサービス構築入門」](http://www.shoeisha.co.jp/book/detail/9784798139784)の実習をSoftLayerの無料ベアメタルで行う記録である。
![OpenStackクラウドインテグレーション オープンソースクラウドによるサービス構築入門](http://www.seshop.com/static/images/product/17681/L.png)

# 第11章 Ansibleを利用した構成管理の自動化

第10章まではOpenStackの標準機能の利用を学習してきた。当章ではAnsibleを利用し、OpenStackの運用を効率化する。

当章の支援ファイルは[こちら](https://github.com/josug-book1-materials/chapter11)。

## 11.1 ストーリーの展開

Ansibleで運用を改善しようという章のイントロ。

## 11.2 Ansibleの導入と設定

### 11.2.1 Ansibleのインストール

OSが提供するパッケージ、pip、ソースコードからビルドと3つの導入方法がある。その3つの方法の説明。
だたし、本書の記述はその先でpipからの導入を想定しているので、それにあわせることとする。

ガイドされているのはパッケージグループ「Development Tools」とパッケージ「python-virtualenv」の導入。

```
[root@step-server ~]# yum groupinstall -y "Development Tools"
～～～～～～～～
Complete!
[root@step-server ~]# yum install -y python-virtualenv
～～～～～～～～
Complete!
```

この後、一般ユーザーから作業をするとあるので、一般ユーザー user01 を作成し切り替える。

```
[root@step-server ~]# adduser user01
[root@step-server ~]# su - user01
```

一般ユーザー user01 でpythonの仮想実行環境に切り替えansibleを
インストールする。

```
[user01@step-server ~]$ virtualenv venv
New python executable in venv/bin/python
Installing Setuptools..............................................................................................................................................................................................................................done.
Installing Pip.....................................................................................................................................................................................................................................................................................................................................done.
[user01@step-server ~]$ source venv/bin/activate

(venv)[user01@step-server ~]$ pip install jinja2 passlib pycrypto pyyaml
Downloading/unpacking jinja2
～～～～～～～～
Successfully installed jinja2 passlib pycrypto pyyaml markupsafe
Cleaning up...

(venv)[user01@step-server ~]$ pip install ansible
Downloading/unpacking ansible
  Downloading ansible-1.9.0.1.tar.gz (916kB): 916kB downloaded
～～～～～～～～
Successfully installed ansible paramiko ecdsa
Cleaning up...

(venv)[user01@step-server ~]$ ansible --version
ansible 1.9.0.1
  configured module search path = None
```

1.9.0.1が導入された。本書では1.8.2で確認をしているとある。

### 11.2.2 Ansibleの基本設定

$HOME/.ansible.cfgに基本設定を記述する。

logディレクトリーを作る。

```
(venv)[user01@step-server ~]$ mkdir $HOME/log
```

$HOME/.ansible.cfgを設定する。

```
(venv)[user01@step-server ~]$ nano .ansible.cfg
(venv)[user01@step-server ~]$ cat .ansible.cfg
[defaults]
forks                   = 10
log_path                = /home/user01/log/ansible.log
host_key_checking       = False
gathering               = smart
transport               = smart
```

### 11.2.3 Ansibleの動作確認

Ansibleでlocalhost にpingを打ってみる。

```
(venv)[user01@step-server ~]$ cd
(venv)[user01@step-server ~]$ pwd
/home/user01
(venv)[user01@step-server ~]$ echo "localhost ansible_connection=local" > ansible_hosts
(venv)[user01@step-server ~]$ ansible all -i ansible_hosts -m ping
localhost | success >> {
    "changed": false,
    "ping": "pong"
}
```

ansible_hostsに192.168.0.11と192.168.0.21を足す。192.168.0.11のホストは存在しない。192.168.0.21は第10章で生き残ったaz2-dbs01のアドレスである。

```
(venv)[user01@step-server ~]$ nano ansible_hosts
(venv)[user01@step-server ~]$ cat ansible_hosts
localhost ansible_connection=local
192.168.0.11
192.168.0.21
```


Ansibleは、基本的にsshで接続して操作する。
localhostは「ansible_connection=local」なのでssh接続せずに実行しsuccessする。
192.168.0.21は、sshでTCP接続はしたがログインできなかったためにエラーになった。
192.168.0.11は、このIPでサーバーが起動していないのでsshでのTCP接続でエラーになった。

```
(venv)[user01@step-server ~]$ ansible all -i ansible_hosts -m ping
localhost | success >> {
    "changed": false,
    "ping": "pong"
}

192.168.0.21 | FAILED => SSH Error: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
    while connecting to 192.168.0.21:22
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
192.168.0.11 | FAILED => SSH Error: ssh: connect to host 192.168.0.11 port 22: No route to host
    while connecting to 192.168.0.11:22
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
```

sshで192.168.0.21にログインできるようにする。sshの秘密鍵を/home/user01/にコピーし、オーナーをuser01にする。

```
[root@step-server ~]# cp key-for-internal.pem /home/user01/
[root@step-server ~]# cd /home/user01
[root@step-server user01]# chown user01 key-for-internal.pem
[root@step-server user01]# ls -al key-for-internal.pem
-rw------- 1 user01 root 1680 Mar 29 18:03 key-for-internal.pem
```

.ansible.cfgのprivate_key_fileに秘密鍵をフルパスで設定する。

```
(venv)[user01@step-server ~]$ cat .ansible.cfg
[defaults]
forks                   = 10
log_path                = /home/user01/log/ansible.log
host_key_checking       = False
gathering               = smart
transport               = smart
private_key_file        = /home/user01/key-for-internal.pem
```
ansibleを実行するとき「-u root」を指定し、相手にrootで入る事を宣言する。
/home/user01/key-for-internal.pemでroot@192.168.0.21に接続でき、pingが成功した。

192.168.0.11が失敗するのは当然。

```
(venv)[user01@step-server ~]$ ansible all -i ansible_hosts -m ping -u root
localhost | success >> {
    "changed": false,
    "ping": "pong"
}

192.168.0.21 | success >> {
    "changed": false,
    "ping": "pong"
}

192.168.0.11 | FAILED => SSH Error: ssh: connect to host 192.168.0.11 port 22: No route to host
    while connecting to 192.168.0.11:22
It is sometimes useful to re-run the command using -vvvv, which prints SSH debug output to help diagnose the issue.
```

対象を「all:**!**192.168.0.11」とする。「**!**」で192.168.0.11を除いた「all」が対象となる。

192.168.0.11が対象から除外されたので、対象全てに正常にping応答が確認できた。

```
(venv)[user01@step-server ~]$ ansible 'all:!192.168.0.11' -i ansible_hosts -m ping -u root
localhost | success >> {
    "changed": false,
    "ping": "pong"
}

192.168.0.21 | success >> {
    "changed": false,
    "ping": "pong"
}
```

## 11.3 Ansibleの仕組み

節のタイトルのとおりAnsibleの仕組みの解説である。

このホスト名を変更する[プレイブック](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/sample-11-1.yml)の実行で動作を確認する。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-1.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [get hostname] **********************************************************
changed: [192.168.0.21]

TASK: [set hostname] **********************************************************
changed: [192.168.0.21]

NOTIFIED: [show hostname] *****************************************************
ok: [192.168.0.21] => {
    "msg": "before=az2-dbs01 after=ansible-host1"
}

PLAY RECAP ********************************************************************
192.168.0.21               : ok=4    changed=2    unreachable=0    failed=0

```

az2-dbs01 から ansible-host1 にホスト名が変更された。

もう一度、実行する。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-1.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [get hostname] **********************************************************
changed: [192.168.0.21]

TASK: [set hostname] **********************************************************
ok: [192.168.0.21]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=3    changed=1    unreachable=0    failed=0

```

すでにホスト名が変更されているため、handlersは呼び出されず「NOTIFIED: [show hostname]」は呼び出されない。

## 14.4 Ansibleによる基本操作の自動化

### 14.4.1 CenrOSのパッケージをインストール/アップデートする

パッケージをインストール/アップデートする。利用するプレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/sample-11-2.yml)。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-2.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [install or upgrade packages] *******************************************
changed: [192.168.0.21] => (item=bash,tcsh,zsh)

PLAY RECAP ********************************************************************
192.168.0.21               : ok=2    changed=1    unreachable=0    failed=0

```

### 11.4.2 ユーザーアカウントを作成する

対象ホストにユーザーansibleを作成する。利用するプレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/sample-11-3.yml)。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-3.yml
Enter a new user's password:
confirm Enter a new user's password:
***** VALUES ENTERED DO NOT MATCH ****
Enter a new user's password:
confirm Enter a new user's password:

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [add a new user on target host] *****************************************
changed: [192.168.0.21]

TASK: [add a publickey on localhost to authorized_keys on target host] ********
fatal: [192.168.0.21] => could not locate file in lookup: /root/.ssh/id_rsa.pub

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/home/user01/sample-11-3.retry

192.168.0.21               : ok=2    changed=1    unreachable=1    failed=0

```

パスワードの再入力でミスしたら再度入力を求められた。
「/root/.ssh/id_rsa.pub」へのアクセスでエラーになっている。本書を、よく読むと、事前にssh-keygenで作成しておいた公開鍵を指定するとある。

「/home/user01/.ssh/id_rsa.pub」を作る。

```
(venv)[user01@step-server samples]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user01/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user01/.ssh/id_rsa.
Your public key has been saved in /home/user01/.ssh/id_rsa.pub.
The key fingerprint is:
74:11:82:b0:f5:aa:c2:0f:cf:b8:45:f4:d6:26:44:7a user01@step-server
The key's randomart image is:
+--[ RSA 2048]----+
|    ..o.. o.     |
|     =.. . .     |
|    + E o .      |
|   . + + .       |
|    . = S        |
| . . o o         |
|  + o            |
|   O             |
|  o.+            |
+-----------------+
```

公開鍵のファイル名を書き換える。

```
    authorized_key:
      user: "{{ username }}"
      key: "{{ lookup('file', '/home/user01/.ssh/id_rsa.pub') }}"
```

今度は成功した。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-3.yml
Enter a new user's password:
confirm Enter a new user's password:

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [add a new user on target host] *****************************************
changed: [192.168.0.21]

TASK: [add a publickey on localhost to authorized_keys on target host] ********
changed: [192.168.0.21]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=3    changed=2    unreachable=0    failed=0
```

sshログインが可能になっている。

```
(venv)[user01@step-server samples]$ ssh ansible@192.168.0.21
[ansible@ansible-host1 ~]$ exit
logout
Connection to 192.168.0.21 closed.
```

### 11.4.3 sudoの設定を追加する

「/etc/sudoers」にansibleが所属するwheelを追加する。追加するのは存在しない場合だけ。利用するプレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/sample-11-4.yml)。

一度目は、エントリーが無いので「TASK: [grant privileges to do the sudo command to the wheel group]」が「changed」になる。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-4.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [grant privileges to do the sudo command to the wheel group] ************
changed: [192.168.0.21]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=2    changed=1    unreachable=0    failed=0
```

再度実行すると存在するので「ok」と表示され、追加は行われない。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-4.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [grant privileges to do the sudo command to the wheel group] ************
ok: [192.168.0.21]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=2    changed=0    unreachable=0    failed=0
```

### 11.4.4 設定ファイルを配置してサービスをリスタートする。

用意してある[my.cnf.j2](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/my.cnf.j2)を/etc/my.cnfにコピーする。ファイルの置き換えが発生したときだけ、MySQLをリスタートする。利用するプレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/sample-11-5.yml)。

一度目は[replace my.cnf]がchangedで、[restart database]が呼び出されている。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-5.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [replace my.cnf] ********************************************************
changed: [192.168.0.21]

NOTIFIED: [restart database] **************************************************
changed: [192.168.0.21]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=3    changed=2    unreachable=0    failed=0
```

2度目は[replace my.cnf]がokで、[restart database]は呼び出さない。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-5.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [replace my.cnf] ********************************************************
ok: [192.168.0.21]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=2    changed=0    unreachable=0    failed=0
```

### 11.4.5 OSを再起動して起動完了を確認する。

対象をrebootし2分待ってから10秒間隔でssh接続できるか確認する。利用するプレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/samples/sample-11-6.yml)。

pauseモジュールで停止中の場合「(^C-c = continue early, ^C-a = abort)」の表示でわかるように「Ctrl+C」で「Action? (a)bort/(c)ontinue:」のメッセージを出し中止することができる。

```
(venv)[user01@step-server samples]$ ansible-playbook -i ~/ansible_hosts -u root -e target=192.168.0.21 sample-11-6.yml

PLAY [192.168.0.21] ***********************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.21]

TASK: [reboot server] *********************************************************
changed: [192.168.0.21]

TASK: [wait for shutdown process] *********************************************
(^C-c = continue early, ^C-a = abort)
[192.168.0.21]
Pausing for 120 seconds
^C
Action? (a)bort/(c)ontinue:
ok: [192.168.0.21 -> 127.0.0.1]

TASK: [check the server to start up] ******************************************
ok: [192.168.0.21 -> 127.0.0.1]

PLAY RECAP ********************************************************************
192.168.0.21               : ok=4    changed=1    unreachable=0    failed=0
```

pauseモジュールでの停止中を待たないで「Ctrl+C」を押したら、終了してしまった。

```
TASK: [reboot server] *********************************************************
^CERROR: interrupted
(venv)[user01@step-server samples]$
```

## 11.5 OpenStack管理作業の自動化

### 11.5.1 事前準備作業

踏み台サーバーでユーザーansibleを作成して切り替える。

```
[root@step-server ~]# useradd ansible
[root@step-server ~]# cp /root/openrc /home/ansible/
[root@step-server ~]# chown ansible:ansible /home/ansible/openrc
[root@step-server ~]# su - ansible
[ansible@step-server ~]$
```


ユーザーansibleでansibleをpipによる導入する。

```
[ansible@step-server ~]$ virtualenv venv
New python executable in venv/bin/python
Installing Setuptools.............................................................................................done.
Installing Pip....................................................................................................................................done.

[ansible@step-server ~]$ source venv/bin/activate

(venv)[ansible@step-server ~]$ pip install jinja2 passlib pycrypto pyyaml
Downloading/unpacking jinja2
～～～～～～～～
Successfully installed jinja2 passlib pycrypto pyyaml markupsafe
Cleaning up...

(venv)[ansible@step-server ~]$ pip install ansible
Downloading/unpacking ansible
  Downloading ansible-1.9.0.1.tar.gz (916kB): 916kB downloaded
～～～～～～～～
Successfully installed ansible paramiko ecdsa
Cleaning up...
```

本書の支援ファイルとpython-novaclient、python-novaclientを導入する。

```
(venv)[ansible@step-server ~]$ cd $HOME

(venv)[ansible@step-server ~]$ git clone https://github.com/josug-book1-materials/chapter11.git
Initialized empty Git repository in /home/ansible/chapter11/.git/
remote: Counting objects: 218, done.
remote: Total 218 (delta 0), reused 0 (delta 0), pack-reused 218
Receiving objects: 100% (218/218), 32.98 KiB, done.
Resolving deltas: 100% (116/116), done.

(venv)[ansible@step-server ~]$ pip install python-novaclient==2.16.0
Downloading/unpacking python-novaclient==2.16.0
  Downloading python-novaclient-2.16.0.tar.gz (227kB): 227kB downloaded
～～～～～～～～
Successfully installed python-novaclient pbr argparse iso8601 PrettyTable requests simplejson six Babel pytz
Cleaning up..

(venv)[ansible@step-server ~]$ pip install python-neutronclient==2.3.4
Downloading/unpacking python-neutronclient==2.3.4
  Downloading python-neutronclient-2.3.4.tar.gz (105kB): 105kB downloaded
～～～～～～～～
Successfully installed python-neutronclient cliff httplib2 cmd2 pyparsing stevedore
Cleaning up...
```

oprnrcにネットワークのUUIDを取得する部分を加え[この様](https://github.com/josug-book1-materials/chapter11/blob/master/sample_openrc)にし、実行する。

```
(venv)[ansible@step-server ~]$ cat openrc
export OS_AUTH_URL=http://192.168.100.10:5000/v2.0/
export OS_REGION_NAME=RegionOne
export OS_TENANT_NAME=SNSApp
export OS_USERNAME=snsapp-infra-user
export OS_PASSWORD=passw0rd

function get_uuid () { cat - | grep " id " | awk '{print $4}'; }
export OS_DMZ_NET=`neutron net-show dmz-net | get_uuid`
export OS_APP_NET=`neutron net-show app-net | get_uuid`
export OS_DBS_NET=`neutron net-show dbs-net | get_uuid`

(venv)[ansible@step-server ~]$ source openrc
```

キーペアを作成しOpenStackに登録する。

<pre>
(venv)[ansible@step-server ~]$ ssh-keygen -t rsa -b 2048 -N ""
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ansible/.ssh/id_rsa):
Created directory '/home/ansible/.ssh'.
Your identification has been saved in /home/ansible/.ssh/id_rsa.
Your public key has been saved in /home/ansible/.ssh/id_rsa.pub.
The key fingerprint is:
a1:49:c1:a2:6d:db:3b:bb:d9:91:50:88:0a:0d:53:1f ansible@step-server
The key's randomart image is:
+--[ RSA 2048]----+
|o.. E..          |
| + ..o.o         |
|. .oo.o o        |
| ...o. + .       |
|  .. o+ S        |
|    . .. .       |
|       .o        |
|      oo .       |
|      ++.        |
+-----------------+

(venv)[ansible@step-server ~]$ nova keypair-add --pub-key .ssh/id_rsa.pub key-for-ansible

(venv)[ansible@step-server ~]$ nova keypair-list
+---------------------+-------------------------------------------------+
| Name                | Fingerprint                                     |
+---------------------+-------------------------------------------------+
| key-for-step-server | c6:a2:cd:b5:ee:0b:29:ae:19:61:27:f8:5d:28:5f:8b |
| key-for-internal    | 9d:89:c8:a7:c6:4b:f1:23:8c:41:9f:3f:a8:bf:91:77 |
| key-for-ansible     | a1:49:c1:a2:6d:db:3b:bb:d9:91:50:88:0a:0d:53:1f |
+---------------------+-------------------------------------------------+
</pre>

### 11.5.2 仮想マシンインスタンス構築の自動化

web、app、dbsと役割を指定すると、その役割の仮想マシンインスタンスを構築する。プレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book1/create_sample_vm.yml)。


プレイブックをホームにコピーし、ローカル接続にsshを使わないことを宣言する・

```
(venv)[ansible@step-server ~]$ cd

(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book1/create_sample_vm.yml .

(venv)[ansible@step-server ~]$ echo "localhost ansible_connection=local" > ansible_hosts
```

「target=web」を指定してプレイブックを実行する。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web create_sample_vm.yml

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [ansible_python_interpreter setup] **************************************
ok: [localhost]

TASK: [get uuid for generate hostname] ****************************************
changed: [localhost]

TASK: [create {{ target }}-server on nova-compute with floating_ip] ***********
changed: [localhost]

TASK: [create {{ target }}-server on nova-compute without floating_ip] ********
skipping: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=0

```

サーバーが作成されFloating IPも付与されている。

<pre>
(venv)[ansible@step-server ~]$ nova list --name ^web- --field name,networks
+--------------------------------------+------------------------------------------+-------------------------------------------------------------+
| ID                                   | Name                                     | Networks                                                    |
+--------------------------------------+------------------------------------------+-------------------------------------------------------------+
| 0055b5ed-5180-4b06-8805-c8b6205040dd | web-520710f9-08d3-41cd-9d28-aa6cc4bfca66 | dmz-net=192.168.0.22, 192.168.100.135; app-net=172.16.10.15 |
+--------------------------------------+------------------------------------------+-------------------------------------------------------------+

(venv)[ansible@step-server ~]$ nova floating-ip-list
+-----------------+-----------+--------------+---------+
| Ip              | Server Id | Fixed Ip     | Pool    |
+-----------------+-----------+--------------+---------+
| 192.168.100.135 |           | 192.168.0.22 | Ext-Net |
| 192.168.100.131 |           | 10.0.0.1     | Ext-Net |
| 192.168.100.134 |           | 192.168.0.19 | Ext-Net |
| 192.168.100.133 |           | 192.168.0.5  | Ext-Net |
+-----------------+-----------+--------------+---------+
</pre>


「target=app」で作成。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=app create_sample_vm.yml

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [ansible_python_interpreter setup] **************************************
ok: [localhost]

TASK: [get uuid for generate hostname] ****************************************
changed: [localhost]

TASK: [create {{ target }}-server on nova-compute with floating_ip] ***********
skipping: [localhost]

TASK: [create {{ target }}-server on nova-compute without floating_ip] ********
changed: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=0
```

作成された。

<pre>
(venv)[ansible@step-server ~]$ nova list --name ^app- --field name,networks
+--------------------------------------+------------------------------------------+-----------------------------------------------------------------+
| ID                                   | Name                                     | Networks                                                        |
+--------------------------------------+------------------------------------------+-----------------------------------------------------------------+
| ab7c19c6-6f4f-438e-8cdf-012dbb7a4cc1 | app-18e1b380-a213-4518-a3ae-30ccad545014 | dmz-net=192.168.0.23; app-net=172.16.10.16; dbs-net=172.16.20.8 |
+--------------------------------------+------------------------------------------+-----------------------------------------------------------------+
</pre>

「target=dbs」で作成。

<pre>
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=dbs create_sample_vm.yml

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [ansible_python_interpreter setup] **************************************
ok: [localhost]

TASK: [get uuid for generate hostname] ****************************************
changed: [localhost]

TASK: [create {{ target }}-server on nova-compute with floating_ip] ***********
skipping: [localhost]

TASK: [create {{ target }}-server on nova-compute without floating_ip] ********
changed: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=0

(venv)[ansible@step-server ~]$ nova list --name ^dbs- --field name,networks
+--------------------------------------+------------------------------------------+-------------------------------------------+
| ID                                   | Name                                     | Networks                                  |
+--------------------------------------+------------------------------------------+-------------------------------------------+
| 359d02ea-098e-4e03-966e-81bbc40da2c0 | dbs-968a948e-7e58-4089-a6c6-6b2a38bb71e6 | dmz-net=192.168.0.24; dbs-net=172.16.20.9 |
+--------------------------------------+------------------------------------------+-------------------------------------------+
</pre>


### 11.5.3 アプリケーションデプロイの自動化

ここで行うのは、下記の4点である。

0. タイムゾーンの変更
1. githubからアプリケーションのチェックアウト
2. 導入スクリプトの実行
3. サーバー間の連携をとるendpoint.confを内容を書き換えながら転送
4. サービスの開始

プレイブックは[こちら](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book1/install_sample_app.yml)。

まず、ansible_hosts に対象ホストのdmz-netのIPを記述する。これは操作用である。また、endpoint.confの書き換え用に、webにセットするappのapp-netのIPを、appにセットするdbsのdbs-netのIPを記述する。

```
(venv)[ansible@step-server ~]$ cat ansible_hosts
[localhost]
localhost ansible_connection=local

[web]
192.168.0.22

[app]
192.168.0.23

[dbs]
192.168.0.24

[web:vars]
app = 172.16.10.16

[app:vars]
dbs = 172.16.20.9
```

プレイブックとendpoint.confのテンプレートをホームにコピーする。

```
(venv)[ansible@step-server ~]$ cd

(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book1/install_sample_app.yml .

(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book1/endpoint.conf.j2 .
```

依存関係があるのでdbs、app、webの順にインストールする。

「target=dbs」で実行する。ログインするので「-u root」も指定した。アプリをgithubから取得するときに「403 Forbidden」が出た。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=dbs -u root install_sample_app.yml

PLAY [dbs] ********************************************************************

GATHERING FACTS ***************************************************************
The authenticity of host '192.168.0.24 (192.168.0.24)' can't be established.
RSA key fingerprint is 9d:7e:70:8f:da:c2:b0:1f:9c:57:39:c1:a1:01:9a:a3.
Are you sure you want to continue connecting (yes/no)? yes
ok: [192.168.0.24]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.24]

TASK: [checkout app from github] **********************************************
failed: [192.168.0.24] => {"cmd": "/usr/bin/git clone --origin origin --branch v1.0 https://github.com/josug-book1-materials/sample-app.git /root/sample-app", "failed": true, "rc": 128}
stderr: error: The requested URL returned error: 403 Forbidden while accessing https://github.com/josug-book1-materials/sample-app.git/info/refs

fatal: HTTP request failed

stdout: Initialized empty Git repository in /root/sample-app/.git/

msg: error: The requested URL returned error: 403 Forbidden while accessing https://github.com/josug-book1-materials/sample-app.git/info/refs

fatal: HTTP request failed

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/home/ansible/install_sample_app.retry

192.168.0.24               : ok=2    changed=1    unreachable=0    failed=1
```

とりあえず再実行した。今度は成功した。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=dbs -u root install_sample_app.yml

PLAY [dbs] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.24]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.24]

TASK: [checkout app from github] **********************************************
changed: [192.168.0.24]

TASK: [execute install script] ************************************************
ok: [192.168.0.24]

TASK: [copy endpoint.conf to web and app server] ******************************
skipping: [192.168.0.24]

PLAY RECAP ********************************************************************
192.168.0.24               : ok=4    changed=2    unreachable=0    failed=0
```

「target=app」で実行。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=app -u root install_sample_app.yml

PLAY [app] ********************************************************************

GATHERING FACTS ***************************************************************
The authenticity of host '192.168.0.23 (192.168.0.23)' can't be established.
RSA key fingerprint is 4d:8e:f4:7d:06:ca:85:c4:b7:23:27:30:67:3a:8b:13.
Are you sure you want to continue connecting (yes/no)? yes
ok: [192.168.0.23]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.23]

TASK: [checkout app from github] **********************************************
changed: [192.168.0.23]

TASK: [execute install script] ************************************************
ok: [192.168.0.23]

TASK: [copy endpoint.conf to web and app server] ******************************
changed: [192.168.0.23]

NOTIFIED: [startup service] ***************************************************
changed: [192.168.0.23]

PLAY RECAP ********************************************************************
192.168.0.23               : ok=6    changed=4    unreachable=0    failed=0
```


「target=app」で実行。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web -u root install_sample_app.yml

PLAY [web] ********************************************************************

GATHERING FACTS ***************************************************************
The authenticity of host '192.168.0.22 (192.168.0.22)' can't be established.
RSA key fingerprint is 28:30:e0:72:bc:7e:d8:61:da:1d:cb:67:02:19:8b:5e.
Are you sure you want to continue connecting (yes/no)? yes
ok: [192.168.0.22]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.22]

TASK: [checkout app from github] **********************************************
changed: [192.168.0.22]

TASK: [execute install script] ************************************************
ok: [192.168.0.22]

TASK: [copy endpoint.conf to web and app server] ******************************
changed: [192.168.0.22]

NOTIFIED: [startup service] ***************************************************
changed: [192.168.0.22]

PLAY RECAP ********************************************************************
192.168.0.22               : ok=6    changed=4    unreachable=0    failed=0
```

### 11.5.4 ダイナミックインベントリーでホストの増減に対応

「11.5.3 アプリケーションデプロイの自動化」では対象のIPをansible_hostsに記述した。しかし、OpenStackでは基本的にデプロイするまでアドレスが不明である。
ansibleにはインベントリー情報を返す外部プログラムを呼び出し、それを対象とすることができる。

外部プログラムの条件は、下記と本書にある。

0. 単体実行可能
1. --list を引数とした場合、ホストリストをJSONで返す
2. --host <hostname>が引数の場合、ホスト用のパラメーターをJSONで返す

単純にホストリストを返すシェルで実行を確認する。

```
(venv)[ansible@step-server ~]$ cat inventry.sh
#!/bin/sh

usage() {
        echo "Usage: invenrty.sh --list|--host hostname"
        exit 1
}

case $1 in
        "--list")
                echo '{"sns":{"hosts":["192.168.0.22","192.168.0.23","192.168.0.24"]}}'
                ;;
        "--host")
                if [ "x"$2 == "x" ] || [ $# -ne 2 ]; then
                        usage
                fi
                echo "{}"
                ;;
        *)
                usage
                ;;
esac
```

pingモジュールで確認すると、こんなシェルでも機能する。

```
(venv)[ansible@step-server ~]$ ansible sns -i inventry.sh -m ping -u root
192.168.0.22 | success >> {
    "changed": false,
    "ping": "pong"
}

192.168.0.24 | success >> {
    "changed": false,
    "ping": "pong"
}

192.168.0.23 | success >> {
    "changed": false,
    "ping": "pong"
}
```

用意されてる[sample_app_inventory.py](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/sample_app_inventory.py)と[sample_app_inventory.ini](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/sample_app_inventory.ini)をホームにコピーする。[sample_app_inventory.py](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/sample_app_inventory.py)には実行権をつける。

```
(venv)[ansible@step-server ~]$ cd

(venv)[ansible@step-server ~]$ cp chapter11/playbooks/sample_app_inventory.py .

(venv)[ansible@step-server ~]$ cp chapter11/playbooks/sample_app_inventory.ini .

(venv)[ansible@step-server ~]$ chmod u+x sample_app_inventory.py

```

iniファイルは、このようになっている。

```
(venv)[ansible@step-server ~]$ cat sample_app_inventory.ini
[DEFAULT]


[stack]
api_version    = 1.1
os_username    = %OS_USERNAME%
os_password    = %OS_PASSWORD%
os_auth_url    = %AUTH_URL%
os_region_name = %REGION_NAME%
os_tenant_name = %TENANT_NAME%

[sample_app]
web_hostname_prefix = web-
app_hostname_prefix = app-
dbs_hostname_prefix = dbs-


##
## [EOF]
##
```

今回の環境に合わせて書き換える。

```
(venv)[ansible@step-server ~]$ cat sample_app_inventory.ini
[DEFAULT]


[stack]
api_version    = 1.1
os_username    = snsapp-infra-user
os_password    = passw0rd
os_auth_url    = http://192.168.100.10:5000/v2.0/
os_region_name = RegionOne
os_tenant_name = SNSApp

[sample_app]
web_hostname_prefix = web-
app_hostname_prefix = app-
dbs_hostname_prefix = dbs-


##
## [EOF]
##
```

実行すると

```
(venv)[ansible@step-server ~]$ ./sample_app_inventory.py --list
{
  "_meta": {
    "hostvars": {
      "192.168.0.22": {
        "app": "172.16.10.16"
      },
      "192.168.0.23": {
        "dbs": "172.16.20.9"
      },
      "192.168.0.24": {}
    }
  },
  "app": {
    "hosts": [
      "192.168.0.23"
    ],
    "vars": {
      "dbs": "172.16.20.9"
    }
  },
  "dbs": {
    "hosts": [
      "192.168.0.24"
    ],
    "vars": {}
  },
  "localhost": {
    "hosts": [
      "localhost"
    ],
    "vars": {
      "ansible_connection": "local"
    }
  },
  "web": {
    "hosts": [
      "192.168.0.22"
    ],
    "vars": {
      "app": "172.16.10.16"
    }
  }
}
```

この章で作ったサーバーをいったん削除する。

```
(venv)[ansible@step-server ~]$ nova delete app-18e1b380-a213-4518-a3ae-30ccad545014
(venv)[ansible@step-server ~]$ nova delete dbs-968a948e-7e58-4089-a6c6-6b2a38bb71e6
(venv)[ansible@step-server ~]$ nova delete web-520710f9-08d3-41cd-9d28-aa6cc4bfca66
```

新規にサーバーを起動する。

```
(venv)[ansible@step-server ~]$ echo "localhost ansible_connection=local" > ansible_hosts
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=web create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=app create_sample_vm.yml
(venv)[ansible@step-server ~]$ ansible-playbook -i ansible_hosts -e target=dbs create_sample_vm.yml
```

dbsに導入する。対象IPが[192.168.0.27]になっている。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=dbs install_sample_app.yml

PLAY [dbs] ********************************************************************

GATHERING FACTS ***************************************************************
The authenticity of host '192.168.0.27 (192.168.0.27)' can't be established.
RSA key fingerprint is a8:6a:42:e4:e2:19:2f:19:67:99:44:2e:8e:72:8b:40.
Are you sure you want to continue connecting (yes/no)? yes
ok: [192.168.0.27]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.27]

TASK: [checkout app from github] **********************************************
changed: [192.168.0.27]

TASK: [execute install script] ************************************************
ok: [192.168.0.27]

TASK: [copy endpoint.conf to web and app server] ******************************
skipping: [192.168.0.27]

PLAY RECAP ********************************************************************
192.168.0.27               : ok=4    changed=2    unreachable=0    failed=0
```

appに導入する。対象IPが[192.168.0.26]になっている。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=app install_sample_app.yml

PLAY [app] ********************************************************************

GATHERING FACTS ***************************************************************
The authenticity of host '192.168.0.26 (192.168.0.26)' can't be established.
RSA key fingerprint is 82:84:ad:c8:3e:fe:fd:a9:b0:43:cd:fc:9d:d0:43:b6.
Are you sure you want to continue connecting (yes/no)? yes
ok: [192.168.0.26]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.26]

TASK: [checkout app from github] **********************************************
changed: [192.168.0.26]

TASK: [execute install script] ************************************************
ok: [192.168.0.26]

TASK: [copy endpoint.conf to web and app server] ******************************
changed: [192.168.0.26]

NOTIFIED: [startup service] ***************************************************
changed: [192.168.0.26]

PLAY RECAP ********************************************************************
192.168.0.26               : ok=6    changed=4    unreachable=0    failed=0
```

webに導入する。対象IPが[192.168.0.25]になっている。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -e target=web install_sample_app.yml

PLAY [web] ********************************************************************

GATHERING FACTS ***************************************************************
The authenticity of host '192.168.0.25 (192.168.0.25)' can't be established.
RSA key fingerprint is b4:3c:b3:1c:bd:58:5f:4e:8c:72:6d:05:82:2e:a3:01.
Are you sure you want to continue connecting (yes/no)? yes
ok: [192.168.0.25]

TASK: [change the timezone] ***************************************************
changed: [192.168.0.25]

TASK: [checkout app from github] **********************************************
changed: [192.168.0.25]

TASK: [execute install script] ************************************************
ok: [192.168.0.25]

TASK: [copy endpoint.conf to web and app server] ******************************
changed: [192.168.0.25]

NOTIFIED: [startup service] ***************************************************
changed: [192.168.0.25]

PLAY RECAP ********************************************************************
192.168.0.25               : ok=6    changed=4    unreachable=0    failed=0
```

### 11.5.5 データベースのバックアップ/リストアを自動化

dbsでスナップショットの取得、appでサービスの再起動、スナップショットのバックアップの自動化である。

3ステップのプレイブックはこちら。

[create_snapshot.yml](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book2/create_snapshot.yml)、
[restart_rest_service.yml](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book2/restart_rest_service.yml)
[backup_snapshot.yml](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book2/backup_snapshot.yml)

これを一気に行うプレイブックはこちら。

[db_backup.yml](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book2/db_backup.yml)

これらのプレイブックをホームにコピーする。

```
(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book2/create_snapshot.yml .
(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book2/restart_rest_service.yml .
(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book2/backup_snapshot.yml .
(venv)[ansible@step-server ~]$ cp chapter11/playbooks/book2/db_backup.yml .
```

一気に行う[db_backup.yml](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book2/db_backup.yml)を実行したがエラーになる。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -t snapshot,backup -u root db_backup.yml

PLAY [dbs] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.27]

TASK: [stop mysqld] ***********************************************************
ok: [192.168.0.27]

TASK: [umount mysql_dir] ******************************************************
ok: [192.168.0.27]

TASK: [create snapshot on lvm] ************************************************
failed: [192.168.0.27] => {"changed": true, "cmd": ["lvcreate", "-s", "/dev/mysql_vg/mysql_vol01", "-L", "100m", "-n", "mysql_bk_snap01"], "delta": "0:00:00.009340", "end": "2015-03-30 17:32:52.913837", "rc": 5, "start": "2015-03-30 17:32:52.904497", "warnings": []}
stderr:   Volume group "mysql_vg" not found

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/home/ansible/db_backup.retry

192.168.0.27               : ok=3    changed=0    unreachable=0    failed=1

```

lvmのsnapshotを作成しようとしているけど、

```
～～～～～～
mysql_dir: /var/lib/mysql
mysql_vol: /dev/mysql_vg/mysql_vol01
mysql_snap: mysql_bk_snap01
mysql_snap_size: 100m
～～～～～～
command: lvcreate -s "{{ mysql_vol }}" -L "{{ mysql_snap_size }}" -n "{{ mysql_snap }}"
```

dbsにlvは無いし．．．

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# lvdisplay
  No volume groups found
```

接続されているdiskはvdaとvdb。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# lsblk
NAME                            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0                              11:0    1  410K  0 rom
vda                             252:0    0   10G  0 disk
└─vda1                          252:1    0   10G  0 part /
vdb                             252:16   0   10G  0 disk /mnt
```

[backup_snapshot.yml](https://github.com/josug-book1-materials/chapter11/blob/master/playbooks/book2/backup_snapshot.yml)では/dev/vdd1をマウントしているので、vdcとvddが接続されている想定のようだ。
[SoftLayerの無料ベアメタルでOpenStackの学習をする(10) - 第9章「ブロックボリュームを活用したデータ保護」(Cinderの利用)](http://qiita.com/orz/items/db45139054ee42612179)の手順を元に、ボリュームを2本追加する。
vdcにLVMをつくりmysqlのデータ領域とする。
vddは通常のext4のパーティションとしてバックアップ領域にする。

cinderでボリュームを2本作成する。

<pre>
(venv)[ansible@step-server ~]$ cinder create --display-name dbs_vdc --availability-zone az1 10
+---------------------+--------------------------------------+
|       Property      |                Value                 |
+---------------------+--------------------------------------+
|     attachments     |                  []                  |
|  availability_zone  |                 az1                  |
|       bootable      |                false                 |
|      created_at     |      2015-03-30T11:43:00.654349      |
| display_description |                 None                 |
|     display_name    |               dbs_vdc                |
|      encrypted      |                False                 |
|          id         | 5293f5c7-d386-4b36-9092-252f724eeafd |
|       metadata      |                  {}                  |
|         size        |                  10                  |
|     snapshot_id     |                 None                 |
|     source_volid    |                 None                 |
|        status       |               creating               |
|     volume_type     |                 None                 |
+---------------------+--------------------------------------+

(venv)[ansible@step-server ~]$ cinder create --display-name dbs_vdd --availability-zone az1 10
+---------------------+--------------------------------------+
|       Property      |                Value                 |
+---------------------+--------------------------------------+
|     attachments     |                  []                  |
|  availability_zone  |                 az1                  |
|       bootable      |                false                 |
|      created_at     |      2015-03-30T11:43:13.524431      |
| display_description |                 None                 |
|     display_name    |               dbs_vdd                |
|      encrypted      |                False                 |
|          id         | e7f73a03-e9a3-4f27-9a33-a40c869d13cb |
|       metadata      |                  {}                  |
|         size        |                  10                  |
|     snapshot_id     |                 None                 |
|     source_volid    |                 None                 |
|        status       |               creating               |
|     volume_type     |                 None                 |
+---------------------+--------------------------------------+
</pre>

dbsに接続する。

<pre>
(venv)[ansible@step-server ~]$ function get_uuid () { cat - | grep " id " | awk '{print $4}'; }

(venv)[ansible@step-server ~]$ export MY_DBS_VDC=`cinder show dbs_vdc |get_uuid`

(venv)[ansible@step-server ~]$ export MY_DBS_VDD=`cinder show dbs_vdd |get_uuid`

(venv)[ansible@step-server ~]$ nova volume-attach dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf $MY_DBS_VDC
+----------+--------------------------------------+
| Property | Value                                |
+----------+--------------------------------------+
| device   | /dev/vdc                             |
| id       | 5293f5c7-d386-4b36-9092-252f724eeafd |
| serverId | e4908bd6-c862-4993-964c-44c7bf6c4ddf |
| volumeId | 5293f5c7-d386-4b36-9092-252f724eeafd |
+----------+--------------------------------------+

(venv)[ansible@step-server ~]$ nova volume-attach dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf $MY_DBS_VDD
+----------+--------------------------------------+
| Property | Value                                |
+----------+--------------------------------------+
| device   | /dev/vdd                             |
| id       | e7f73a03-e9a3-4f27-9a33-a40c869d13cb |
| serverId | e4908bd6-c862-4993-964c-44c7bf6c4ddf |
| volumeId | e7f73a03-e9a3-4f27-9a33-a40c869d13cb |
+----------+--------------------------------------+
</pre>

接続された。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0     11:0    1  410K  0 rom
vda    252:0    0   10G  0 disk
└─vda1 252:1    0   10G  0 part /
vdb    252:16   0   10G  0 disk /mnt
vdc    252:32   0   10G  0 disk
vdd    252:48   0   10G  0 disk
```

「/dev/mysql_vg/mysql_vol01」のLVMスナップショットを作ることになっている。

/dev/vdcのタイプを 8e (Linux LVM)にする。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# fdisk /dev/vdc
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0xed33b73b.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-20805, default 1):
Using default value 1
Last cylinder, +cylinders or +size{K,M,G} (1-20805, default 20805):
Using default value 20805

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): 8e
Changed system type of partition 1 to 8e (Linux LVM)

Command (m for help): p

Disk /dev/vdc: 10.7 GB, 10737418240 bytes
16 heads, 63 sectors/track, 20805 cylinders
Units = cylinders of 1008 * 512 = 516096 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xed33b73b

   Device Boot      Start         End      Blocks   Id  System
/dev/vdc1               1       20805    10485688+  8e  Linux LVM

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.
```
/dev/vdc1にpvを作り、vg「mysql_vg」、lv「mysql_vol01」を作る。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# pvcreate /dev/vdc1
  Physical volume "/dev/vdc1" successfully created

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# vgcreate mysql_vg /dev/vdc1
  Volume group "mysql_vg" successfully created

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# lvcreate -L 5G -n mysql_vol01 mysql_vg
  Logical volume "mysql_vol01" created
```

/dev/mysql_vg/mysql_vol01 が作成された。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# lsblk
NAME                            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sr0                              11:0    1  410K  0 rom
vda                             252:0    0   10G  0 disk
└─vda1                          252:1    0   10G  0 part /
vdb                             252:16   0   10G  0 disk /mnt
vdc                             252:32   0   10G  0 disk
└─vdc1                          252:33   0   10G  0 part
  └─mysql_vg-mysql_vol01 (dm-0) 253:0    0    5G  0 lvm
vdd                             252:48   0   10G  0 disk

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# ls /dev/mysql_vg/mysql_vol01
/dev/mysql_vg/mysql_vol01
```
ext4のfsを作り、MySQLデータを移行し/var/lib/mysqlにマウントする。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# mkfs.ext4 -L mysql_data /dev/mysql_vg/mysql_vol01

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# tune2fs -c 0 -i 0 -r 0 /dev/mysql_vg/mysql_vol01

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# mkdir /tmp/data

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# mount LABEL=mysql_data /tmp/data

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# chown -R mysql:mysql /tmp/data

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# service mysqld stop

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# mv /var/lib/mysql/* /tmp/data/


[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# umount /tmp/data/

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# mount LABEL=mysql_data /var/lib/mysql

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# service mysqld start
```

vddは、83 (Linux)にしてext4のfsを作成しておく。

```
[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# fdisk /dev/vdd

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# mkfs.ext4 -L mysql_backup /dev/vdd1

[root@dbs-e945fd19-f2ba-40a2-8470-ad1c6092eacf /]# tune2fs -c 0 -i 0 -r 0 /dev/vdd1
```

これでansibleでの自動バックアップに成功した。

```
(venv)[ansible@step-server ~]$ ansible-playbook -i sample_app_inventory.py -t snapshot,backup -u root db_backup.yml

PLAY [dbs] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.27]

TASK: [stop mysqld] ***********************************************************
changed: [192.168.0.27]

TASK: [umount mysql_dir] ******************************************************
changed: [192.168.0.27]

TASK: [create snapshot on lvm] ************************************************
changed: [192.168.0.27]

TASK: [mount mysql_dir] *******************************************************
changed: [192.168.0.27]

TASK: [start mysqld] **********************************************************
changed: [192.168.0.27]

PLAY [app] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.26]

TASK: [restart rest app] ******************************************************
changed: [192.168.0.26]

PLAY [dbs] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [192.168.0.27]

TASK: [make directory] ********************************************************
changed: [192.168.0.27]

TASK: [mount backup] **********************************************************
changed: [192.168.0.27]

TASK: [mount snapshot] ********************************************************
changed: [192.168.0.27]

TASK: [archive database files to "{{ backup_mountpoint }}"] *******************
changed: [192.168.0.27]

TASK: [umount snapshot] *******************************************************
changed: [192.168.0.27]

TASK: [umount backup] *********************************************************
changed: [192.168.0.27]

TASK: [remove snapshot] *******************************************************
changed: [192.168.0.27]

PLAY RECAP ********************************************************************
192.168.0.26               : ok=2    changed=1    unreachable=0    failed=0
192.168.0.27               : ok=14   changed=12   unreachable=0    failed=0
```

***
第11章の完了。なんとかなった。
***
[前回はこちら](http://qiita.com/orz/items/957f15eabaedf312b1a4) - [次回はこちら](http://qiita.com/orz/items/b303c0145f3b9be486bd)