Ansibleのinventory・role・module設計|現場で崩れない構成管理の基礎

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > Ansibleのinventory・role・module設計|現場で崩れない構成管理の基礎
「Ansibleを使い始めたけれど、ファイルが増えるにつれて管理が混乱してきた」「inventoryをどう分けるべきか、roleはどう設計すればいいかが分からない」
こういった悩みは、Ansibleを実務で使い始めた多くのエンジニアが通る道です。

チュートリアルの段階ではひとつのPlaybookに全部書いても問題ありません。ですが、管理するサーバー台数が増え、環境(dev・stg・prod)が分かれ、チームで共有するようになった瞬間に「なぜこう書いたのか誰も分からない」「本番に間違えた設定が流れた」といった問題が起きます。

この記事では、ansible inventory role module の3軸を軸に、現場で崩れない構成管理の設計方針を解説します。「inventoryのINI形式・YAML形式の使い分け」「ファイルの置き場所の原則」「roleの分割粒度」「moduleの選び方」「ansible-inventoryによる変数の事前検証」まで、実際に手を動かしながら理解できる内容にしています。動作確認環境はRHEL 9.4 / Rocky Linux 9.4、ansible-core 2.15系です。

この記事のポイント

・inventory は INI形式(手軽)とYAML形式(階層記述)から用途に合わせて選択する
・ansible inventory は dev/stg/prod のディレクトリに分割し group_vars で環境差分を自動適用する
・ansible-inventory --list / --graph で変数とグループ構造を実行前に必ず検証する
・role は機能単位(nginx/mariadb)で分割し依存性を meta/main.yml で管理する
・module は「冪等性が保証されるか」を基準に選択。command/shell は最終手段
・本番適用前は --check --diff でドライランし差分を確認してから実行する


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

なぜinventory・role・moduleの設計が構成管理の核心なのか

Ansibleで構成管理を始めると、最初は一枚のPlaybookで十分に感じます。しかし現場では早い段階でこんな問題が起きます。

・本番と開発でIPアドレスが違うのにPlaybookをコピーして運用している
・Nginxの設定とMariaDBの設定が同一ファイルに混在していてどこを直せばいいか分からない
・ を書いてしまい、何度実行しても同じ結果になるか確信が持てない
・hostsファイルのコメントアウトミスで本番に開発用の設定が流れた

これらの問題はツールの問題ではなく、設計の問題です。さらにもう1つ、「Playbookを実行する前に変数が正しく解決されているか確認する方法が分からない」という声も実務の現場でよく聞きます。

inventory・role・moduleの3つを正しく設計し、ansible-inventoryコマンドで事前検証する習慣を身につければ、Ansibleは「何度実行しても同じ状態になる」「環境差分を安全に管理できる」ツールとして機能します。

inventoryファイルの形式:INI形式とYAML形式の書き分け

Ansibleの静的inventoryには、INI形式とYAML形式の2種類があります。どちらも機能は同等ですが、可読性と複雑な構成への対応力が異なります。プロジェクト規模とチームの習熟度に合わせて選択してください。

1. INI形式の基本構造

最もシンプルな形式です。テキストエディタで直感的に編集でき、Ansibleを使い始めて最初に触れる形式でもあります。

# hostsファイル(INI形式の例) [webservers] web01.example.com web02.example.com [dbservers] db01.example.com db02.example.com [all:vars] ansible_user=rocky ansible_ssh_private_key_file=/home/ansible/.ssh/id_ed25519

IPアドレスやホスト名を列挙し、[グループ名]ヘッダでグループを区切ります。[all:vars]セクションに書いた変数は全ホストに適用されます。ただし後述のgroup_vars/host_varsを使う場合、inventoryファイル本体にvarsを書く必要はほとんどなくなります。

複数グループをまとめる親グループは[親グループ名:children]セクションで表現します。

# INI形式でchildrenを使う例(webserversとdbserversをapp_serversにまとめる) [app_servers:children] webservers dbservers

hosts: app_serversとPlaybookで指定すると、webserversとdbserversの全ホストに対して実行されます。

2. YAML形式で書く場合の構造

