ローカル環境でAnsibleの動作をDockerを使って検証する

こんにちはみなさん、@niisan-tokyo です。

今回は弊社でも使用しているインフラ環境の構成管理ツールであるAnsibleについて、自分の勉強も兼ねて記事にしてみました。

# Ansible

インフラ環境をコードで記述しようという思想( infra as a code )のもとで作られた、インフラの構成管理ツールで、同様のものにchef, itamae, pappetなんてものがあります
https://www.ansible.com/

Ansibleはplaybookと呼ばれるインフラ構成の設定ファイルを作成しておけば、コマンド一発で対象環境にssh接続し、設定されたとおりに環境を整えてくれるというものです。
こいつの利点は、なんといっても一回設定を完成させれば、同じ構成のインフラをいくらでも作れるというところです。
もちろん、設定ファイルの完成までに、何度かやり直しをする必要が出てくるでしょう。
そんなとき、手軽に破棄して再生成できる検証環境があると、それなりに捗るんじゃないかと考えたため、今回はDockerを使用して検証環境を作ってみようと考えました

ついでに、Ansibleをインストールしたdockerイメージを一緒に作成して、ホストマシンにAnsibleを入れていなくても、すぐに検証できるようにしてみました。

## 実験環境

今回は OSX 11.10.5 に、docker toolboxを導入した環境で検証しています

# 検証環境の構築

今回の検証では、ubuntuにインストールされたAnsibleを使って、CentOSマシンの環境を整える、という状況をシミュレートします
そのため、Dockerイメージとして、Ansibleをインストールしたマシンおよび検証用のCentOSマシンの2つのイメージを用意します

## Ansibleインストールマシン

Ansibleをインストールしたマシンを以下のDockerfileで定義します(ansible/Dockerfile)

```ansible/Dockerfile
FROM ubuntu

RUN apt-get update && apt-get install -y software-properties-common && \
apt-add-repository ppa:ansible/ansible && apt-get update && apt-get install -y ansible

CMD /bin/bash
```

## CentOS 検証マシン

次にCentOSの検証マシンを以下のDockerfileで定義します(centos/Dockerfile)

```centos/Dockerfile
FROM centos:6.8

RUN yum -y install openssh-server

RUN ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
RUN ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa

RUN sed -ri 's/^#PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config
RUN echo "root:" | chpasswd

EXPOSE 22

CMD ["/usr/sbin/sshd", "-D"]
```
わざわざSSHDを起動しているのは、これがないとAnsibleが接続できないからです。

## docker-compose.yml

上の二つのDockerfileを個々にbuildして、linkでつなげてしまっても良いのですが、見通しを要するために、以下のdocker-compose.ymlファイルを用意し、docker-composeで連携できるように設定しちゃいましょう

```docker-compose.yml
ersion: '2'
services:
    ansible:
        build: ansible
        volumes:
            - .:/var/data

    target:
        build: centos

```

## 動作確認

以下で検証環境を立ち上げてみましょう

```
$ docker-compose build
$ docker-compose up -d
$ docker-compose run ansible
```

これで、Ansibleのコンテナが立ち上がり、ターミナルには入れたと思います

```
$ ansible --version
ansible 2.1.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```

こんな感じでansibleが使えるようになっています
次に、`ssh`で検証用のCentOSに接続できることを確認します

```
root@75f8e4c375b5:/# ssh target
[root@80fbcbf5d857 ~]# exit
root@75f8e4c375b5:/#
```
できました

# Ansibleの動作検証

## Ansibleで直接コマンドを打つ

それではAnsibleを使ってCentOS検証環境にコマンドを打ってみましょう
まず、接続設定のために以下のファイルを用意します(hosts)

```hosts
[target]
target

[target:vars]
ansible_user=root
```
次にコマンドラインで以下のコマンドを打ってみましょう

```
$ cd /var/data
$ ansible -i hosts target -vvvv -m ping
(略)
target | SUCCESS => {
    "changed": false,
    "invocation": {
        "module_args": {
            "data": null
        },
        "module_name": "ping"
    },
    "ping": "pong"
}
```
はい、SUCCESSと出ましたので、成功です。
`-i`でホスト情報などを記したファイルの場所を指定しています
`-vvvv`は詳細なログを残すためのオプションです
`-m`はモジュール名で、ansibleが用意している操作のことです
pingとありますが、普通に我々が使っているpingとは挙動が違っていますね

## vim をインストールしてみる

vimはCentOS検証環境にはデフォルトでは入っていません

```
$ ssh target
$ vim
-bash: vim: command not found
$ exit
```
なので、ansibleを通してインストールしてみましょう

```
$ ansible -i hosts target -vvvv -m yum -a name=vim
$ ssh target
$ vim hoge
```
しっかりインストールされていますね
ここでも`yum`はansibleの用意しているモジュール名で実際には`yum install -y`が叩かれています
`-a`はモジュールに渡される引数です。今回の場合、`name=vim`でインストールするパッケージ名を指定しています

## playbookを使ってみる

一旦ansible環境から出て、docker-composeでCentOS検証環境のコンテナを削除し、新しいコンテナを立てなおしてみましょう

```
$ docker-compose stop
$ docker-compose rm target
$ docker-compose up -d
$ docker-compose run ansible
$ ssh target
$ vim
-bash: vim: command not found
$ exit
```
新しくコンテナを立て直したことで、vimがインストールされる前の状態に戻りました
こんな感じで、検証環境を好きな様に捨てて刷新することができます

では、最後にplaybookを使ってAnsibleを動かしてみましょう
以下のファイルを用意します

```playbook.yml
- hosts: target
  tasks:
  - name: Install Vim
    yum: name=vim
```
で、playbookを使ったコマンドを叩いてみます

```
$ ansible-playbook -i hosts playbook.yml
```
少し経つと処理が完了します(-vvvvで詳細なログを出せます)

最後に確かめてみましょう

```
$ ssh target
$ vim hoge
```
`vim`がインストールされているのが確認できます

# まとめ

Ansibleを使った環境構築が流行ってきているので、便乗してみました。
業務上で必要になったこともあり、検証環境を作っていましたが、いかがでしたでしょうか
まあ、Vagrantでも良かったのですが、あれは注意していないとPCのディスクを一気に圧迫しかねないので、サクッと消せるDockerを採用してみた次第です
では、この辺りで失礼します

# 参考
[ようへいの日々精進XP](http://inokara.hateblo.jp/entry/2014/02/26/012144)
[Ansible install](http://docs.ansible.com/ansible/intro_installation.html#latest-releases-via-apt-ubuntu)
[Ansible yum-module](http://docs.ansible.com/ansible/yum_module.html)
[Ansible playbook](http://docs.ansible.com/ansible/playbooks_intro.html)