そんな運用になっていないでしょうか。サーバー台数が増えてdev・staging・productionと環境が分かれてくると、構成管理ツールを導入したのに管理ファイルが増殖するという状態に陥りがちです。
この記事では、Ansibleのインベントリを「役割軸」と「環境軸」の2次元で設計するアプローチを解説します。group_varsとhost_varsのディレクトリ配置まで含めた設計パターンを習得すれば、1つのPlaybookでdev・staging・productionの差分を吸収できる構成が実現できます。
この記事のポイント
・Ansibleインベントリは「役割グループ(何者か)」と「環境グループ(どこに属するか)」の2軸で設計すると再利用性が高い
・group_vars/all が全ホスト共通の変数、group_vars/{group_name} が各グループ固有の変数を担う
・host_vars はサーバー固有の値(IPアドレス・固有設定)にだけ使い、変数の散在を防ぐ
・インベントリ設計の失敗は後からのリファクタリングが困難なため、最初の設計方針が重要
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜインベントリ設計でPlaybookの再利用性が決まるのか
Ansibleのインベントリは、単なる「接続先ホストの一覧」ではありません。インベントリの設計次第で、同じPlaybookが複数環境で使い回せるかどうかが決まります。たとえば、次のような状態になっていないでしょうか。
・playbook_dev.yml、playbook_staging.yml、playbook_production.yml の3ファイルが存在する
・vars:ブロックの中にIPアドレスやドメイン名を直書きしている
・ホストを追加するたびに複数のPlaybookを修正する必要がある
これはインベントリの設計が不十分な状態です。Ansibleが本来提供する「1つのPlaybookを複数ホストに適用する」という設計思想が活かせていません。
インベントリを適切に設計すると、Playbook側は「どのグループに何を配るか」という宣言だけになります。環境差分はインベントリのグループ変数が吸収してくれるため、Playbook本体を環境ごとにコピーする必要がなくなります。
シェルスクリプトでサーバー構築を管理していた時代と比べると、Ansibleのインベントリは「どのサーバーに・何を・どんな設定値で配るか」を構造化して表現できます。この構造化こそが、規模が拡大しても管理を破綻させない基盤になります。
インベントリの2軸設計とは
インベントリの設計には「役割軸」と「環境軸」の2つの視点があります。この2軸を組み合わせることで、整理されたインベントリ構造が実現できます。1. 役割軸——サーバーの「担当業務」でグループ化する
役割軸は、サーバーが何をするかでグループを定義します。一般的な3層Webシステムであれば、次のような役割グループが考えられます。・webservers:NginxやApacheを稼働させるWebサーバー群
・appservers:アプリケーションサーバー群(PHPやNode.js等)
・dbservers:MySQL・PostgreSQL等のデータベースサーバー群
・cacheservers:RedisやMemcachedを稼働させるキャッシュサーバー群
役割グループを定義しておくと、Playbook側で「webserversグループに対してNginxをセットアップするroleを適用する」「dbserversグループに対してMySQL設定roleを適用する」という形で役割ごとにroleを割り当てられます。これがPlaybookの再利用性の基盤です。
役割軸の命名には複数形の名詞(webservers、dbservers)を使う慣習が広く使われています。1台か複数台かに関係なく同じグループ名を使えるため、サーバー台数が増えても定義を変更せずに済みます。
2. 環境軸——dev/staging/prodで同じroleを再利用する
環境軸は、サーバーがどの環境に属するかでグループを定義します。・dev:開発環境のサーバー群
・staging:検証環境のサーバー群
・production:本番環境のサーバー群
環境グループを定義すると、接続先IPアドレスやドメイン名・証明書パス・ログレベルといった環境ごとに異なる値を、グループ変数として集中管理できます。Playbook本体には「差分をどこで定義するか」という知識を持たせる必要がなくなります。
2軸設計の肝は「ホストを2つのグループに同時所属させる」ことです。たとえばweb01というサーバーは、webservers(役割軸)にもproduction(環境軸)にも所属します。Ansibleはこの2グループの変数を自動的にマージして適用するため、「Webサーバーとしての設定」と「本番環境としての設定」の両方がweb01に届きます。
この設計により、role自体はwebserversとしての振る舞い(Nginxの設定構造)だけを知っていればよく、「本番ではどのドメインか」「開発ではどのDBに接続するか」といった環境差分は一切持たなくて済みます。role設計の再利用性が大幅に向上するのはこのためです。
group_varsディレクトリで差分を吸収する設計
2軸設計の効果を最大化するのが、group_varsディレクトリです。ファイル形式(group_vars/webservers.yml)でも機能しますが、ディレクトリ形式(group_vars/webservers/main.yml)にしておくと複数ファイルで変数を分割管理できるため、本番運用ではディレクトリ形式を推奨します。1. group_vars/allで全ホスト共通の基本設定を管理する
group_vars/all(またはgroup_vars/all/main.yml)には、すべてのホストに共通して適用したい変数を定義します。# group_vars/all/main.yml --- ansible_user: ansible ansible_ssh_private_key_file: ~/.ssh/ansible_rsa ntp_server: ntp.example.com log_timezone: Asia/Tokyo admin_email: ops-alert@example.com
2. グループ固有ディレクトリで環境差分を定義する
役割グループと環境グループ、それぞれに対応するgroup_varsを用意します。# group_vars/webservers/main.yml(役割グループの変数) --- nginx_worker_processes: auto nginx_keepalive_timeout: 65 http_port: 80 https_port: 443 document_root: /var/www/html
# group_vars/production/main.yml(本番環境グループの変数) --- db_host: db-prod.internal.example.com app_domain: www.example.com ssl_cert_path: /etc/ssl/certs/prod.crt log_level: warn deploy_env: production
# group_vars/dev/main.yml(開発環境グループの変数) --- db_host: db-dev.internal.example.local app_domain: dev.example.local ssl_cert_path: /etc/ssl/certs/dev.crt log_level: debug deploy_env: development
{{ db_host }}という変数参照を書くだけでよく、実行時に対象ホストが所属するグループの変数が自動解決されます。役割グループの変数(nginx設定)と環境グループの変数(DB接続先)が別ファイルで管理されるため、役割の変更と環境の変更が互いに影響しません。
3. host_varsはサーバー固有値の最終手段
host_varsは、特定ホストにしか適用しない値(固有のIPアドレス、クラスタIDなど)に限定して使います。# host_vars/web01.example.com/main.yml --- ansible_host: 192.168.10.11 server_id: web01
Ansibleの変数優先順位はhost_varsがgroup_varsより高いため、万が一グループ変数とhost_varsで同名の変数が存在した場合はhost_varsの値が勝ちます。この動作を意識した上で、「group_varsで定義した値をホスト固有で上書きする」用途にhost_varsを使うことも有効ですが、多用すると管理が複雑になるため注意が必要です。
実践:3層WebシステムのInventory設計例
これまでの設計をまとめた実践例を示します。Web・App・DBの3層構成で、dev・production(本番)の2環境を管理するケースです。1. ディレクトリ構造
inventory/ ├── hosts.yml # ホスト一覧とグループ定義 ├── group_vars/ │ ├── all/ │ │ └── main.yml # 全ホスト共通変数 │ ├── webservers/ │ │ └── main.yml # webservers役割変数 │ ├── appservers/ │ │ └── main.yml # appservers役割変数 │ ├── dbservers/ │ │ └── main.yml # dbservers役割変数 │ ├── production/ │ │ └── main.yml # production環境変数 │ └── dev/ │ └── main.yml # dev環境変数 └── host_vars/ ├── web01.example.com/ │ └── main.yml # web01固有変数(ansible_host等) └── db01.example.com/ └── main.yml # db01固有変数(ansible_host等)
2. hostsファイルの記述(YAML形式)
# inventory/hosts.yml --- all: children: # 役割グループ webservers: hosts: web01.example.com: web02.example.com: appservers: hosts: app01.example.com: dbservers: hosts: db01.example.com: # 環境グループ production: hosts: web01.example.com: web02.example.com: app01.example.com: db01.example.com: dev: hosts: web-dev.example.local: app-dev.example.local: db-dev.example.local:
3. ansible-inventoryコマンドで設計を確認する
インベントリの設計が意図通りに機能しているかは、ansible-inventoryコマンドで確認できます。$ ansible-inventory -i inventory/hosts.yml --host web01.example.com { "ansible_host": "192.168.10.11", "ansible_ssh_private_key_file": "~/.ssh/ansible_rsa", "ansible_user": "ansible", "app_domain": "www.example.com", "db_host": "db-prod.internal.example.com", "deploy_env": "production", "document_root": "/var/www/html", "http_port": 80, "https_port": 443, "log_level": "warn", "log_timezone": "Asia/Tokyo", "nginx_keepalive_timeout": 65, "nginx_worker_processes": "auto", "ntp_server": "ntp.example.com", "server_id": "web01", "ssl_cert_path": "/etc/ssl/certs/prod.crt" }
この出力が「意図した変数が正しく解決されているか」の確認手段として有効です。Playbook適用前にansible-inventoryコマンドで変数の解決状態を確認する習慣をつけると、変数設計の誤りを早期に発見できます。
Ansibleを使った構成管理の設計パターンをより深く学びたい方は、Ansibleで始める構成管理入門も参考にしてください。
インベントリ設計でよくあるトラブルと対処パターン
インベントリ設計の経験が浅いうちによく発生するトラブルと、その原因・対処を整理します。トラブル1:PlaybookのvarsセクションにIPアドレスを直書きする
PlaybookのvarsセクションやタスクにIPアドレスやドメイン名を直書きすると、本番環境と開発環境で別々のPlaybookが必要になります。これらの値はgroup_vars/productionやgroup_vars/devに移すことで、1つのPlaybookで両環境に対応できます。変数を「Playbookが持つべきか、インベントリが持つべきか」の判断基準は「環境によって値が変わるか」です。環境で変わる値はインベントリのgroup_varsに置きます。
トラブル2:環境ごとに別のhostsファイルを用意する
inventory/hosts_dev.yml、inventory/hosts_prod.ymlのように環境別のhostsファイルを分けると管理ファイルが増殖します。2軸設計では1つのhosts.ymlに全ホストを定義し、所属グループで環境を表現します。Ansibleコマンドの
-l production(--limitオプション)でグループを絞り込めば、実行対象の環境を安全に制御できます。【注意】本番環境への誤適用を防ぐために
本番環境にPlaybookを適用する際は、必ず
-l productionでグループを明示するか、--checkオプションで事前にドライランを実行することを強く推奨します。環境グループの指定が漏れると、全ホストにPlaybookが適用されるリスクがあります。トラブル3:すべてをhost_varsで管理する
「ホスト固有の値だから」とhost_varsを多用すると、50台あれば50ファイルを管理する状態になります。共通パターンのある値(ログレベル、NTPサーバー、タイムゾーン等)はgroup_varsで管理し、本当にサーバーごとに異なる値(固有ID、固有IPアドレス等)だけをhost_varsに書く習慣が重要です。
トラブル4:役割軸と環境軸を1つのグループ名に混ぜる
prod_webserversというグループ名は「本番の」と「Webサーバー」が混在しています。このグループ命名では、group_varsで「本番の変数」と「Webサーバーの変数」を分離できなくなります。役割軸はwebservers、環境軸はproductionと分けて、ホストを両方に所属させる設計が原則です。グループ名を変えずに変数を分離できるのが2軸設計の強みです。
トラブル5:childrenグループを深くネストしすぎる
グループ階層を深くしすぎると、変数の継承関係が追いにくくなります。役割軸と環境軸の2層(all→group→host)で表現できる構成であれば、それ以上のネストは原則として不要です。複雑なグループ階層を作る前に「group_vars/allとグループ変数の組み合わせで同じことができないか」を確認しましょう。
本記事のまとめ
Ansibleのインベントリ2軸設計について整理します。| 設計要素 | 目的 | 配置例 |
|---|---|---|
| 役割グループ | サーバーの担当業務で分類 | webservers、dbservers |
| 環境グループ | 環境差分の吸収 | production、staging、dev |
| group_vars/all | 全ホスト共通変数の集約 | ansible_user、ntp_server |
| group_vars/{グループ名} | グループ固有変数の管理 | nginx設定値、DB接続先 |
| host_vars/{ホスト名} | サーバー固有値のみ | ansible_host、server_id |
シェルスクリプトからAnsibleへ移行するときも、まずインベントリの設計から始めることを推奨します。後から変数の置き場所を整理する(Playbook直書きからgroup_varsへの移行)のは、ホスト数・Playbook数が増えるほど工数がかかります。最初の設計で「役割軸と環境軸の2軸で管理する」という方針を固めておくことが、長期的な運用のしやすさにつながります。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、Ansibleをはじめとする構成管理の考え方を実際のサーバー環境で学べる機会をご用意しています。インベントリ設計からrole分割・本番適用まで、現役サーバーエンジニアによるハンズオン解説でじっくり習得できます。
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AnsibleでAWSのセキュリティグループを管理する方法|ec2_security_groupモジュールとrole設計でネットワークポリシーを自動化する
- この記事の属するカテゴリ:Ansibleへ戻る

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