Red Hat Certified Engineer (RHCE) #2 Inventory: static、dynamic、group/host_vars
#1 で RHCE (EX294) が Ansible 自動化の実技試験だという正体を押さえました。プレイブックを書く前に、まず答えるべき質問が 1 つあります。Ansible はいったいどのホストを扱うのか です。この質問に答えるファイルが inventory です。inventory は control node が管理する managed node の一覧であり、どのホストをどのグループにまとめ、各ホストにどう接続するかを宣言します。
inventory を正確に構成できないと、その後のすべてのプレイブックは対象を見つけられません。そこで今回の記事は、static inventory の 2 つの形式、グループとグループのグループ、変数を分離する group_vars と host_vars ディレクトリ、そして inventory を検証するコマンドまで一度に整理します。
inventory とは何か #
inventory は Ansible が作業を実行する対象ホストの一覧です。最も単純な形は、ホスト名や IP アドレスを 1 行に 1 つずつ書いたテキストファイルです。ここにホストをグループにまとめ、グループごとに変数を与え、接続方法まで足していくと、実戦で使う inventory になります。
inventory は大きく 2 種類に分かれます。
- static inventory。人が直接ファイルにホストを書いておく inventory です。変わらない固定環境に適しており、RHCE 試験で作成する inventory はほぼ全部こちらです。
- dynamic inventory。スクリプトやプラグインが外部システム (クラウド API、CMDB など) に問い合わせてホスト一覧を実行時点で生成する inventory です。ホストが頻繁に変わる環境に適しています。
試験の中心は static inventory なので、ここから正確に固めます。
static inventory: INI 形式 #
最も伝統的な inventory 形式は INI 形式です。角括弧でグループ名を宣言し、その下にホストを 1 行ずつ並べます。
# inventory
# グループなしで並べたホストは自動的に ungrouped グループに属します
bastion.example.com
[web]
web1.example.com
web2.example.com
[db]
db1.example.com
[lb]
lb1.example.com角括弧でまとめられないままファイル上部に書いたホストは、ungrouped という暗黙グループに入ります。そして inventory のすべてのホストは自動的に all というグループにも一緒に属します。つまり all と ungrouped は、ユーザーが作らなくても常に存在するグループです。
ホスト範囲表記 #
ホスト名が規則的な数字やアルファベットで続くなら、範囲表記で短く書けます。角括弧の中で開始と終了をコロンでつなぎます。
[web]
web[1:3].example.com
[db]
db[a:c].example.comweb[1:3].example.com は web1.example.com、web2.example.com、web3.example.com を意味します。数字だけでなく [a:c] のようにアルファベット範囲も可能です。ホストが多いときに inventory を短く明確に保つ表記なので、覚えておきます。
グループのグループ: children #
グループをさらにまとめて上位グループを作れます。INI 形式では [グループ名:children] ヘッダーの下に下位グループ名を並べます。
[web]
web[1:3].example.com
[db]
db1.example.com
# web と db をまとめた上位グループ
[production:children]
web
dbこうすると、production グループを対象に指定したときに web と db に属するすべてのホストが一緒に選択されます。環境 (production、staging) や役割でホストを階層化するときに便利な構造です。
INI 形式のインライン変数 #
INI 形式では、ホスト行の後ろに変数をそのまま付けることもできます。
[web]
web1.example.com ansible_host=192.168.10.11 ansible_user=devops
web2.example.com ansible_host=192.168.10.12 ansible_user=devopsただし、このようにホスト行に変数を長く付けると可読性が下がります。変数は後で扱う group_vars と host_vars に分離する方式が推奨されます。
static inventory: YAML 形式 #
同じ inventory を YAML 形式でも書けます。構造が明示的なので、グループ階層と変数が一目で分かります。
# inventory.yml
all:
children:
web:
hosts:
web1.example.com:
web2.example.com:
web3.example.com:
db:
hosts:
db1.example.com:
production:
children:
web:
db:YAML 形式では all の下の children でグループを宣言し、各グループの hosts の下にホストを置きます。グループのグループは、グループの中にもう一度 children を置いて表現します。INI の [production:children] がここでは production の下の children に対応します。YAML 形式でもグループの vars やホストの下に変数を直接与えられます。INI と YAML のどちらの形式を使っても動作は同じです。試験では 2 つのうち慣れた形式を使えばよいですが、提供された inventory を解釈するには両方の形式を読める必要があります。
接続変数: ホストにどう接続するか #
ホスト名だけでは接続できない場合が多いです。接続アドレスが違ったり、ログインアカウントが違ったり、ポートが標準でなかったりします。このとき使う特殊変数が connection variable です。
| 変数 | 意味 |
|---|---|
ansible_host | 実際に接続するアドレスや IP アドレス (inventory 名と違ってもよい) |
ansible_user | SSH ログインアカウント |
ansible_port | SSH ポート (デフォルトの 22 でないときに指定) |
ansible_connection | 接続方式 (ssh がデフォルト、ローカルは local) |
ansible_become | 権限昇格の有無 (true/false) |
inventory に書いた名前と実際の接続情報が違うとき、これらの変数で合わせます。接続変数もホスト行に散らばせるより、group_vars と host_vars に整理すると管理がすっきりします。
group_vars と host_vars で変数を分離 #
inventory ファイルに変数を直接書くこともできますが、変数が多くなるとファイルが複雑になります。Ansible は inventory の隣に決まったディレクトリを置くと変数を自動的に読み込む規約を提供します。それが group_vars と host_vars です。
group_vars/<グループ名>.yml。そのグループに属するすべてのホストに適用される変数です。host_vars/<ホスト名>.yml。特定のホスト 1 つにだけ適用される変数です。
ディレクトリ構造は次のとおりです。
project/
├── ansible.cfg
├── inventory
├── group_vars/
│ ├── all.yml
│ ├── web.yml
│ └── db.yml
├── host_vars/
│ ├── web1.example.com.yml
│ └── db1.example.com.yml
└── site.ymlgroup_vars/all.yml はすべてのホストに共通で適用される変数を置きます。group_vars/web.yml は web グループだけに、host_vars/web1.example.com.yml は web1.example.com ホスト 1 つだけに適用されます。ファイル名がグループ名やホスト名と正確に一致しないと自動的に読み込まれません。
group_vars の例 #
web グループ全体に適用する変数を group_vars/web.yml に置きます。
# group_vars/web.yml
http_port: 80
max_clients: 200
app_user: webadmin
firewall_service: httpすべてのホスト共通の変数は group_vars/all.yml に置きます。
# group_vars/all.yml
ansible_user: devops
ansible_port: 22
ntp_server: time.example.comhost_vars の例 #
特定のホストにだけ必要な値は host_vars に置きます。たとえば web1 だけ接続アドレスとポートが違うなら、次のように書きます。
# host_vars/web1.example.com.yml
ansible_host: 192.168.10.11
ansible_port: 2222
server_id: 1このように分離しておくと、inventory ファイルはホストとグループ構造だけを持ち、変数は各ファイルが責任を持ちます。試験で「このグループにだけこの値を与えよ」というパターンが出たら、ほぼ group_vars で解決します。
inventory の確認 #
inventory を作成したら、Ansible が意図どおりに解釈したかを必ず検証する必要があります。頭の中の構造と実際のパース結果が違う場合がよくあるからです。検証に使うコマンドは次のとおりです。
ansible-inventory –list #
inventory 全体の構造と、各ホストに適用された変数を JSON で出力します。
ansible-inventory -i inventory --listこのコマンドは group_vars と host_vars まで合わせて、各ホストが最終的に持つ変数を見せてくれるので、変数が意図したホストに正しく付いたかを確認するのに最適です。
ansible-inventory –graph #
グループとホストの階層構造をツリー状に出力します。
ansible-inventory -i inventory --graph出力例は次のとおりです。
@all:
|--@ungrouped:
|--@production:
| |--@web:
| | |--web1.example.com
| | |--web2.example.com
| | |--web3.example.com
| |--@db:
| | |--db1.example.comグループのグループ (children) が意図どおりにまとまったかを一目で見られます。--graph の後ろに --vars を付けると、各ノードの変数も一緒に表示されます。
ansible all –list-hosts #
特定のパターンがどのホストに展開されるかを素早く確認します。
ansible web -i inventory --list-hosts
ansible production -i inventory --list-hosts
ansible all -i inventory --list-hostsweb グループや production のような上位グループを指定したときに、実際にどのホストが選択されるかを見せてくれます。プレイブックを回す前に対象が合っているかを点検する安全装置です。
dynamic inventory の概念 #
ホストが頻繁に変わる環境では、inventory を手で維持するのが難しいです。クラウドのようにインスタンスが頻繁に生成・削除される場所では、実行時点で現在のホスト一覧を受け取る dynamic inventory が必要です。
dynamic inventory は 2 つの方式で実装されます。
- inventory script。実行すると決まった JSON 形式でホスト一覧を出力する実行ファイルです。形式さえ合わせれば、どの言語でも書けます。
- inventory plugin。最新の推奨方式です。YAML 設定ファイルで外部ソースを指定すると、プラグインがホストを取得します。たとえば
amazon.aws.aws_ec2プラグインは AWS の EC2 インスタンスを inventory に変換します。
プラグイン方式の設定ファイルの例は次のとおりです。
# aws_ec2.yml (inventory plugin)
plugin: amazon.aws.aws_ec2
regions:
- ap-northeast-2
keyed_groups:
- key: tags.Role
prefix: roleこのファイルを -i aws_ec2.yml で指定すると、Ansible が実行時点で AWS API に問い合わせてホスト一覧を作り、EC2 の Role タグの値でグループを自動生成します。RHCE 試験で dynamic inventory を直接作成せよというパターンは比重が小さいですが、static と dynamic の違いと概念は整理しておきます。
試験の定番パターン #
RHCE 試験で inventory に関連してよく登場する作業は定型化されています。
- 特定グループの定義。与えられたホストを指定されたグループ名にまとめ、複数のグループをさらに上位グループ (children) にまとめる作業です。
- group_vars で変数を分離。inventory ファイルを汚さず、特定のグループにだけ適用される変数を
group_vars/<グループ>.ymlに置く作業です。 - host_vars で例外処理。1 つのホストだけ別の値を持つべきときに
host_vars/<ホスト>.ymlで処理する作業です。 - 接続変数の指定。
ansible_host、ansible_user、ansible_portで接続情報を合わせる作業です。
次は上の要求を一度に満たす総合例です。INI inventory と group_vars を一緒に置いた構成です。
# inventory
[web]
web1.example.com
web2.example.com
[db]
db1.example.com
[datacenter:children]
web
db# group_vars/web.yml
http_port: 80
firewall_service: http
app_root: /var/www/app# group_vars/all.yml
ansible_user: devops
timezone: Asia/Seoulこの構成を ansible-inventory -i inventory --graph --vars で確認すると、datacenter の下に web と db がまとまり、各ホストに group_vars の変数が正しく適用されているのが見えます。
試験ポイント #
- inventory のすべてのホストは自動的に
allグループに、グループなしのホストはungroupedグループに属します。 - INI 形式のグループのグループは
[グループ:children]、YAML 形式はグループの下のchildrenで表現します。 - 範囲表記
web[1:3]はweb1〜web3に展開します。数字とアルファベットの両方が可能です。 - 変数は inventory に直接書くより、
group_vars/<グループ>.ymlとhost_vars/<ホスト>.ymlに分離します。ファイル名がグループ名やホスト名と正確に一致しないと自動的に読み込まれません。 - 接続は
ansible_host、ansible_user、ansible_portで制御します。 - 作成後は
ansible-inventory --list、ansible-inventory --graph、ansible <パターン> --list-hostsで必ず検証します。 - dynamic inventory は script や plugin で外部ソースからホストを取得する方式であり、クラウド環境に適しています。
まとめ #
この記事で押さえたこと:
- inventory は Ansible が扱うホストを定義する出発点 です。static と dynamic に分かれ、試験の中心は static です。
- static inventory は INI と YAML の 2 形式で作成し、ホストとグループ、グループのグループ (children)、範囲表記 (
web[1:3]) をサポートします。 - 変数は
group_varsとhost_varsディレクトリに分離し、接続変数 (ansible_host/ansible_user/ansible_port) で接続を制御します。 ansible-inventory --listと--graph、ansible all --list-hostsで inventory を検証します。- dynamic inventory はスクリプトとプラグインで、クラウドのような外部ソースのホストを実行時点で取得します。
次へ — 設定ファイルと接続 #
これで Ansible がどのホストを扱うかは inventory で定義しました。では Ansible はその inventory をどこで見つけ、ホストにどう接続し、権限はどう上げるのでしょうか。
#3 設定ファイルと接続: ansible.cfg、ssh、become では、ansible.cfg の優先順位と主要な設定、SSH キーベースの接続構成、そして become で権限を昇格する方法まで、直接構成しながら整理します。