Differentiate environments with ansible

ansibleでdigitaloceanの構成管理をしている。このときvagrantを使って試しながら本番に適用しているのだが、本番にしか適用したくない設定(mackerel-agentのインストールとか)、開発環境にのみ適用したい設定が出てきた。

それっぽいワードで調べてみたら、group_varsやhost_varsとwhenステートメントを組み合わせる方法が手軽そうだった。

リンクを参考に以下のような感じでインベントリを設定した。

development

[ponpokopon-vm]
192.168.33.10 ansible_ssh_user=vagrant ansible_ssh_private_key_file=.vagrant/machines/default/virtualbox/private_key

[all:vars]
stage=development  

production

[ponpokopon-production]
ponpokopon.me ansible_ssh_user=username ansible_ssh_private_key_file=~/.ssh/id_rsa

[all:vars]
stage=production  

プレイブックでは以下のようにwhenステートメントを使いgroup_varsの内容で条件分岐することで、適用先を変えることができる。

- name: mackerel-agent is installed
  yum: pkg=mackerel-agent state=installed
  when: stage == "production"
  tags: mackerel

group_varsについて

インベントリとかグループとかまだあまり慣れてないので整理。

ansibleはインベントリという単位でプレイブック適用先を管理している。

インベントリ1(productionとか)

[グループ1(baseとかwebとか)]
ホスト1(192.168.1.10とか)
ホスト2

[グループ2]
ホスト1
ホスト3

インベントリ2

[グループ1]
ホスト4
ホスト5

[グループ2]
ホスト4
ホスト6

この時、グループで共通の変数を定義することができる。これがgroup_vars。

[グループ1(baseとかwebとか)]
ホスト1(192.168.1.10とか)
ホスト2

[グループ2]
ホスト1
ホスト3

[グループ1:vars]
group1_var1=hogehoge  
group1_var2=piyopiyo  

そしてこの変数は定義したグループに対してプレイブックが実行された際に参照することができる。ただし、この書き方では環境を示す変数を定義したい場合、グループごとに設定をしないとダメなのでグループが複数ある場合ちょっとめんどくさい。

[グループ1(baseとかwebとか)]
ホスト1(192.168.1.10とか)
ホスト2

[グループ2]
ホスト1
ホスト3

[グループ1:vars]
stage=production

[グループ2:vars]
stage=production  

そこでall:varsを使う。all:varsは全てのグループに適用される変数なので、結果的にそのインベントリ全体に適用される変数になる。

[グループ1(baseとかwebとか)]
ホスト1(192.168.1.10とか)
ホスト2

[グループ2]
ホスト1
ホスト3

[all:vars]
stage=production  

感想

chefの場合は環境ごとの設定はenvironment/{production.json,development.json}、グループはroles/{web.json,db.json}、ホストはnodes/{192.168.1.10.json,192.168.1.11.json}みたいにバラバラのファイルとして存在しているが、ansibleの場合インベントリでまとめて定義されるという違い。

この辺の違いはjsonが辞書型のような形式で、yamlがインデントで構造を表現していることに起因している…のかな?