ansibleで実行対象を切り替える方法
本番環境、検証環境、開発環境など、複数の環境を持っており、それごとにサーバーや設定が異なる、ということはよくあると思います。
ansibleで、これらの対象を切り替える方法は複数ありますので、それを紹介したいと思います。
サーバーが異なるだけで、設定が同じ場合
この場合は、inventoryファイルでグループを分けて切りかえればいいと思います。
[stg:children]
stg_Web
stg_DB
[prod:children]
prod_Web
prod_DB
[stg_web]
stg_web_01
[stg_DB]
stg_db_01
[prod_web]
prod_web_01
[prod_DB]
prod_db_01
のように書いておき、
% ansible-playbook -l prod something.yml
という感じで-lでグループを切り替えればいいでしょう。上記例のように、グループは入れ子構造にもできますので、一つの環境に複数のグループあっても問題ありません。
実行taskを切り替える
最後のtaskを一つだけ切り替えたい、ということもあるかと思います。その場合、whenを使って切り替えられます。
- name: 本番環境用ファイルをコピー
copy: src=config.ini.prod dest=/etc/config.ini
when: target == 'prod'
- name: 検証環境用ファイルをコピー
copy: src=config.ini.stg dest=/etc/config.ini
when: target == 'stg'
としておけば、先ほどと同様
% ansible-playbook -l prod something.yml
で、実行対象に応じたファイルがコピーされます。
ここで target には指定した対象が入ります。
タグで切り替えたい
ansibleには--tagsオプションで実行時にタグをつけることができます。
- name: 本番環境用ファイルをコピー
copy: src=config.ini.prod dest=/etc/config.ini
tags:
- prod
- name: 検証環境用ファイルをコピー
copy: src=config.ini.stg dest=/etc/config.ini
tags:
- stg
としておけば、
% ansible-playbook -l stg -t prod something.yml
と実行すると、inventoryだけではできなかった、例えば検証環境に本番環境用のファイルをコピーする事ができます。まあ、たまには意味があるかもしれません。
includeでまとめて切り替える
これまでの例はtask単位でtagをつける必要がありました。でも、切り替えたいタスクが多くなると大変になります。
異なるtaskを切り出しておいて、
- include: prod.yml tags=prod
- include: stg.yml tags=stg
や
- include: prod.yml when: target == 'prod'
- include: stg.yml when: target == 'stg'
のように、includeでまとめて切り替えることもできます。
roleで切り替える
ちょっと大きくなってくるとroleに切り分ける方が見通しがよくなりますので、roleに切っている人もおられるかと思います。
roleにもwhenを適用できますので、
roles:
- { role: prod, when: target == 'prod' }
- { role: stg, when: target == 'stg' }
とすることも可能です。が、これではprodとstgという二つのroleを作成する必要があるので通常は変数を定義しておくでしょう。ついでにtagで切り替えられるようにしてみます。
roles:
- { role: something, port:80, tags: ['prod'] }
- { role: something, port:8080, tags: ['stg'] }
varsを切り替える
そもそも変数に切り出すならvarsを入れ替えるだけでいいですよね。でも、 vars にはwhenなどは書けません。
ではどうするかというと、include_vars モジュールを使います。
tasks:
- include_vars: vars_prod.yml
when: target == "prod"
- include_vars: vars_stg.yml
when: target == "stg"
- debug: msg=" port is {{ port }}"
ノート
1.6.2で試したところtagsと組み合わせるとその後のtaskが実行されないような気がします。ちょっとあとで追ってみます。
これとvars_promptを組み合わせると
---
- hosts: all
gather_facts: no
vars_prompt:
env: "What is your target env?"
tasks:
- include_vars: vars_prod.yml
when: env == "prod"
- include_vars: vars_stg.yml
when: env == "stg"
- debug: msg="port is {{ port }}"
"What is your target env?" とplaybook実行時に聞いてきますので、入力すれば指定したvarsファイル読み込まれます。え、あんまり意味ないですかそうですか…
まとめ
対象を変えたい場合はよくあると思います。その時に使える方法をいくつか紹介しました。
複数の方法がありますが、特にこれでなくてはいけない、ということはありません。強いて言えばroleと変数を使った方が後々便利になりますが、こうしなくては、ということはありません。使いたい環境に適した方法を取ればいいと思います。