なりゆき
ここしばらくChefを使っていたけど、台数が増えてくると実行がだんだん面倒になってきたのでpull型のツールだけじゃなくてpush型のツールも使ってみなきゃなあ、と思っていたところ、Ansibleが目に入ったので使ってみることにした。
Ansibleを触っての最初の目標は、chefのenvironmentに当たるもの、つまり環境によって設定内容の切り替えを行う方法を見つけることとした。
Ansibleでenvironmentは環境変数を示す予約語のようなのでgoogleに聞くのはちょっと難易度が高かったのだが、なんとか以下のようなページを見つけることができた。
- http://qiita.com/yteraoka/items/5ed2bddefff32e1b9faf
- http://tdoc.info/blog/2014/05/30/ansible_target_switching.html
もっとも、これらはAnsibleをある程度触るまでは内容を理解できなかったのだが、内容を理解した時、以下のような考えに至った。
- インベントリファイルを環境ごとに分ける、というのは素晴らしいので即採用。
- しかしインベントリファイルに配列型の変数を作ることはできなさそうに見える(し、できたとしてもそういうのはインベントリファイルでなくyamlに外出しした方がきれいだよね)。
- ダイナミックインベントリにすれば配列型の変数も作れそうだが、ダイナミックインベントリ書くのめんどいし、実行しないと内容がわからないのがちょっと。リポジトリは見えるけど実行できない、しても意味ない、という状況はままある。
- 環境名を実行時に入力する、というのは入力ミスが怖いな。2つの環境を誤って同じ設定内容にしてしまったらIPアドレスかぶり(特にありそうなのが負荷分散する時のVirtual IP address)とかでこれまで動いていたのがどっちも動かない、とかなるからね。
- インベントリファイルに環境名を与えた変数だけ書いておく、という案も考えたがインベントリファイルをコピーして環境名だけ後回しにしていて結局直し忘れた、はありそうなシナリオでやっぱり怖い。
で、考えた結果。
インベントリファイル名をそのまま(か、ちょっと加工して)環境名にするのがいいよね、という結論に。
そしてこうなった
site.ymlの最初に以下を追加する。
- hosts: all
gather_facts: no
tasks:
- group_by: key={{ inventory_file | basename | regex_replace('^hosts-', '') }}
changed_when: False
インベントリファイル名がhosts-env1, hosts-env2, hosts-env3, …だったらgroup_varsディレクトリ以下にenv1.yml, env2.yml, env3.yml, …を作ってここに環境ごとの設定値を変数に書いていく。
2014-07-23追記: 実際に何かが変更されるわけではないのにchanged判定されるのは良くないので「changed_when: False」を追加。
2014-07-30追記: ソースを読んだところ、group_varsの中の各ファイルの変数の優先順位は、(group_byで追加されたグループ).ymlはすべてのホストに適用されるall.ymlより高く、(インベントリで定義されたグループ).ymlより低いようだ。
さいごに
まあしかし、何やってもコピーした後の書き直し忘れには対応できないよね。
ゆめゆめチェックを怠るなかれ。