茶太郎の日記

クラウドやコンテナ辺り中心に技術をやっていきます

Ansibleのベストプラクティスに学ぶ

しばらく更新が開いてしまいました。

今年の前半はDockerやKubernetesに追いかけていたのですが、
近頃は仕事でAWS*1とAnsibleを中心に使っているため、関心もそちらに寄ってきています。

今回はAnsibleのベストプラクティスについて勉強したので書いていきます。


Ansibleのベストプラクティスとは

「ベストプラクティスとは大きく出たな 」
「そもそも何のベストプラクティスなんだろう?」
とお思いの方もいるかも知れませんが、 Ansibleでは公式でベストプラクティスを公開しています。
Best Practices — Ansible Documentation

こちらを見てみると分かる通り、ファイルやディレクトリの構成のようです。
Ansibleではご存知の通り様々なファイルが使用されます。
大きく分けるとプレイブックとインベントリの2つが中心ですが、細かい挙動などをファイル毎に分けていくとかなりの数に分類されます。
それをうまく活用しつつ、キレイに配置しよう、というのがベストプラクティスと呼ばれるものだと思います。

公式サイトでは2種類のベストプラクティスを紹介しています。

ベストプラクティスな構成を作ってみる

ドキュメントを読んでいても(英語だし)いまいちピンとこなかったので、
ベストプラクティスを真似た構成を作ってみました。
手前味噌ですが、練習用も兼ねてリポジトリを作っています。 github.com ちなみに今の仕事でも商用/検証環境が別れているのでAlternative Directory Layoutのほうをベースにしています。

インベントリの構成

ディレクトリ構成は以下のようになっています。

.
├── inventory
│   ├── production
│   │   ├── group_vars
│   │   │   ├── all.yml
│   │   │   ├── app.yml
│   │   │   ├── db.yml
│   │   │   └── web.yml
│   │   ├── hosts
│   │   └── host_vars
│   │       └── webserver2.yml
│   └── staging
│       ├── group_vars
│       │   ├── all.yml
│       │   ├── app.yml
│       │   ├── db.yml
│       │   └── web.yml
│       ├── hosts
│       └── host_vars

インベントリファイルの内容は以下のようです。

$ cat inventory/production/hosts
[web]
webserver1
webserver2

[app]
appserver

[db]
dbserver

変数はすべてgroup_vars, host_varsに記載しています。
ProductionとStagingで同じようなグループ構成にしつつ
IPアドレスやパラメータの違いを*_varsで吸収させることで、
共通のPlaybookを使うことができるのが良さですね。

各種の変数には強弱というか優先順位があります。
Variables — Ansible Documentation

思っている以上に数があって覚えるのは大変そうですし、よく使うのはこの辺りです。*2

弱い
* role defaults
* inventory group_vars/all
* inventory group_vars/
* inventory host_vars/

* include_vars
強い

role defaultsは最も弱い変数なのでデフォルト値として、他の変数に上書きされたりするんですね。
でも、バージョンアップの対応として高いバージョンをhost_vars→group_varsと段階的にバージョンアップしていき、
確証が取れたら最終的にdefaultsのバージョンを上げる、というような使い方もできます。 include_varsなどの強力な変数はほぼ上書きできないので、もはや定数みたいな扱いですね。

こういった変数の構成はプログラミングのようでInfrastructure as Codeしている感があって好きですね。

ロールの構成

ロールを作っているうちに「大した仕事させない割にはすごいファイル数だな…」と感じました。
Tipsですが、ロールを作るのにいちいち特定のディレクトリ名を作るのが面倒だと思い調べたところ、
ansible-galaxy init というコマンドを知りました。

$ ansible-galaxy init common/hoge --offline
- common/hoge was created successfully
$ tree common/hoge/
common/hoge/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 8 files

上のように、ロールで使われるディレクトリを1コマンドで一気に作ってくれます。
(デフォルトではAnsible Galaxyのサイトを一度見に行くようなので--offlineを付けることでローカル実行で早く終わるようです)

ちなみにリポジトリの方はまだ挙動を知る段階なので見やすさ重視で不要なディレクトリ/ファイルは削除してます。
でもtestsとか気になるのでいずれ触ってみたいと思います。*3

最後に

今回Ansible公式のベストプラクティスを紹介しましたが、
Qiitaなどで見ると俺的ベストプラクティスがいくつか紹介されています。
環境によっても使い方は様々だと思うので、実環境での使いやすさや好みでベストな構成を考えるのも良いのかもしれません。
私も「これだ!」という構成を見つけるまでは公式のベストプラクティスをベースで作っていきたいと思います。*4


*1:AWSはSAAがそろそろ失効してしまうのでSAPに昇格して更新しようと模試を受けたらボロボロだったので、そちらは同じモノを更新か、他のアソシエイトのものに挑戦しようかと思ってます。

*2:他のもののうまい使い方があれば教えてください!

*3:testsを活用されていたら教えていただけると嬉しいです

*4:ちなみに今回このテーマを取り上げた理由は、今の仕事の構成がアンチパターンだから。。。