YAML形式はPlaybookと同じフォーマットで書けるため、グループの階層をより明示的に記述できます。3層以上の複雑な階層や、CI/CDで自動生成する場合に特に有効です。

# inventory.yml(YAML形式の例) all: children: webservers: hosts: web01.example.com: web02.example.com: dbservers: hosts: db01.example.com: app_servers: # 親グループ(webservers + dbservers をまとめる) children: webservers: dbservers:

インデントで階層を表現するため、ネストが深くなると記述量は増えますが、ツールによる自動生成・バリデーションが容易です。hosts:の下にホスト固有の変数を直接書けるため、後述のhost_varsとの併用設計も柔軟に対応できます。

3. どちらを選ぶか——実務での判断基準

INI形式が向くケース:小規模なinventory(20台以下)、チームがAnsible初心者、手軽に始めたい場合
YAML形式が向くケース:複雑なグループ階層(3層以上)、CI/CDで自動生成する場合、Ansible経験者チーム

大規模プロジェクトでは「YAML形式 + group_vars/host_vars分離」が長期保守性の観点から推奨されます。一方、10台以下のシンプルな構成管理ならINI形式で十分です。どちらの形式も共存できるため、移行は段階的に進められます。

inventory設計:環境と個体差を分離する

1. ディレクトリ型inventoryで環境を分ける

ファイル型inventoryの典型的な失敗パターンは、 という1ファイルに開発・本番のホストをコメントで切り替えながら書くことです。コメントアウトのミスが本番事故につながります。

推奨するのは、環境ごとにディレクトリを分けるディレクトリ型inventoryです。dev(開発)・stg(ステージング)・prod(本番)の3環境を分離するのが現場での標準構成です。

# ディレクトリ構造(推奨) inventories/ ├── dev/ │ ├── hosts # 開発環境のホスト定義 │ └── group_vars/ │ └── all.yml # 開発環境共通変数 ├── stg/ │ ├── hosts # ステージング環境のホスト定義 │ └── group_vars/ │ └── all.yml # ステージング環境共通変数 └── prod/ ├── hosts # 本番環境のホスト定義 └── group_vars/ └── all.yml # 本番環境共通変数

# inventories/dev/hosts の例 [web] web01.dev.example.com web02.dev.example.com [db] db01.dev.example.com # 親グループ dev_all が子グループ web / db を持つ宣言(変数の継承に使う) [dev_all:children] web db [all:vars] ansible_user=ec2-user ansible_ssh_private_key_file=~/.ssh/dev_key.pem

# inventories/prod/hosts の例(本番ホストのみ) [web] prod-web01 ansible_host=10.0.1.11 prod-web02 ansible_host=10.0.1.12 [db] prod-db01 ansible_host=10.0.2.11 [all:vars] ansible_user=ec2-user ansible_ssh_private_key_file=~/.ssh/prod_key.pem

重要なポイントは、各inventoryディレクトリ配下に を置くことです。 と指定した場合、Ansibleは を自動的に参照します。実行時に でinventoryを切り替えることで、誤って本番に実行するリスクを大幅に下げられます。事前にssコマンドでSSH 22番ポートの開放状況を確認してから接続設定を進めると安心です。

# 開発環境に対してPlaybookを実行 ansible-playbook -i inventories/dev site.yml # stg環境に対してPlaybookを実行 ansible-playbook -i inventories/stg site.yml # 本番環境への適用前にドライランで差分確認(推奨) ansible-playbook -i inventories/prod site.yml --check --diff # 本番環境に対してPlaybookを実行 ansible-playbook -i inventories/prod site.yml

2. host_varsで個体差を吸収する

同じ役割(webサーバー)でもホストごとにIPアドレスやディスク構成が違うことがあります。これを で管理します。

# host_vars/web01.dev.example.com.yml の例 # サーバー固有の変数をここで定義する nginx_port: 80 data_volume: /dev/xvdb max_conn: 512

# host_vars/web02.dev.example.com.yml の例 nginx_port: 80 data_volume: /dev/xvdc # 別デバイスでも吸収できる max_conn: 256

