Ansible: 複数のステージに対応する際のポイント

この記事で考察すること

production、staging の2つの環境があるとします。

やりたいことは、Ansible の一つのソースで、両方に対応できるようにすること。
つまり、次のようにコマンドで環境を使い分けて実行できるようにします。

# production を対象にする
$ ansible-playbook -i production_hosts site.yml

# staging を対象にする
$ ansible-playbook -i staging_hosts site.yml

今回作成する Ansible ソースのポイント

ポイントを簡単に箇条書きにします。

  • ステージごとにインベントリファイルを用意(staging_hosts, production_hosts)。このファイル中で、変数 stage にステージ名を設定します。
  • web, db という粒度でプレイブックを作成(web.yml, db.yml)。これらのプレイブックから、ステージに応じたロール、変数ファイルを呼び出します。

ディレクトリ構成

|-- production_hosts
|-- staging_hosts
|
|-- site.yml
|
|-- web.yml
|-- db.yml
|
|-- roles
|   |-- staging_pretask/
|   |-- db/
|   `-- web/
|
`-- vars
    |-- common.yml
    |-- production
    |     |-- web.yml
    |     |-- db.yml
    `-- staging
          |-- web.yml
          |-- db.yml

inventory

ステージごとにインベントリファイルを用意します。
特徴的なのは、ここでステージの環境変数を設定しています。

production_hosts

[web]
web.prd.example.com

[db]
db.prd.example.com

[all:vars]
stage=production

staging_hosts

[web]
web.stg.example.com

[db]
db.stg.example.com

[all:vars]
stage=staging

Playbook

site.yml

web, db のプレイブックを import するだけの内容です。(余談ですが、include はバージョン 2.8 で無くなります。)

- import_playbook: web.yml
- import_playbook: db.yml

上位プレイブックで環境の制御

web, db という粒度でプレイブックを作成します。この中で必要なロール、変数を設定します。
ポイントは、vars_files でステージに対応した変数を読み込んでいること。

Tips
  • tags をロールごとに設定しておくと、プレイブック実行時に指定ロールのみの処理を実行可能です。
  • 特定ステージでのみ実行したいロールがある場合は、when を使ってステージを指定します。
web.yml
- hosts: web
  become: yes
  vars_files:
    - vars/{{ stage }}/web.yml
    - vars/common.yml
  roles:
    - { role: staging_pretask, tags: staging_pretask, when: stage == 'staging' }
    - { role: common,      tags: common }
    - { role: web,         tags: web }

db.yml も同じような考え方で作成します。

タスク単位で、環境ごとに動作を変えたい場合

片方の環境でのみ実行したい処理は、when 句によってステージを指定します。

roles/common/tasks/main.yml
- name: xxxxxx
  ...
  when:
   - stage == "production"

プレイブック実行

コマンド

-i でステージング、プロダクションを切り替えます。

# production を対象とする。
$ ansible-playbook -i production_hosts site.yml

# staging を対象とする。
$ ansible-playbook -i staging_hosts site.yml

# staging を対象とする。web サーバのみ。
$ ansible-playbook -i staging_hosts web.yml

# staging を対象とする。web サーバを対象に、common ロールのみ。
$ ansible-playbook -i staging_hosts web.yml --tags common

補足: なぜ group_vars を避けたか

Ansible がよしなに必要な変数ファイルを読み込んでくれるのですが、意図どおり読み込まれないことがありました。それならば、vars_files で自分が必要なものを明示的に呼びだそうと考えました。

参考

Ansible公式: Best Practices

Ansible inventoryパターン

Qiita:Ansibleのインベントリファイルでステージを切り替える

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.