ansible role 事始め

この記事は [エーピーコミュニケーションズ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ap-com) の 4 日目の記事となります。

# はじめに

今回は今年一年でやっと業務で使いはじめた ansible の role について簡単に説明していきます。
最近は role を作ってからコーディングし始める流れが自分の中ででき、単体で playbook を作る場面が少なく感じています。
今回は ansible のインストールから簡単な role の作成、playbook 実行までを説明していきます。

# 環境構成

* VirtualBox：6.0.14
* OS：CnetOS 7.7
* python：3.6.8
* ansible：2.9.1

```console:Ansibleのバージョン指定
CentOS では yum でインストール可能な Ansible ですが、
python モジュールの１つでもあるため python のパッケージ管理でもある pip でもインストール可能です。

CentOS の yum では以下のバージョンがインストール可能です。
※2019/12/03 時点
・extras repository：2.4.2
・epel   repository：2.9.1

上記以外のバージョンをインストールしたい場合には python-pip をインストールし、
pip コマンドでバージョンを指定しインストールすることも可能です。
```

# ansible setup

```console:ansible-install
$ yum install python3
$ python3 -V
Python 3.6.8

$ pip3 install ansible
$ ansible --version
ansible 2.9.1
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Aug  7 2019, 17:28:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
```

# ansible 疎通確認

インストールできたところで疎通確認です。
今回は自身のサーバのみに設定変更を行うため、SSHの鍵認証を簡略して設定します。

```console:鍵設定
# パスフレーズ無しで鍵作成
$ ssh-keygen -t rsa -b 4096
・・・
Enter file in which to save the key (/root/.ssh/id_rsa): ★ Enter key
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): ★ Enter key
Enter same passphrase again: ★ Enter key

# 鍵ファイルを所定の位置に移動
$ mv .ssh/{id_rsa.pub,authorized_keys}

# 接続用設定ファイルの修正
$ vi .ssh/config
↓
Host localhost
  HostName 127.0.0.1
  User root
  IdentityFile ~/.ssh/id_rsa

# 疎通確認
$ ssh localhost
・・・
Are you sure you want to continue connecting (yes/no)?  ★ yes を入力

$ w
※二人ログインしていれば OK
$ exit
```

inventory ファイルを作成して ansible の疎通確認をします。

```console:ansible疎通確認
$ vi inventory.dev
↓
[web]
localhost ansible_host=127.0.0.1

# ping モジュールで疎通確認
$ ansible -i inventory.dev web -m ping
localhost | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
```

```console:ansibleの実行環境(管理対象サーバ)
上述の facts を見ると管理対象サーバの python のバージョンを取得しています。
※今回は python3 を追加でインストールしたのですが、ansible が対象サーバから取得したバージョンは python2 でした。

ansible はエージェントレスなアプリケーションですが、内部では python のコードを scp でファイル転送し、
python コードを対象サーバで実行しています。
このため、モジュールによっては対象サーバ内にpythonモジュールが必要な場合もあります。
```

# role 作成

早速 Role を作成します。
今回は common(サーバ共通の設定)と webtier(webサーバ(nginx))を作成していきます。

```console:role作成
# role 用のディレクトリ作成
$ mkdir roles

# role のテンプレート作成
$ ansible-galaxy init --init-path roles/ common
$ ansible-galaxy init --init-path roles/ webtier

# role 設定
$ vi web.yml
↓
- hosts: web
  gather_facts: no
  become: yes
  roles:
    - common
    - webtier

# 空実行
$ ansible-playbook -i inventory.dev web.yml
PLAY [web] ***************************************************************

PLAY RECAP ***************************************************************
```
---

```yml:playbook編集[common]
# 共通設定
$ vi roles/common/tasks/main.yml
↓
---
# tasks file for common
- include: packages.yml
- include: users.yml

$ vi roles/common/tasks/packages.yml
↓
---
# tasks file for common packages
- name: install common packages
  yum:
    name: "{{ packages }}"
  vars:
    packages:
      - bind-utils
      - vim
      - wget

$ vi roles/common/tasks/users.yml
↓
---
# tasks file for common users
- name: add users
  user:
    name: james
    group: wheel
    shell: /bin/bash

# Playbook 実行
$ ansible-playbook -i inventory.dev web.yml
・・・
PLAY RECAP *************************************************************************************************
localhost            : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

# 実装確認
$ nslookup www.google.co.jp
・・・
Name:   www.google.co.jp
Address: xxx.xxx.xxx.xxx

$ id james
uid=1000(james) gid=10(wheel) groups=10(wheel)
```

---

```yml:playbook編集[webtier]
# web設定
$ vi roles/webtier/tasks/main.yml
↓
---
# tasks file for webtier
- name: install nginx
  yum:
    name: nginx

- name: start/enabled nginx
  systemd:
    name: nginx
    state: started
    enabled: yes

$ ansible-playbook -i inventory.dev web.yml
PLAY RECAP *************************************************************************************************
localhost            : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

# 実装確認
$ curl -I localhost
HTTP/1.1 200 OK
Server: nginx/1.16.1
・・・
```

---

```console:git管理
ansible はコードの塊のため、git で管理するにはもってこいです。
注意点があるとすれば、ansible-galaxy で作成したディレクトリテンプレートの中に空のディレクトリがあります。
※common/files や common/templates

これらのディレクトリはファイルが配置されていないため、明示的に指定しない限りは git の管理外になってしまう場合があります。
git clone 等をした際にいつの間にかなくなっている場合があるので気を付けてください。
```

# まとめ

今回は簡単に ansible role について説明しました。
ルールが決まることでファイルの構成も見やすくなり、管理がし易いかと思います。
ansible では他にも公式に Best Practice がありますので、以下URLを参考にしていただければと思います。
※今回のディレクトリ構成も以下の URL にあるディレクトリ構成を参考にしています。

> Best Practices
> https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html