AnsibleのマルチステージInventory設計|staging・productionのgroup_vars分離とホストパターンによる環境切り替え実践

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > AnsibleのマルチステージInventory設計|staging・productionのgroup_vars分離とホストパターンによる環境切り替え実践
「Playbookはできたのに、stagingで確認してから本番に入れようとして、うっかり本番のInventoryを指定してしまった」——Ansibleを使い始めて規模が大きくなると、こういったヒューマンエラーが現実のリスクになります。

「stagingと本番で同じplaybookを使いたいが、接続先や設定値は当然違う。どう管理すればいい?」——答えはInventoryの設計にあります。環境分離はAnsibleが最も得意とする分野であり、正しいディレクトリ構成とgroup_varsの使い方を知れば、誤適用を構造的に防げます。

この記事では、staging・productionを安全に分離するInventoryのディレクトリ設計、group_varsの環境別配置パターン、そして--limitと--check・--diffによる本番昇格前確認フローを解説します。

この記事のポイント

・stagingとproductionは別ディレクトリのInventoryファイルで物理的に分離する
・共通変数はroleのdefaults、環境固有値は各環境のgroup_vars/配下に配置する
・ansible-playbook -i inventories/staging のように実行時に環境を明示指定する
・本番適用前は--check --diffで変更差分を確認してから昇格させる


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜAnsibleの環境分離は設計で解くべき問題なのか

Ansibleを使い始めた段階では、1つのInventoryファイルに全ホストを書いて、コメントアウトや手動切り替えで環境を分けることが多いです。しかし、台数が増えてチームで使うようになると、この方式は破綻します。

誤適用リスク: コメントアウトを忘れると本番ホストに直接実行される
変数の衝突: staging用の設定値と本番用の設定値が同じファイルに混在して管理できなくなる
レビューが難しい: 「このPlaybook実行は本当にstagingのみに当たっているか」をコードレビューで確認できない

Ansibleは最初からマルチ環境設計を前提としたInventoryの仕組みを持っています。「後から分ける」ではなく「最初から分ける」設計を採用することで、これらのリスクを構造的に排除できます。

マルチステージInventoryのディレクトリ構成

1. 推奨ディレクトリ構造(inventories分離型)

Ansibleの公式Best Practicesでは、環境ごとにInventoryディレクトリを分けることが推奨されています。以下が基本的な構成です。

# プロジェクトのディレクトリ構造 project/ ├── inventories/ │ ├── staging/ │ │ ├── hosts # stagingホスト定義 │ │ └── group_vars/ │ │ ├── all.yml # staging全体の共通変数 │ │ └── webservers.yml # stagingのwebグループ変数 │ └── production/ │ ├── hosts # productionホスト定義 │ └── group_vars/ │ ├── all.yml # production全体の共通変数 │ └── webservers.yml # productionのwebグループ変数 ├── roles/ │ └── httpd/ │ ├── tasks/main.yml │ └── defaults/main.yml # デフォルト値(最低優先度) └── site.yml # 共通のPlaybookエントリーポイント

この構成のポイントはroleは共通、Inventoryは環境ごとに分ける点です。「staging用のrole」と「production用のrole」を別々に作る必要はありません。実行時に渡すInventoryを変えるだけで、同じroleが環境に応じた設定で動きます。

2. stagingとproductionのhostsファイルの書き方

各環境のhostsファイルには、その環境のホストだけを記載します。

# inventories/staging/hosts(INI形式) [webservers] stg-web01.example.com stg-web02.example.com [dbservers] stg-db01.example.com [all:vars] ansible_user=ansible ansible_ssh_private_key_file=~/.ssh/id_ed25519

# inventories/production/hosts(INI形式) [webservers] web01.example.com web02.example.com web03.example.com [dbservers] db01.example.com db02.example.com # productionは冗長構成 [all:vars] ansible_user=ansible ansible_ssh_private_key_file=~/.ssh/id_ed25519

hostsファイルの[all:vars]には、SSH接続に関する共通オプションを置くのが一般的です。接続情報(ユーザー名・鍵ファイル)が両環境で共通の場合は、プロジェクト直下のansible.cfgに書く方法もあります。

group_varsで環境ごとの変数を分離する

1. roleのdefaultsに共通値、環境別group_varsに固有値

roleのdefaults/main.ymlに「上書き前提のデフォルト値」を設定し、各環境のgroup_varsでそれを上書きする設計が最も整理しやすい方法です。

# roles/httpd/defaults/main.yml(最低優先度・上書き前提) httpd_max_workers: 50 httpd_log_level: warn app_environment: undefined # 必ず環境ごとに上書きさせる # inventories/staging/group_vars/all.yml(staging固有) httpd_max_workers: 10 # リソース節約 httpd_log_level: debug # デバッグ用に詳細ログ app_environment: staging # inventories/production/group_vars/all.yml(production固有) httpd_max_workers: 200 httpd_log_level: warn app_environment: production

roleはhttpd_max_workersという変数名だけを知っていれば動きます。「stagingは10、productionは200」という実際の値は、Inventoryのgroup_varsが担います。roleのdefaults/main.ymlにapp_environment: undefinedのようなプレースホルダーを置いておくと、Inventoryを指定し忘れて実行したときに気づきやすくなります。

2. Ansible Vaultで機密値を環境別に分離する

DBパスワードやAPIキーなどの機密値は、group_vars内でVault暗号化ファイルを使って管理します。

# inventories/production/group_vars/dbservers/ ディレクトリ # ├── vars.yml ← 平文の変数(DB名など)Gitにコミット可 # └── vault.yml ← ansible-vault encrypt で暗号化済み # vault.yml の内容(暗号化前) db_password: "P@ssw0rd!SecureValue" # 暗号化コマンド ansible-vault encrypt inventories/production/group_vars/dbservers/vault.yml # 実行時にVaultパスワードを渡す ansible-playbook site.yml -i inventories/production --vault-password-file ~/.vault_pass

vars.ymlとvault.ymlをグループ変数ディレクトリ内に共存させる「vars/vault分離パターン」はAnsible公式が推奨する設計です。平文のvars.ymlはGitにコミットし、vault.ymlはVault暗号化した状態でコミットすることで、機密値をリポジトリで安全に管理できます。

--limitとホストパターンで実行環境を指定する

1. 基本的な環境指定コマンド

Inventoryを分けた後は、実行時に-iオプションでInventoryディレクトリを指定するだけです。

# stagingに対して実行 ansible-playbook site.yml -i inventories/staging # productionに対して実行 ansible-playbook site.yml -i inventories/production # productionのwebserversグループのみ ansible-playbook site.yml -i inventories/production --limit webservers # 特定ホストのみ(ピンポイント適用) ansible-playbook site.yml -i inventories/production --limit web01.example.com

-i inventories/staging のようにディレクトリを指定すると、その中のhostsファイルとgroup_varsディレクトリが自動的に読み込まれます。これが環境切り替えの仕組みです。

2. 誤爆防止の2ステップ確認フロー

本番適用前に実行対象ホストを事前確認するのが現場の基本手順です。

# Step 1: 対象ホスト一覧を確認(playbookは実行しない) ansible-playbook site.yml -i inventories/production --list-hosts # 出力例 # play #1 (webservers): webservers # pattern: ['webservers'] # hosts (3): # web01.example.com # web02.example.com # web03.example.com # Step 2: 問題なければ実際に実行する ansible-playbook site.yml -i inventories/production

--list-hostsで対象ホストを目視確認してから実行するフローをチームの標準手順にしておくと、「想定外のホストに当たっていた」というミスをほぼ防げます。

ステージング検証→本番昇格のフロー設計

1. --check --diffで変更内容を事前確認する

本番昇格前に--check(ドライラン)と--diff(差分表示)を組み合わせて実行します。

# productionに対してドライラン(実際には何も変更しない) ansible-playbook site.yml -i inventories/production --check --diff # 出力例(設定ファイルに変更がある場合) # TASK [httpd : update httpd.conf] ********************* # --- before: /etc/httpd/conf/httpd.conf # +++ after: /etc/httpd/conf/httpd.conf # @@ -150,7 +150,7 @@ # -MaxRequestWorkers 150 # +MaxRequestWorkers 200 # changed: [web01.example.com]