変数の優先順位(後優先)はAnsibleの重要な仕様です。 は より優先されるため、グループ共通のデフォルト値をgroup_varsに、個体固有の上書き値をhost_varsに書く設計が安定します。

特定ホストだけ例外的な設定を入れたい場合(メンテナンスモードの有効化など)も、host_varsで安全に管理できます。

# inventories/prod/host_vars/prod-web02.yml # prod-web02のみメンテナンスモードを有効にする場合 nginx_maintenance_mode: true maintenance_message: "定期メンテナンス中です(10:00~12:00)"

ただし、host_varsの多用には注意が必要です。「特定ホストだけ設定が違う」という例外が増えると管理が煩雑になります。IPアドレスや役割(primary/standby)など真にそのホスト固有の情報だけをhost_varsに書き、環境差分はgroup_varsで吸収するのが鉄則です。

3. group_varsの設計例|dev・prod別の変数定義

inventoryディレクトリを分けると、group_varsのスコープも自動的に分離されます。 で実行した場合は が、 で実行した場合は が参照されます。Playbookは1本のまま維持できるため、環境間での変更漏れも起きません。

# inventories/dev/group_vars/all.yml env: dev app_port: 8080 nginx_worker_processes: 1 log_level: debug allow_debug_endpoints: true db_host: 192.168.10.21 db_name: myapp_dev ansible_user: ansible ntp_server: ntp.nict.jp

# inventories/prod/group_vars/all.yml env: prod app_port: 80 nginx_worker_processes: auto log_level: warn allow_debug_endpoints: false db_host: 10.0.2.11 db_name: myapp_prod ansible_user: ansible ntp_server: ntp.nict.jp

変数を定義しておくと、Jinja2テンプレートや 条件で環境を判別できます。また や のように全環境共通のデフォルト値もall.ymlに置いておくと、inventory切り替えのたびに同じ設定を書き直す手間が省けます。

グループ別の変数ファイルも活用すると、webグループ専用の設定を独立したファイルで管理できます。

# inventories/dev/group_vars/webservers.yml(webグループ専用) http_port: 80 https_port: 443 webserver_package: nginx max_connections: 512

# tasks/main.yml の例 — env変数で環境ごとに条件分岐する - name: デバッグエンドポイントを有効化する(dev環境のみ) ansible.builtin.template: src: debug_routes.conf.j2 dest: /etc/nginx/conf.d/debug.conf when: env == "dev" - name: worker_processesを設定する ansible.builtin.lineinfile: path: /etc/nginx/nginx.conf regexp: '^'worker_processes' line: "worker_processes {{ nginx_worker_processes }};"

4. ansible-inventoryで変数解決を事前検証する

inventoryを設計したら、Playbookを実行する前に コマンドで変数が正しく解決されているかを確認してください。これを習慣にするだけで、「思っていた値と違った」「本番に開発用の値が流れた」という実行時エラーの大半を未然に防げます。

# 本番inventoryの全変数をJSON形式で確認する ansible-inventory -i inventories/prod --list # 特定ホストの変数だけを絞り込んで確認する ansible-inventory -i inventories/prod --host prod-web01 # グループ階層をツリー形式で視覚的に確認する ansible-inventory -i inventories/prod --graph

オプションは、グループの親子関係とホストの所属を一目で確認できます。@ungroupedに意図しないホストが入っていないかの確認にも使えます。ungroupedのホストはgroup_varsが適用されないため、設定漏れの原因になります。

# ansible-inventory --graph の出力例 $ ansible-inventory -i inventories/prod --graph @all: |--@web: | |--prod-web01 | |--prod-web02 |--@db: | |--prod-db01 |--@ungrouped:

実際の出力例(prod-web01のhostvarsを抜粋):

{ "_meta": { "hostvars": { "prod-web01": { "ansible_host": "10.0.1.11", "ansible_user": "ansible", "app_port": 80, "db_host": "10.0.2.11", "env": "prod", "log_level": "warn", "nginx_worker_processes": "auto", "ntp_server": "ntp.nict.jp" } } }, "web": { "hosts": ["prod-web01", "prod-web02"] } }

