ansibleを使ってみて

## はじめに
若干の今更感はありますが、ansibleを使ってみて感じたことやどういう風に使ってきたかを記載します。
\# 多分、初めて使う人は同じような流れになるんじゃないかなと思ったり。
これから始める人の参考になれば幸いです。

## ansibleとは？
公式サイトのドキュメントの冒頭には以下のように記載されています。
> Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.

既に情報は色々でていると思うので省きますが、簡単にいうと構成管理ツール（システム自動管理ツール？）です。ChefやPuppetと似たようなものでが、別途エージェントやクライアントが不要で、Linuxであれば標準でインストールされているであろうSSHを利用します。

詳細は以下リンク先を参照してください。

* [ANSIBLE](http://docs.ansible.com/index.html)
* [Ansible Tutorial](http://yteraoka.github.io/ansible-tutorial/)

# 環境
* AWS
* Amazon Linux AMI release 2014.09

## インストール
インストール方法はドキュメントにLinuxのディストリビューション毎に記載されているので、そちらを参考にしてください。

* [インストール方法](http://docs.ansible.com/intro_installation.html#installing-the-control-machine)

Amazon Linuxであれば、以下コマンドを実行するだけで使えるようになります。

```bash
$ sudo yum --enablerepo=epel install ansible
$ ansible --version
ansible 1.7.2
```

## 初期動作確認
インストール後、以下コマンドなどを実行し動作確認可能です。successとなることを確認します。

```bash
$ ansible localhost -m ping
localhost | success >> {
    "changed": false,
    "ping": "pong"
}

$ ansible localhost -a "/bin/echo hello"
localhost | success | rc=0 >>
hello

```

上記ではローカルホストに対して実施していますが、リモートホストに対して実行する際は事前にSSH接続関連の設定が必要です。
詳しくはドキュメントを参照してください。

* [Getting Startted] (http://docs.ansible.com/intro_getting_started.html)

とりあえずここまででansibleを使う為の準備ができます。
以下からはどういう風に使ってきたかを簡単に…。

## どういう風に使ってきたか？
### 初期1
何はともあれ使ってみようっていう事で、以下のドキュメントを参考にplaybookを作成して試してみました。

* [Intro to Playbooks] (http://docs.ansible.com/playbooks_intro.html)

これは単一のymlファイルを作成して、その中に処理の全てを記載する方式です。
以下のようなファイルを作成して実行させます。

ansible用のhostsファイルを作成

```bash:/etc/ansible/hosts
[server]
192.168.100.11
```

処理を記載したsample1.ymlを作成

``` yaml:/etc/ansible/sample1.yml
---
- hosts: server
  vars:
    httpd_pkgs:
      - httpd
      - httpd-devel
  sudo: yes
  tasks:
  - name: ensure apache is at the latest version
    yum: name={{ item }} state=latest
    wiht_items:
      - "{{ httpd_pkgs }}"
  - name: ensure apache is running
    service: name=httpd state=started
```

ansible-playbookからsample1.ymlを指定して実行

```bash
$ cd /etc/ansible
$ ansible-playbook ./sample1.yml

<snip>

PLAY RECAP ********************************************************************
192.168.100.11                  : ok=x    changed=x    unreachable=0    failed=0
```

処理が多くなければこの方式で問題ないです。
但し、処理させたいことが多くなってくると、ファイルが大きくなっていくので管理が大変になってきます。

### 初期2
playbookは外部ファイルを参照させることも可能なようなので、処理毎にymlファイルを作成する方式です。以下のようなイメージです。

処理を呼び出すmain.ymlを作成

```yaml:/etc/ansible/main.yml
---
- include: /etc/ansible/sample1.yml
- include: /etc/ansible/sample2.yml
```

sample1.ymlは先ほどのものとします。

処理を記載したsample2.ymlを作成

```yaml:/etc/ansible/sample2.yml
---
- hosts: server
  vars:
    mysql_pkgs:
      - mysql
      - mysql-server
      - mysql-devel
  sudo: yes
  tasks:
    - name: ensure mysql is at the latest version
      yum: name={{ item }} state=latest
      with_items:
        - "{{ mysql_pkgs }}"
```

ansible-playbookからmain.ymlを指定して実行


```bash
$ cd /etc/ansible
$ ansible-playbook ./main.yml

<snip>

PLAY RECAP ********************************************************************
192.168.100.11                  : ok=x    changed=x    unreachable=0    failed=0
```

一つのymlファイルに全て記載するよりは管理しやすくなったでしょうか…？
但し、varに記載している変数がファイル内に含まれたままになっています。

### 中期1
ドキュメントを読んでいくとベストプラクティスなるものがあることに気づきます。

* [Best Practices] (http://docs.ansible.com/playbooks_best_practices.html)

これはroleという概念がでてきて、ディレクトリ構成で役割（処理）を分割することが可能な方式です。以下のようなイメージです。

```
production          # inventory file for production servers
stage               # inventory file for stage environment

group_vars/
 group1             # here we assign variables to particular groups
 group2             # ""
host_vars/
 hostname1          # if systems need specific variables, put them here
 hostname2          # ""

site.yml            # master playbook
webservers.yml      # playbook for webserver tier
dbservers.yml       # playbook for dbserver tier

roles/
  common/           # this hierarchy represents a "role"
    tasks/          #
      main.yml      #  <-- tasks file can include smaller files if warranted
    handlers/       #
      main.yml      #  <-- handlers file
    templates/      #  <-- files for use with the template resource
      ntp.conf.j2   #  <------- templates end in .j2
    files/          #
      bar.txt       #  <-- files for use with the copy resource
      foo.sh        #  <-- script files for use with the script resource
    vars/           #
      main.yml      #  <-- variables associated with this role
    defaults/       #
      main.yml      #  <-- default lower priority variables for this role
    meta/           #
      main.yml      #  <-- role dependencies

  webtier/          # same kind of structure as "common" was above, done for the webtier role
  monitoring/       # ""
  fooapp/           # ""
```

この構成で大体すっきりしてきました。
但し、ロールや変数に対して共有のもの、個別のものが混ざってしまうことがありました。

### 中期2
以下の構成を参考にしています。

* [Ansible オレオレベストプラクティス] (http://qiita.com/yteraoka/items/5ed2bddefff32e1b9faf)

共有したいロールを外に出してディレクトリツリーを作成しているところがナルホド！と思いました。

## 感想
ansibleはSSHを利用しているので、ラーニングコストも高くなく取っつきやすいと感じました。数年前にSSHを利用してリモートホストに対して、操作させるようなコマンドをシェルスクリプトで作成したことがありますが、それをもっと使いやすくしたツールだと思います。

また、現在も試行錯誤中なので後期はなく中期までとしています。
他にもこんな方法があるよ！といったものがあれば教えてください！

構成管理ツールは常時起動していなくて良いと思うし、ポータビリティ性があると別環境への展開もし易くなると思うのでDockerで管理した方が良いのかなー？とか思っています。
\# ansible環境を作るのが難しくないので、playbookの内容をSVNやGitで管理させるだけでも良さそうですが…。