「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で変更差分を確認してから昇格させる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ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エントリーポイント
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
[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
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
--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全体が停止するため、連鎖的な障害を防げます。
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で安全適用 |
Ansibleをより実践的に学びたい方は、LinuxMaster.JPのAnsible専門ページもあわせてご覧ください。
Ansible実践ハンズオンの詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Ansibleのデバッグ設計入門|-vvvフラグ・debugモジュール・assertで実行時エラーを体系的に切り分ける方法
- この記事の属するカテゴリ:Ansibleへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます