nikkie-ftnextの日記

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

Ansibleのplaybookをディレクトリに分けて置くには(環境変数 ANSIBLE_ROLES_PATH を使った例)

この記事は、Ansible Advent Calendar 2022 12日目の記事です。
11日目はkitaraさんによる「Ansible CoreをREST API経由で操作してみた」でした。
Ansible、こんなことまでできるんですね!

はじめに

今はまだ勇気も自信もぜんぜんだから」、nikkieです。

Ansible Advent Calendarに一ネタ投稿です!
業務きっかけでAnsibleを触っていますが、まだまだ雰囲気、完全に理解はもうちょっと先🔰という感触です。
気になって調べたトピックを小ネタとしてアウトプットします。

Ansibleは初学者ですので、伸びしろにお気づきの際は、小さな点でも@ftnextまでコメントお寄せいただけると大変助かります〜1

目次

やりたいことは

前提

Ansibleのドキュメントの「ベストプラクティス」>「コンテンツの整理」>「ディレクトリーのレイアウト」に沿ったレイアウトをしています。

増えてきたplaybookをディレクトリに分けて整理したい

使っている中でplaybookが増えてきました
ドキュメントの例ではplaybookは3つ(site.ymlwebservers.ymldbservers.yml)ですが、10を超えたとします。
Zen of Python的には「Flat is better than nested.」ですが、10を超えたflatはちょっと扱いにくさを感じます。

playbookの名前を観察すると、プレフィックスが振られているのに気付きました。
プレフィックスの分、ファイル名が長くなっています。
これが扱いにくさの1つですね。
こういうときはプレフィックスごとにディレクトリに分けて置いたらよさそうですよね。

結論:ディレクトリに置いた上で、環境変数の指定が必要

  • playbookをディレクトリの中に置けます!
  • その場合、ansible-playbookコマンドを実行するには、環境変数ANSIBLE_ROLES_PATHの指定が必要です

サンプルplaybookで説明

具体例で説明しましょう。
ソースコードは以下にあります。

Before: ディレクトリ導入前

playbookをディレクトリに分けて置く前の状態は以下とします。
ディレクトリに分けた後の実行方法だけを検証したかったので、検証しやすいよう簡素なつくりとしています。

.
├── fabulous-playbook.yml  # playbook
└── roles/
    ├── awesome/
    │   ├── tasks/
    │   │   └── main.yml
    │   └── templates/
    │       └── awesome.j2  # main.ymlのtaskで使う
    └── common/
        └── tasks/
            └── main.yml

fabulous-playbook.ymlでは

  1. common roleの main タスクを使ったデバッグ出力
  2. awesome roleの main タスクを使った、テンプレートを埋めたファイル作成

を行います。

---
- hosts: localhost
  tasks:
  - name: Execute common
    import_role:
      name: common
  - name: Execute awesome
    import_role:
      name: awesome

実行してみましょう(出力は抜粋です)

$ ansible-playbook -e subject=nijigaku fabulous-playbook.yml
PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************

TASK [common : common print] ***************************************************
ok: [localhost] => {
    "msg": "Common"
}

TASK [awesome : Template a file] ***********************************************

hoge.txtができました!

✨✨✨ nijigaku is awesome!! ✨✨✨

After: ディレクトリ導入後

tidyディレクトリを作って、fabulous-playbook.ymlを移動します。

mv fabulous-playbook.yml tidy/located-playbook.yml
.
├── tidy/
│   └── fabulous-playbook.yml  # ディレクトリの下に移動
└── roles/
    ├── awesome/
    │   ├── tasks/
    │   │   └── main.yml
    │   └── templates/
    │       └── awesome.j2
    └── common/
        └── tasks/
            └── main.yml

実行してみると、うまくいきません。

$ ansible-playbook -e subject=nijigaku tidy/located-playbook.yml

ERROR! the role 'common' was not found in ...

After + ANSIBLE_ROLES_PATHを指定する

環境変数ANSIBLE_ROLES_PATHも指定すると、Beforeのときと同様に動きます。

$ ANSIBLE_ROLES_PATH=$PWD/roles ansible-playbook -e subject=nijigaku tidy/located-playbook.yml
PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************

TASK [common : common print] ***************************************************
ok: [localhost] => {
    "msg": "Common"
}

TASK [awesome : Template a file] ***********************************************

tidy/hoge.txtができます!(ファイルの内容は同じですが、できあがる場所が異なります)

ANSIBLE_ROLES_PATHも指定するとうまくいく仕組み

環境変数ANSIBLE_ROLES_PATHはAnsibleの変数DEFAULT_ROLES_PATHに関わる環境変数です。

Colon separated paths in which Ansible will search for Roles.

ANSIBLE_ROLES_PATHを指定しないときのエラーメッセージを見ると、「以下を探したがロールが見つからない」と書かれています。

  • $PWD/tidy/roles(実行したplaybookの置かれているディレクトリ)
  • $HOME/.ansible/roles
  • /usr/share/ansible/roles
  • /etc/ansible/roles
  • $PWD/tidy

ロールがある$PWD/rolesを指定したので(commonawesomeといった)ロールが見つかり、playbookが実行できたというわけですね。

DEFAULT_ROLES_PATHに関してドキュメントの記載を探したところ、以下が見つかりました。

これを使用して、共通のロールをすべて 1 つの場所にチェックアウトし、複数の Playbook プロジェクト間で簡単に共有します。(「ロール検索パス」より)

多数のplaybookを整理するためにディレクトリを導入したことで、ロールが共通となっているってことですね!
DEFAULT_ROLES_PATHを設定して共通のロールを利用しました。

動作環境

# pip freezeの出力はリポジトリのrequirements.txtをどうぞ
ansible==7.1.0
ansible-core==2.14.1

終わりに

ANSIBLE_ROLES_PATHを使い、playbookをディレクトリに分けて置いて実行する方法を共有しました。

このトピック、検索しても求める情報になかなかにたどり着けなかったんですよね(初学者ゆえに適切な検索語句を知らなかったというのもあると思います)。
playbookをディレクトリに分けて置いてみて、エラーの解決方法がなかなか分からなくて、時間をおいて何回か調べて、ドキュメントからANSIBLE_ROLES_PATHを見つけました。
過去の私と同じところでつまづいた方の一助となったら嬉しいです。

明日のAnsible Advent Calendar 2022 13日目はcurry9999xさんです!
「Ansible で macOS を 管理するお話」だそうです。楽しみですね〜!!

追記(2022/12/24):公開直後ansible-galaxy role install を教えていただく

ありがとうございます!2素振りしてみます


  1. 「playbookをディレクトリに分けて置く」をもっとうまくやる方法を知りたいですし、Ansibleは師がいないので、「そもそも考え違いをしている(Ansible的にはplaybookをディレクトリに分けるのは筋悪)」というような指摘もありがたいです
  2. 気づいた反響としては https://twitter.com/yassan168/status/1602317021181804544 も。インベントリファイルやansible-playbook -eで指定してます(私が疑問をうまく汲み取れていないかも)