この出力で と が正しく反映されていることを目視確認します。group_vars/all.ymlから来た や と、prod専用のall.ymlから来た や が1つのホストにマージされて表示されているのが分かります。

本番実行前に素早く全ホストの環境を一覧確認したい場合は、以下のワンライナーが便利です。

# 全ホストのenv変数を一覧表示して環境を目視確認する ansible-inventory -i inventories/prod --list | python3 -c " import json, sys inv = json.load(sys.stdin) for host, vars in inv['_meta']['hostvars'].items(): print(host, '->', vars.get('env', '未設定')) " # 出力例(全ホストが prod を指していることを確認する) # prod-web01 -> prod # prod-web02 -> prod # prod-db01 -> prod

5. prod専用のシークレット管理(Ansible Vault)

本番環境のDBパスワードなど機密情報は、group_vars内にAnsible Vaultで暗号化したファイルを置きます。inventoryディレクトリが分かれているため、devのシークレットとprodのシークレットが完全に分離されます。

# prod専用のVaultファイルを新規作成する ansible-vault create inventories/prod/group_vars/vault.yml # ファイル内に記述する変数(暗号化前の平文イメージ): # db_password: "ProdP@ssw0rd" # app_secret_key: "prod-secret-key-xxxxx" # Vaultパスワードファイルを使ってPlaybookを実行する ansible-playbook -i inventories/prod --vault-password-file ~/.vault_pass.txt site.yml

Vaultファイルはgitにコミットしても安全です(暗号化されているため)。ただし (パスワードファイル)は に必ず含め、リポジトリに含めないよう注意してください。

6. 動的inventoryで台数が増えても崩れない

AWSやAzureのようにインスタンスが動的に増減する環境では、静的なhostsファイルは追いつきません。Ansibleには動的inventory用のプラグインが用意されています。

# inventories/dev/aws_ec2.yml(動的inventory設定例) plugin: amazon.aws.aws_ec2 regions: - ap-northeast-1 filters: "tag:Env": dev "tag:Role": web keyed_groups: - key: tags.Role prefix: role # 実行時のコマンド ansible-playbook -i inventories/dev/aws_ec2.yml site.yml

タグ(Env=dev, Role=web)でホストが自動グルーピングされるため、インスタンスを追加・削除してもinventoryファイルの編集は不要になります。実際に検証機(t3.micro)で試した出力例は以下の通りです。

# ansible-inventory -i inventories/dev/aws_ec2.yml --list の出力例(抜粋) { "_meta": { "hostvars": { "10.0.1.23": { "ansible_host": "10.0.1.23", "tags": {"Env": "dev", "Role": "web"} } } }, "role_web": { "hosts": ["10.0.1.23", "10.0.1.24"] } }

複数環境を安全に実行する

1. ansible-playbook -i で環境を指定して実行する

環境の切り替えは オプションでinventoryディレクトリを指定するだけです。Playbookは共通の を使い回せます。

# dev環境へのPlaybook実行 ansible-playbook -i inventories/dev site.yml # stg環境へのPlaybook実行 ansible-playbook -i inventories/stg site.yml # prod環境への適用前にcheckモードで差分確認(必須) ansible-playbook -i inventories/prod --check --diff site.yml # prod環境への本番適用 ansible-playbook -i inventories/prod site.yml

本番(prod)への適用前は必ず でドライランを行い、変更内容を確認してから実行するのが現場の鉄則です。以下は実際のドライラン出力例(prod-web01 への適用前確認)です。

$ ansible-playbook -i inventories/prod --check --diff site.yml PLAY [web] ****************************************** TASK [nginx : Deploy nginx.conf from template] ****** --- before: /etc/nginx/nginx.conf +++ after: /home/ansible/.ansible/tmp/ansible-tmp-xxx/source @@ -3,7 +3,7 @@ -worker_processes 1; +worker_processes auto; PLAY RECAP ****************************************** prod-web01 : ok=4 changed=1 unreachable=0 failed=0 prod-web02 : ok=4 changed=1 unreachable=0 failed=0

