このエントリーをはてなブックマークに追加

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と変数を使った方が後々便利になりますが、こうしなくては、ということはありません。使いたい環境に適した方法を取ればいいと思います。