--checkは実際の変更を行わず「実行したらどう変わるか」だけを表示します。--diffを加えると、設定ファイルの変更前後をdiff形式で確認できます。本番昇格のフローは以下の3ステップで標準化しておくのが現場では一般的です。

Step 1: stagingで-i inventories/stagingを実行して動作確認する
Step 2: productionで--check --diffを実行して変更差分をレビューする
Step 3: 差分に問題がなければ--checkを外してproductionへ本適用する

2. serial: 1とmax_fail_percentageで段階適用する

複数台のproductionサーバーへの適用時は、全台同時ではなく段階的に適用するのが安全です。

# site.yml(productionのWebサーバーへの段階適用) --- - name: webサーバー設定の段階適用 hosts: webservers serial: 1 # 1台ずつ適用 max_fail_percentage: 0 # 1台でも失敗したら全体を停止 roles: - httpd # 台数が多い場合は段階的に増やす serial: - 1 # まず1台で確認 - 30% # 次に30%(複数台) - 100% # 問題なければ残り全台

serial: 1で1台ずつ適用することで、万が一エラーが起きた際の影響を最小限に抑えられます。max_fail_percentage: 0を設定しておくと、1台でも失敗した時点でPlay全体が停止するため、連鎖的な障害を防げます。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

よくある設計ミスとその対処

1. 変数の上書き順が分からなくなる

Ansibleの変数優先順位(22段階)を整理できていないと、「どこで設定した値が使われているのかわからない」という状態になります。役割の原則は次の通りです。

roleのdefaults/main.yml: 上書き前提のデフォルト値(最低優先度)
group_vars/all.yml: 全グループの共通値
group_vars/グループ名.yml: 特定グループ固有の値
host_vars/ホスト名.yml: 特定ホストのみの値(さらに高優先度)

「何でもgroup_vars/all.ymlに書く」と、環境が増えた時に管理が難しくなります。roleのデフォルトを低く設定し、環境のgroup_varsで上書きする一方向の流れを保つことが、長期運用の鍵です。

2. stagingとproductionで別々のroleを作ってしまう

「stagingはhttpd_stagingロール、productionはhttpd_productionロール」のように環境ごとのroleを作ると、ロジックの重複が発生します。変更時に両方のroleを修正し忘れるミスが生まれます。正しい設計は「roleは1つ、変数で環境を切り替える」です。

# roles/httpd/tasks/main.yml(環境変数で分岐する例) - name: ログローテーション設定 template: src: logrotate.conf.j2 dest: /etc/logrotate.d/httpd # テンプレート内で {{ app_environment }} を使って期間を分岐 # staging: rotate 2, production: rotate 7

3. ansible.cfgにInventoryパスをハードコードしてしまう

# NG: ansible.cfgにInventoryを固定すると常にproductionを向く [defaults] inventory = inventories/production # -i を忘れると本番直撃

ansible.cfgにInventoryパスを固定すると、-i指定を省略した実行が常にproductionに当たります。Inventoryの指定は必ずコマンドラインの-iで行うことをチームのルールにしてください。Makefileのラッパーに-i inventories/${ENV}を組み込む方法も有効です。

Ansibleマルチ環境設計のまとめ

staging・productionのInventory分離設計をまとめます。
設計要素 推奨アプローチ
環境分離の単位 inventories/staging/ と inventories/production/ の別ディレクトリ
共通設定の管理 roleのdefaults/main.ymlにデフォルト、group_varsで環境別に上書き
機密値の管理 環境別group_vars内のvault.ymlをansible-vault encryptで保護
実行時の環境指定 ansible-playbook -i inventories/staging(-iを必ず指定)
対象ホストの事前確認 --list-hostsで一覧確認後に本実行
本番昇格前の確認 --check --diffで差分確認 → 問題なければ本適用
複数台への段階適用 serial: 1とmax_fail_percentage: 0で安全適用
Inventoryの設計は「後から直せる」と思われがちですが、台数が増えチームが大きくなると修正コストが急増します。Ansibleを使い始めた段階で環境分離の設計を確立しておくことが、長期的な安全運用の土台になります。

Ansibleをより実践的に学びたい方は、LinuxMaster.JPのAnsible専門ページもあわせてご覧ください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。