この出力で、 がprod用の に正しく切り替わっていることが確認できます。dev環境で を設定していた値がprod用に上書きされており、inventoryの分離が正しく機能しています。

2. Makefileでラップして誤実行を防ぐ

オプションの指定忘れは誤実行の原因になります。Makefileでコマンドをラップすると、環境名をターゲット名として指定するだけで実行できます。

# Makefile(タブでインデントすること) .PHONY: dev stg check-prod prod dev: ansible-playbook -i inventories/dev site.yml stg: ansible-playbook -i inventories/stg site.yml check-prod: ansible-playbook -i inventories/prod --check --diff site.yml prod: check-prod @echo "prod本番適用を実行します。本当によいですか? [y/N]" @read ans && [ "651618{ans}" = "y" ] && ansible-playbook -i inventories/prod site.yml || echo "中止しました。"

/ / とターゲットを指定するだけでよく、長いコマンドをそのまま入力するより誤操作が減ります。 ターゲットは に依存しているため、ドライランなしに本番適用するルートが物理的になくなります。

role設計:機能単位で分割し依存を管理する

1. roleのディレクトリ構造を理解する

roleはAnsibleが定める規約ディレクトリを持ちます。 で雛形を生成するのが最も確実です。

# role雛形の生成 ansible-galaxy role init nginx # 生成されるディレクトリ構造 nginx/ ├── defaults/ │ └── main.yml # デフォルト変数(最低優先度) ├── handlers/ │ └── main.yml # handler(サービス再起動など) ├── tasks/ │ └── main.yml # タスク本体 ├── templates/ │ └── nginx.conf.j2 # Jinja2テンプレート ├── vars/ │ └── main.yml # role内固定変数(高優先度) ├── files/ # 静的ファイル ├── meta/ │ └── main.yml # roleの依存関係定義 └── tests/ └── test.yml

2. roleの分割粒度:「1 role = 1サービス」が基準

roleを分割する粒度で悩む人は多いです。現場で安定している基準は「1 role = 1サービス(またはデーモン)」です。

nginx role:Nginxのインストール・設定・起動
mariadb role:MariaDBのインストール・初期化・設定
php-fpm role:PHP-FPMのインストール・設定
common role:全サーバー共通の設定(SELinux・ファイアウォール・ユーザー作成等)

# site.yml(roleを束ねるエントリポイント) --- - name: Configure web servers hosts: web roles: - common - nginx - php-fpm - name: Configure DB servers hosts: db roles: - common - mariadb

3. defaults/main.ymlで可変値を外に出す

role内にIPアドレスやポート番号をハードコードするのは最も避けるべきパターンです。 にデフォルト値を定義し、inventoryの や から上書きできる設計にします。

# nginx/defaults/main.yml --- nginx_port: 80 nginx_worker_processes: auto nginx_access_log: /var/log/nginx/access.log nginx_error_log: /var/log/nginx/error.log nginx_max_body_size: 10m

# nginx/templates/nginx.conf.j2(Jinja2テンプレートで変数を展開) worker_processes {{ nginx_worker_processes }}; http { access_log {{ nginx_access_log }}; error_log {{ nginx_error_log }}; server { listen {{ nginx_port }}; client_max_body_size {{ nginx_max_body_size }}; } }

4. handlerで「変更があった時だけ再起動」を実現する

handlerはAnsibleの重要な機能です。「設定ファイルを変更したときだけNginxをreloadする」という冪等(べきとう)な動作を実装できます。

# nginx/tasks/main.yml --- - name: Install nginx ansible.builtin.dnf: name: nginx state: present - name: Deploy nginx.conf ansible.builtin.template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf mode: '0644' notify: Reload nginx # 変更があった場合のみhandlerを呼ぶ - name: Ensure nginx is started and enabled ansible.builtin.service: name: nginx state: started enabled: true

# nginx/handlers/main.yml --- - name: Reload nginx ansible.builtin.service: name: nginx state: reloaded

で指定したhandler名は、Playbook実行の最後にまとめて一度だけ実行されます。同じtaskが10回変更を通知しても、再起動は1回だけ行われる仕組みです。

