nikkie-ftnextの日記

イベントレポートや読書メモを発信

Ansibleでターゲットノードがlocalhostのplaybookにて、1つのインベントリファイルにこだわり、参照する変数の値をグループで切り替えるには(ホスト名ごとに変数を持つ挙動を使ったハック)

はじめに

じゃあ、レッスン行こー、ゆりこー! さん!! nikkieです。

「Ansibleでこういうことできないかな」とここ数日考えていた小ネタのアウトプットです。
Ansibleの完全に理解はもうちょっと先かな🔰という初学者レベルですので、伸びしろにお気づきの際は、小さな点でも@ftnextまでコメントお寄せいただけると大変助かります。

目次

やりたいこと:ターゲットノードがlocalhostのplaybookで、参照する変数の値を複数から切り替えたい

Ansibleには2種類のノードがあると理解しています。

  • コントロールノード:ansible-playbookコマンドを実行
  • ターゲットノード:プレイブックの処理内容を実行
    • インベントリに定義される
    • グループも定義できる

今回考えるのは、コントロールノードとターゲットノードがどちらもlocalhostで共通な場合です。

利用シーンとしては、localhostで実行するコマンドをAnsibleでラップしています。
コマンドには変数を使っているのですが、ステージング環境用の実行と本番環境用の実行とで変数の値を変えたいです。
インベントリファイルをステージング環境用と本番環境用に分ける方法もあると思うのですが、分けずに同じ変数に異なる値を持たせられないか試行錯誤しました。

結論:1インベントリをansible-playbook -lで切り替えるハック

実行環境

  • Python 3.11.4
  • ansible==8.5.0

ソースコードはこちらにあります(inventoryとplaybook.yml)

インベントリ

1つのインベントリにステージング環境用のグループと本番環境用のグループを作ってみました。

[my_group:children]
awesome
fabulous

[my_group:vars]
foo=42

[awesome]
127.0.0.1 ansible_connection=local

[awesome:vars]
spam=ham

[fabulous]
0.0.0.0 ansible_connection=local

[fabulous:vars]
spam=egg

変数fooはmy_groupに定義しているので、awesomeグループでもfabulousグループでも同じ値です。
変数spamawesomeグループとfabulousグループとで値を変えて定義しています。

プレイブック

- hosts: my_group
  tasks:
    - name: "Common variable"
      debug:
        msg: "{{ foo }}"
    - name: "Each variable"
      debug:
        msg: "{{ spam }}"

hostsに指定しているのはmy_groupです。
ansible-playbook-lを使って、my_groupの中のターゲットノードを指定します。

-l SUBSET, --limit SUBSET
further limit selected hosts to an additional pattern
ansible-playbook --helpより)

実行結果

awesomeグループを指定すると、変数spamの値はhamです。

% ansible-playbook -l awesome -i inventory playbook.yml

PLAY [my_group] ****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [127.0.0.1]

TASK [Common variable] *********************************************************
ok: [127.0.0.1] => {
    "msg": 42
}

TASK [Each variable] ***********************************************************
ok: [127.0.0.1] => {
    "msg": "ham"
}

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

fabulousグループを指定すると、変数spamの値はeggです。切り替えられた!

% ansible-playbook -l fabulous -i inventory playbook.yml

PLAY [my_group] ****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [0.0.0.0]

TASK [Common variable] *********************************************************
ok: [0.0.0.0] => {
    "msg": 42
}

TASK [Each variable] ***********************************************************
ok: [0.0.0.0] => {
    "msg": "egg"
}

PLAY RECAP *********************************************************************
0.0.0.0                    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

ハックに行き着くまでの試行錯誤ログ

どうやらターゲットノードのホスト名(今回はIPアドレスごとに変数を持つ挙動のようです。

最初、両グループのIPアドレス127.0.0.1に揃えたのですが

[awesome]
127.0.0.1 ansible_connection=local

[fabulous]
127.0.0.1 ansible_connection=local

これだと-lを指定しても、127.0.0.1として変数の値は1通りしか持てませんでした。
「もしかしてホスト名ごとに変数を持つのでは」という仮説に気付き、127.0.0.1localhostで試して、変数を切り替えられることを確認。
このとき「A duplicate localhost-like entry was found (localhost). First found localhost was 127.0.0.1」というWARNINGが出ていたので、0.0.0.0を採用しました。

127.0.0.1と0.0.0.0の違いはこちらが分かりやすかったです。

なお、結論で動いた後は、全てのターゲットノードを表すallグループを使ったバージョンも試しています。

終わりに

「ターゲットノードがlocalhostのplaybookで、変数の値を切り替える」を実現する方法をアウトプットしました。
正直これが本番コードで使えるレベルかは自信がなく(Ansibleの思想に沿っている?)1、考えていたことのバックアップの意味合いが大きいです。
-lオプションの動きがようやく分かったのが収穫です!
hostsの中からsubsetを指定できるのか〜

そもそも私はAnsibleを知らなすぎるので、積ん読していた『Ansible実践ガイド 第3版』2に当たって、インベントリやプレイブックとは何かを学びながら考えました(2章・3章)。

概念が掴めて見えてきたものもあり、ただやっぱりAnsibleは大きいライブラリで、もっと理解したいな〜という感覚です。
Sphinxについて「拡張でこういうことできないかな〜」と考えているのと体験としては近いですね

P.S. ansible-inventoryコマンド、便利!

試行錯誤の中では、ansible-inventoryコマンドにもお世話になりました。

% ansible-inventory -i inventory --graph --vars
@all:
  |--@ungrouped:
  |--@my_group:
  |  |--@awesome:
  |  |  |--127.0.0.1
  |  |  |  |--{ansible_connection = local}
  |  |  |  |--{foo = 42}
  |  |  |  |--{spam = ham}
  |  |  |--{spam = ham}
  |  |--@fabulous:
  |  |  |--0.0.0.0
  |  |  |  |--{ansible_connection = local}
  |  |  |  |--{foo = 42}
  |  |  |  |--{spam = egg}
  |  |  |--{spam = egg}
  |  |--{foo = 42}

このグラフを見返したことで、「ホスト名ごとに変数を持つ」挙動に気づけました。

このコマンドを知ったきっかけはこちらです。アウトプットいただきありがとうございます


  1. インベントリファイルを分けましょうという話なのかもしれないんですよね。マサカリこわい。あー🪓
  2. 📣最新の第4版が今年出たみたいですよ!