AnsibleのMagic Variables設計入門|hostvars・groups・inventory_hostnameで動的なPlaybookを作る方法

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > AnsibleのMagic Variables設計入門|hostvars・groups・inventory_hostnameで動的なPlaybookを作る方法
「このPlaybook、サーバーが増えるたびに書き直さないといけない……」そんな悩みはありませんか?
Ansibleで複数ホストを管理するとき、ホスト名でファイル名を変えたい、他のサーバーのIPをconfigに埋め込みたい、特定グループにだけ条件分岐したい。こうした要求に応えるのが Magic Variables(特殊変数)です。

この記事では、AnsibleのMagic Variablesの概念から、hostvarsgroupsinventory_hostname を使った実践的な設計パターンまで体系的に解説します。
「なんとなく動いている」Playbookを「意図を持って設計した」Playbookに変えるための設計入門として読んでください。

この記事のポイント

・Magic VariablesはAnsibleが自動で設定する組み込み変数で上書き不可
・inventory_hostnameでホスト名を、hostvarsで他ホストの変数を参照できる
・groupsとgroup_namesでグループ条件分岐やクロスホスト設定が実現できる
・gather_facts完了後に利用できる変数と事前利用可能な変数を区別して設計する


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

なぜMagic Variablesが必要なのか|静的なPlaybookの限界

Ansibleを使い始めると、まずシンプルなPlaybookを書きます。しかしホスト数が増え、環境が複雑になるにつれ、次のような壁にぶつかります。

・ホストごとに異なるファイル名を生成したい
・WebサーバーのconfigにデータベースサーバーのIPを自動的に埋め込みたい
・「本番グループのホストだけ」にある処理を実行したい

こうした要求に答えるために vars でいちいち変数を定義していると、「変数の定義がPlaybookとInventoryの両方に散らばる」「ホストを追加するたびに複数箇所を書き換える」という問題が起きます。

Magic Variablesを使えば、Ansibleが実行時に自動で設定する情報をそのまま活用できます。ホスト名・グループ情報・他ホストの変数といった「Ansibleがすでに知っていること」を、Playbookの中で再利用する設計が可能になります。

Magic Variablesの全体マップ|種類と役割の整理

Magic Variablesは大きく3種類に分類できます。

変数名 種別 内容
inventory_hostname ホスト識別 Inventoryに記述したホスト名(FQDNまたは短縮名)
inventory_hostname_short ホスト識別 最初のドットより前の短縮ホスト名
ansible_host ホスト識別 実際の接続先IP/ホスト名(ansible_host変数で指定した値)
hostvars クロスホスト参照 全ホストの変数を辞書形式で参照できる
groups グループ情報 グループ名→ホスト名リストの辞書
group_names グループ情報 現在のホストが属するグループ名のリスト
play_hosts 実行状態 現在のPlayで対象となるホスト名のリスト
ansible_version 実行環境 Ansibleのバージョン情報の辞書
playbook_dir パス Playbookファイルが置かれているディレクトリの絶対パス
inventory_dir パス Inventoryファイルが置かれているディレクトリの絶対パス
これらはすべて Ansibleが自動設定する 変数です。Playbookの vars セクションやInventoryで同名の変数を定義すると予期しない動作の原因になるため、上書きは厳禁です。

inventory_hostnameとansible_hostで自ホスト情報を扱う

Magic Variablesの中で最もよく使うのが inventory_hostname です。Inventoryに記述したホスト名がそのまま入っています。

以下のInventoryがある場合を例に説明します。

# hosts.ini [webservers] web01.example.com web02.example.com [dbservers] db01.example.com ansible_host=192.168.1.101

web01.example.com で実行されるタスクでは、inventory_hostnameweb01.example.cominventory_hostname_shortweb01 になります。

1. ホスト名を使ったファイル生成パターン

ホストごとにユニークなファイル名を生成したい場合、inventory_hostname を直接使えます。

- name: ホスト固有の設定ファイルを配置する template: src: nginx.conf.j2 dest: /etc/nginx/conf.d/{{ inventory_hostname_short }}.conf owner: root mode: '0644'

これだけで web01.conf / web02.conf のようなホスト固有ファイルが生成されます。varshostname: web01 と手書きする必要はありません。

2. ansible_hostとinventory_hostnameの違い

混乱しやすいポイントです。inventory_hostname はInventoryの記述名、ansible_host は実際のSSH接続先です。

たとえば db01.example.com ansible_host=192.168.1.101 と定義されている場合:

inventory_hostnamedb01.example.com(Inventoryでの論理名)
ansible_host192.168.1.101(SSHの実際の接続先)

ログファイル名にはInventoryの論理名、実際の疎通確認にはansible_hostを使うというように、用途に合わせて使い分けます。

hostvarsで他ホストの変数を参照する設計パターン

hostvars は、Ansible実行中のすべてのホストの変数を辞書で持ちます。これを使うと、WebサーバーのPlaybookにDBサーバーのIPを自動埋め込みといったクロスホスト参照が実現できます。

1. 他ホストのIPアドレスをconfigに埋め込む

Webサーバーのconfigにデータベースサーバーの接続先を設定する典型的なユースケースです。

# templates/app.conf.j2 [database] host = {{ hostvars['db01.example.com']['ansible_host'] }} port = 3306