5. roleの依存関係はmeta/main.ymlで宣言する

roleは roleが先にインストールされている必要があるケースがあります。こういった依存関係は に明示します。

# php-fpm/meta/main.yml --- galaxy_info: role_name: php-fpm author: yourname min_ansible_version: "2.15" dependencies: - role: nginx

module設計:冪等性を基準に選ぶ

1. 「冪等性が保証されるmoduleか」を判断軸にする

Ansibleのmoduleを選ぶ基準は明確です。冪等性(何度実行しても同じ結果になる性質)が保証されているかどうかです。

やりたいこと 推奨module 冪等性
パッケージをインストール ansible.builtin.dnf / ansible.builtin.apt あり(state: present/absent)
設定ファイルを配置 ansible.builtin.template / ansible.builtin.copy あり(変更なしはスキップ)
サービスを起動・有効化 ansible.builtin.service あり(状態を確認して実行)
ユーザーを作成 ansible.builtin.user あり(存在確認後に作成)
ファイルのパーミッション設定 ansible.builtin.file あり(変更なしはスキップ)
設定ファイルの一部を書き換え ansible.builtin.lineinfile あり(マッチした行のみ変更)
任意のシェルコマンドを実行 ansible.builtin.command / ansible.builtin.shell なし(最終手段)

2. command/shellを使う前に確認すべきこと

モジュールや モジュールを使いたくなったとき、まず自問してください。「このコマンドで実現したいことに、専用のAnsible moduleはないか?」

例えば、 と書きたい場合は moduleの で代替できます。 と書きたい場合は moduleで代替できます。

どうしても / を使う必要がある場合は、 または パラメータで冪等性を自前実装します。

# commandで冪等性を確保する例 # creates: に指定したファイルが存在する場合はスキップされる - name: Initialize MariaDB data directory ansible.builtin.command: cmd: mysql_install_db --user=mysql --basedir=/usr creates: /var/lib/mysql/mysql # このディレクトリがあればスキップ

3. FQCNでmodule名を書く(Ansible 2.10以降の推奨形式)

Ansibleのmodule名はコレクション管理(FQCN:Fully Qualified Collection Name)の記法で書くことが推奨されています。

旧来の書き方: / /
推奨する書き方: / /

FQCNで書くと、どのコレクションのmoduleを使っているかが明確になり、コレクション更新時の動作変化を追いやすくなります。チームで共有するPlaybookほどFQCN表記を徹底してください。

トラブルシュート:よくある設計ミスと対処法

「No hosts matched」が出る

Playbookの に指定したグループがinventoryに定義されていない場合に発生します。 でグループ名の綴りを確認してください。大文字・小文字の違いやtypoが最多の原因です。

# グループ階層を確認して「No hosts matched」の原因を特定する $ ansible-inventory -i inventories/dev --graph @all: |--@web: | |--web01.dev.example.com |--@ungrouped: | |--db01.dev.example.com # ← ungroupedに入っているホストを発見

上記のように にホストが入っている場合、そのホストはどのグループにも属していません。inventoryのhostsファイルでグループを正しく定義してください。

「group_varsが効かない」→配置場所を確認する

inventoryディレクトリを で指定した場合、Ansibleはそのディレクトリ内の を参照します。プロジェクトルート直下の は参照されません(inventoryファイルを直接指定する場合とは挙動が異なります)。

# NG: プロジェクトルートにまとめて置くパターン project/ ├── group_vars/ │ └── all.yml # どの環境で実行しても同じ値が使われる └── inventories/ ├── dev/hosts └── prod/hosts # OK: inventoryディレクトリ配下に置く project/ └── inventories/ ├── dev/ │ └── group_vars/ │ └── all.yml # dev実行時のみ参照される └── prod/ └── group_vars/ └── all.yml # prod実行時のみ参照される

「変数が上書きされない」→優先順位を確認する

Ansibleの変数優先順位は22段階あります。現場でよく起きる混乱は、(高優先度)と (低優先度)の違いを理解していないことです。

・ に書いた値 → inventoryの や で上書き可能(推奨)
・ に書いた値 → inventoryの変数より優先されるため、外から上書きできない

