色んなプロジェクトを跨いだAnsibleのベストプラクティスについて改めて考えてみる

Ansibleを使い始めて数年立ちましたが未だにベストプラクティスをどうすべきか日々迷走しております。
というのもミニマムで使用する分には管理も含め大変使いやすいのですが、いくつものプロジェクトやサーバなど数が増えていくと色んなplaybookが出来上がってしまいます。

そのため現在抱えている問題点などを挙げ自分なりのベストプラクティスを探っていきたいと考えております。

# ベストプラクティスにたどり着かない理由
- 環境構築する環境がたくさんある
- ミドルウェアのバージョンが新規サーバの構築時期によって違ってくる
- 見返す度に過去の自分の書き方に不満が出てくる
- 無理に共通化すると管理が大変
- 各プロジェクトの文化の違い
 - ディレクトリの場所
 - 書き方
- yumインストールじゃなくてソースインストール
- CentOS6,7問題
- shell,command問題


## まずは基本構成

Ansibleの[ベストプラクティス](http://docs.ansible.com/ansible/latest/playbooks_best_practices.html)によると
大体こういった分け方が一般的ものだと考えております。
###インベントリファイル
 ・環境毎にサーバや特定の変数を管理する場所
※変数はインベントリ内のファイルに含めたり別の場所に切り出したりもする

```bash
例:
.
|-- stage
|   |-- group_vars/
|   `-- hosts
|-- prod
|   |-- group_vars/
|   `-- hosts
`-- vars　　　
    |-- common_grouplist.yml
    |-- common_userlist.yml
    `-- common_yumlist.yml
```
## プレイブック
・サーバの役割毎にロールをまとめたプレイブック

```bash:
例：
.
|-- pcweb-server.yml
|-- spweb-server.yml
`-- db-serever.yml
```

## ロール

- 実際にサーバ内で設定するコマンド類をまとめたもの(tasks)
- サーバの再起動コマンドの呼び出し(handlers)
- rpmファイルや圧縮ファイル(files)、ミドルウェア設定ファイル(templates)の格納なども可能
  - filesとtemplatesの格納場所の分け方の基準※個人的な見解です
     - files：vimでの変更が可能なもの
     - templates：vimでの変更が不可能なもの

```bash
例：
・
roles

example/
|-- files
|   |-- example.tar.gz
|    `-- example_devel.rpm
|-- handlers
|   `-- main.yml
|-- tasks
|   |-- example.yml
|   `-- main.yml
`-- templates
    |--pcweb 
    |   `-- example.conf
    |-- spweb
    |   `-- example.conf
    `-- common
        `-- common.conf
```

## まとめると
上記構成を集めたものが以下のplaybookとなっていきます。
こう見ると一つの階層の中にロール、インベントリ、プレイブックが混ざっているのがわかりますね。初めて触る方が迷うのはまずこちらの切り分けではないでしょうか。


```bash
例:
.
| ※インベントリ
|-- stage
|   |-- group_vars/
|    `- hosts
|-- prod
|   |-- group_vars/
|    `- hosts
|-- vars　　　
|   |-- common_grouplist.yml
|   |-- common_userlist.yml
|    `- common_yumlist.yml
| ※プレイブック
|-- pcweb-server.yml
|-- spweb-server.yml
|-- db-serever.yml
| ※ロール
 `-- roles
     |--  base/
      `-- example/
          |-- files
          |    |-- example.tar.gz
          |     `-- example_devel.rpm
          |-- handlers/
          |     `-- main.yml
          |-- tasks
          |    |-- example.yml
          |     `- main.yml
           `-- templates
             |-- pcweb 
             |     `-- example.conf
             |-- spweb
             |     `-- example.conf
              `- common
                   `-- common.conf
```

## 時間がたってから思ったこと

### 長くansibleを使っていると反映先のサーバにも色んな変化が訪れてきます。

- 脆弱性のためのバージョンアップによるアップデート
- 仕様改善などにより共通項目にしていたロールが共有できなくなる
- クラウド移行によるレシピ見直し
- サーバのスケールアウトに伴う不具合(rpmの前のバージョンがインストールできないなど)
- 共通項目の中でサーバー毎での設定項目が増え管理が大変になる
- 別用途のサーバのミドルウェアを違うバージョンで立てる必要がありroleが複雑になる
- ansible管理外の項目が変更されていて冪統制が取れなくなっている
- ソースインストールだとconfigureやmake install コマンドなどがどうしてもshellやcommandモジュールを使わないといけなくなり、冪統制ではなくなってしまうし確認コマンドなど余計な処理を挟まなければいけない
    - できればyumを入れたいが諸々の事情でソースインストールを行うことが多いのが現状

### さらにロールを使いまわしたい場合

例えば別サービスのサーバを構築する必要がでてきて必要なroleがansibleにある場合、できればroleを使いまわしたいですよね。
しかしここにもやはりいろんな弊害が出てくる可能性があります。

- 反映先のサーバがオンプレだったり仮想だったりクラウドだったりrolesだったりして入っていないパッケージがあり追加が必要
- そもそもOSがCent6からCent7に代わっていてymlの中身を変更しないと使えない
- 実は前に作ったサーバの固有の設定が存在していていらないものが入ってしまっている

### 最近思うベストプラクティス

ansibleやchefなどでいくら自動構築ができるとはいえ、やはり構築は構築。
roleの使いまわしなどをして初期構築各サーバなどは一発でplaybookが成功とはいかないことが多いです。
そのためやはり新しく構築するサーバは改めてroleを見直し日々修正を行う必要があります。

そのため最近では以下点を留意してplaybookを作る等に心がけております。

- インストールと設定変更のymlを分ける
- ミドルウェア毎でroleを分ける場合はバージョンまで記載しておく
- OSの共通設定においてもOS名まで記載しでわかりやすくしておく
  - そもそもCentOS6と7でsysytemdとserviceのモジュール自体も違うためその場合はyml毎で分けif関数でサーバごとの呼び出し先を変えるなどの工夫も必要
- タグは必ずつけ、うまく使っていく

```shell
構成例:
.
| ※インベントリ
|-- stage
|   |-- group_vars/
|    `- hosts
|-- prod
|   |-- group_vars/
|    `- hosts
|-- vars　　　
|   |-- common_grouplist.yml
|   |-- common_userlist.yml
|    `- common_yumlist.yml
| ※プレイブック
|-- pcweb-server.yml
|-- spweb-server.yml
|-- db-serever.yml
| ※ロール
 `-- roles
     |--  base_centos7/
     |--  base_centos6/
     |--  example2.x/
      `-- example1.x/
          |-- files
          |    |-- example.tar.gz
          |     `-- example_devel.rpm
          |-- handlers/
          |     `-- main.yml
          |-- tasks
          |    |-- example_install.yml
          |    |-- example_setting.yml
          |     `- main.yml
           `-- templates
             |-- pcweb 
             |     `-- example.conf
             |-- spweb
             |     `-- example.conf
              `- common
                   `-- common.conf
```

というわけでどこまで汎用的にplaybookを使っていくかというのはこれからも課題になってくると思っています。
そこまでしてansibleを使う必要があるのかという点については、やはり多人数での管理の上でバージョン管理を含め大切なことではないかと思っていますし初期構築さえうまくやればもちろん慣れは必要ですが、運用に乗った後での変更などについてはansibleを使うメリットは大きいです。

この記事内でまだまだ書ききれないことも多々ありますので時間や機会があればもう少し奥深く触れていきたいと思いつつ、皆さんのansibleのうまい使い方などありましたら教えていただけると幸いです。