Inventoryで db01.example.com ansible_host=192.168.1.101 と定義されていれば、host = 192.168.1.101 が自動生成されます。DBサーバーを移設してInventoryを変えるだけで全Webサーバーの設定が更新されます。

2. gather_factsとhostvarsの関係

重要な設計上の注意点があります。hostvars に他ホストのfacts(ansible_default_ipv4 等)を含めるには、そのホストでfactsが収集済みである必要があります。

# Play 1: DBサーバーのfactsを先に収集する(tasks不要・gather_factsだけ実行) - hosts: dbservers gather_facts: yes tasks: [] # Play 2: WebサーバーでDBのfactsを参照する - hosts: webservers tasks: - name: DBサーバーのIPをconfigに埋め込む template: src: app.conf.j2 dest: /etc/app/app.conf vars: db_ip: "{{ hostvars[groups['dbservers'][0]]['ansible_default_ipv4']['address'] }}"

Play 1でDBサーバーのfactsを先に収集し、Play 2のWeb側で安全に参照するパターンです。Playbookの実行順を意識した設計が必要になります。

この設計パターンをAnsibleの実機環境で体験したい方は、>> Ansibleハンズオン講座の詳細を見る をご覧ください。

groupsとgroup_namesでグループ情報を動的に使う

groupsgroup_names を使うと、Inventoryのグループ構成に基づいた動的な条件分岐や繰り返し処理が可能になります。

1. group_namesで「このホストはどのグループか」を判定する

group_names は、現在のホストが属するすべてのグループ名のリストです。when 条件でグループ判定ができます。

- name: 本番グループのみfirewalldを有効化する service: name: firewalld state: started enabled: yes when: "'production' in group_names" - name: ステージングではデバッグパッケージを追加する dnf: name: gdb state: present when: "'staging' in group_names"

同一のPlaybookを全環境に流しながら、実行されるタスクをグループで自動的に切り替えられます。環境ごとにPlaybookを分ける必要がなくなります。

2. groupsでグループ内の全ホストを参照する

groups['グループ名'] はそのグループに属するホスト名のリストを返します。Jinja2テンプレート内でグループ全体をループする場合に使います。

# templates/haproxy.cfg.j2 backend webservers {% for host in groups['webservers'] %} server {{ host }} {{ hostvars[host]['ansible_host'] }}:80 check {% endfor %}

このテンプレートは groups['webservers'] を動的に参照するため、Inventoryに新しいWebサーバーを追加するだけでHAProxyの設定ファイルが自動更新されます。

3. groups['all']で全ホストを確認する

Ansibleには事前定義のグループ all(全ホスト)と ungrouped(グループ未所属のホスト)が常に存在します。

# 全ホストのホスト名一覧を出力する(デバッグ用) - debug: msg: "管理対象の全ホスト: {{ groups['all'] }}"

動的Inventoryを使っている環境で「今日は何台が対象になっているか」を確認する際に役立ちます。

Magic Variablesを使う際のトラブルシュート

【エラー1】「'hostvars' object has no attribute 'xxx'」

対象ホストがInventoryに定義されていないか、gather_factsが実行されていない場合に発生します。

・Inventoryに該当ホストが存在するか確認する: ansible-inventory --list
・gather_facts: yes のPlayを先行して実行し、factsを収集済みにする
・デフォルト値を使う: {{ hostvars[host]['ansible_host'] | default('未設定') }}

【エラー2】inventory_hostnameの値がIPアドレスになっている

Inventoryにホスト名でなくIPアドレスで記載されていると、inventory_hostname もIPアドレスになります。論理名(db01等)でInventoryを定義し、実際の接続先は ansible_host= で指定する書き方を徹底しましょう。

# NG: IPアドレスで直接記載(inventory_hostnameがIPになる) [webservers] 192.168.1.10 192.168.1.11 # OK: 論理名 + ansible_host で接続先を分離する [webservers] web01 ansible_host=192.168.1.10 web02 ansible_host=192.168.1.11

【エラー3】group_namesに期待するグループが入っていない

Inventoryのグループ定義が [children] 経由の場合、子グループ経由のホストにも親グループ名は group_names に含まれます。Inventoryの階層構造と group_names の実際の値を debug モジュールで確認しましょう。

- debug: var: group_names

これを実行するだけで、現在のホストが属するグループ名の一覧が出力されます。

本記事のまとめ

AnsibleのMagic Variables(特殊変数)を使いこなすことで、Inventoryに追加したホストを自動認識し、ホスト固有の設定生成やクロスホスト参照が可能になります。

やりたいこと 使うMagic Variable
Inventoryのホスト名をファイル名に使う inventory_hostname / inventory_hostname_short
他ホストのIPや変数をconfigに埋め込む hostvars['ホスト名']['変数名']
グループメンバーをループして設定を生成する groups['グループ名']
このホストが特定グループに属するか判定する group_names(whenで条件分岐)
Playbookのディレクトリをパスで参照する playbook_dir / inventory_dir
Magic Variablesを設計に組み込むことで、「Inventoryを更新したらPlaybookも直す」という二重管理が解消されます。Inventoryが「唯一の真実の情報源」(Single Source of Truth)になります。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

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

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

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

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

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

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

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

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

この記事を書いた人

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

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

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