外から変えてほしい値は必ず に書き、roleの内部固定値のみ に書くのが鉄則です。

「変数ファイルが読まれない」→YAMLの構文エラーを確認する

group_vars/host_varsのYAMLファイルにインデントエラーや特殊文字の扱いミスがあると、変数ファイル全体が読み込まれません。 を実行してエラーが出るか、期待した変数が表示されない場合はYAML構文を疑ってください。

# YAML構文チェック(python3が使える環境で実行する) $ python3 -c "import yaml; yaml.safe_load(open('inventories/prod/group_vars/all.yml'))" # エラーがなければ何も出力されない。エラーがある場合は行番号付きで表示される # 例: yaml.scanner.ScannerError: mapping values are not allowed here # in "inventories/prod/group_vars/all.yml", line 5, column 12

YAML構文エラーの多くは、コロン直後のスペース不足( ではなく が正しい)や、文字列値をクォートせずに特殊文字( や など)を含めていることが原因です。修正後は必ず で変数が正しく表示されることを確認してください。

「Playbook再実行でエラーが出る」→冪等性の欠如を疑う

再実行でエラーになるタスクは、冪等性がない処理が含まれている可能性があります。

# エラーが出たときのデバッグ手順 # --check でドライランして変更予定タスクを確認する ansible-playbook -i inventories/dev site.yml --check --diff # 特定のtagを付けたタスクだけ実行して切り分ける ansible-playbook -i inventories/dev site.yml --tags "nginx" # 実行結果の詳細を表示する(-vvv で最大詳細) ansible-playbook -i inventories/dev site.yml -v

「roleが見つからない」→roles_pathの設定を確認する

roleのディレクトリが 以外にある場合、 で を明示します。

# ansible.cfg の設定例 [defaults] inventory = inventories/dev roles_path = roles:~/.ansible/roles remote_user = ec2-user host_key_checking = False # 検証機では無効化することが多い [privilege_escalation] become = True become_method = sudo

の に開発環境を指定しておくと便利ですが、本番実行時に を省略した場合の誤実行リスクがあります。コメントアウトして常に で明示指定する運用が安全です。

本記事のまとめ

inventory・role・module設計の要点をまとめます。

設計対象 原則 よくある失敗
inventoryの形式 小規模はINI形式、複雑な階層や自動生成はYAML形式を選択 規模に関係なくINI形式にこだわり、階層管理が破綻する
inventory dev/stg/prodでディレクトリを分ける hostsファイルをコメントで切り替える
group_vars 各inventoryディレクトリ配下に置き環境差分を自動適用 プロジェクトルートにまとめて置き環境が分離されない
host_vars IPアドレス・ロールなど真に固有の値だけをhost_varsで管理 全サーバーを同じ変数で一律設定する
変数の事前検証 ansible-inventory --list / --graph で解決値・グループ構造をPlaybook実行前に確認 実行してみるまで変数が正しいか確認しない
シークレット管理 prod専用のVaultファイルでDBパスワードを暗号化 平文パスワードをgroup_varsに直書きする
prod実行 --check --diffでドライランしてから本番適用 差分確認なしにprodへ直接実行する
role分割 1 role = 1サービスが基準 1 roleに全設定を詰め込む
defaults 外から変える値はdefaults、固定値はvarsに vars/main.ymlに全変数を書いて上書きできない
module選択 冪等性があるmoduleを優先し、command/shellは最終手段 shellで全処理を書いて再実行でエラーになる
構成管理が「崩れない」かどうかは、最初の設計で決まります。
inventoryで環境を分離し、ansible-inventoryで変数を事前検証し、roleで機能を分割し、冪等性のあるmoduleを選ぶ。この4つの習慣を押さえるだけで、Ansibleは「1台のサーバー設定ツール」から「何台でも同じ状態を保証できる構成管理基盤」に変わります。

Ansibleのinventory・role・module設計を実際に手を動かしながら体系的に身につけたい方は、ぜひ詳細をご覧ください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

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

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

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

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

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

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

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

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

この記事を書いた人

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

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

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