😇

【Ansible 2.10】いつの間にかRoleが終焉していた【オワコン】

2023/03/28に公開

気づいたらAnsible 2.10がリリースされて3年近く経過

筆者は最近までAnsible 2.9を使っていたのだが、ふと最新のAnsible 2.10へ移行してみた。するとAnsible 2.9まで動いていた自作Roleが動かなくなってしまった。

Ansible 2.10以降ではRoleが事実上の終焉

調べたところ、いわゆるStandalone Roleと呼ばれる既存のRoleはEoL状態でオワコンになっていた。それゆえAnsible 2.9までで動いていたRoleは2.10以降で動かなくなるケースも出てくる様子。
ちなみにStandalone Roleとは、Collectionという新たな枠組みに属さない単独のRoleという意味。

Aisible 2.10以降では、Collectionが標準化

Collectionとは、Playbook、Role、Module、Pluginをまとめてパッケージ化する新たな概念。
つまり、PlaybookやRoleなどはCollectionの中に内包され群をなすようになるということ。
これにより、Collectionに属さないレガシーなRole達はStandalone Roleと呼ばれるようになった。

今まではAnsible GalaxyからRoleを好きにダウンロードして活用することが出来た。しかし今後はRoleでの配布方式は廃止になり、Collectionという新単位で配布されるようになる。
CollectionはRole以外にPlaybookやModule、Pluginなども含んで配布できる規格のため、規格としては次世代の優れた方式と理解はできる。そこでRedhatはCollectionをかなり強引に普及させようとしており、レガシーなRole資産達は一旦リセットして捨てることにした。Redhatの見解としては、現在も継続的にメンテナンスされているRoleであればAnsible 2.10以降のCollection対応するアップデートするだろうから何も問題にならないし、既にメンテナンスされてないRoleであれば、Collectionに対応することなく負の遺産として消えてどうぞ。ということの様子。

具体的にどうオワコンなのか

あまり活用していない人もいたかもしれないが、Roleは他のRoleとの依存関係を定義できる。例えば、Role Aの実行には事前にRole Bの実行が必要などといった依存表現だ。Collectionも同様にCollection同士の依存関係を定義できるようになっている。
一方で、RoleとCollection間の依存関係はどうにも定義ができない仕組みになっている。

そして最も致命的なのはAnsible 2.10ではModuleもCollection化されたこと。

Moduleってなんだっけ?という人もいるかもしれないが、copyだとかlineinfileだとかtaskの中で実行させる命令セット群のこと。2.9以前はAnsible本体に全てのModuleが含まれていたため、Moduleの概念は深く考えなくても使うことができた。ところがModuleは年々増えていくため、全てのModuleをAnsible本体に内包してしまうコンセプトは現実的ではなくなっていた。そこで2.10以降では、ansible.builtinというビルトインModule以外は各ModuleのCollectionを追加インストールして増やしていく仕組みに切り替わった。今までは全ModuleがAnsible本体に内包されていたので、どのModuleを呼び出しても”Moduleが存在しません”なんてことはならなかったが、2.10以降は使用するModuleのCollectionを事前インストールしておかなければ、Moduleが存在しないエラーも発生しうる。

そうなったことである問題が発生する。RoleはそもそもModuleを意図した順に呼び出すTaskを定義するために使っているはずだ。つまり、Roleは必ず何かのMoudleを必要としている(依存)。ところが、2.10以降はansible.builtin以外のModuleは初期インストールされない。
そうなると、Ansibleをインストールしたユーザ環境毎に使えるModuleも異なってくる。2.9以前は全てのユーザ環境で全てのModuleがインストールされていたので環境毎に差はなかった。

当然、今まで使っていたRoleのTask内には様々なModuleが含まれているだろうし、2.10以降でも初期インストールされるansible.builtinのModuleしか使っていませんなんてことはないだろう。ところが先に述べた通り、2.9以前では全てのModuleがインストールされていたのでRoleの中で何のModuleを使っているかなんて厳密に意識してない人も多かったはず。筆者もその一人で、Ansible 2.10で既存のRoleを動かすとModule不足のエラーが多発、しかも今まで何も考えてなかったため何のModuleが足りないのかもすぐに判別できなかった。

具体例としては、サーバの初期キッティングに使いそうな下記task。1つ目のhostname:ansible.builtinというCollection内のModuleなので2.10でも初期インストールに含まれており、特に問題ない。ところが2つ目のtimezone:community.generalというCollection内のModuleなので2.10では初期インストールに含まれておらず、community.generalというCollectionを追加インストールしないとエラーとなって実行できない。

- name: Set hostname
  hostname:
    name: localhost
  become: true
  
- name: Set timezone
  timezone:
    name: Asia/Tokyo
  become: true

上記のRoleはcommunity.generalというCollectionと依存関係にあり、実行の前にはcommunity.general Collectionのインストールを行っておかなければならない。
しかし冒頭で述べた通り、Roleという概念にはCollectionに対する依存関係を表現できない仕様になっている。つまり、機械的に依存関係に気づくことはできず、Roleを使う人間がその場で気づいて対処しなければならない。

元々Ansibleを2.9以前から活用している人であれば、複数に部品化されたRoleを組み合わせて運用しているだろう。それらのRoleが依存するCollectionを手動で探して実行環境に事前インストールしないと動作しない、それがAnsible 2.10以降の世界となっている。

CollectionはAnsibleの実行環境毎にインストールするわけなので、人が依存関係を探して手作業で追加インストールしたとして、今度はお手製の実行環境とRoleが依存関係を持ってしまい、他の端末にRoleを移しても実行環境が異なるので再びエラー地獄に会うだろう。もし他の実行環境でRoleを実行したいならその環境にも手動でCollectionをインストールする必要がある。

ではどうすればいいのか?というところだが、根本的な対策としては今あるRoleをCollection化して、(Roleの入った)Collectionから(Moduleの入った)Collectionへ依存関係を定義すること。Collectionに指定された他のCollectionへの依存関係はPlaybook実行時に自動インストールしてくれる。つまりは、Ansible 2.10に向けて今あるRoleは全部Collectionへ移行するか、いらないなら捨ててくださいと。

今日本のAnsible解説記事で、Ansible 2.10以降のCollectionを作成する前提としたものはあまり見つからない。Ansible 2.10がリリースされて3年近く経ってこの状態なのだから実質Ansible 2.9が最後のバージョンなのかもしれないとさえ思わされる。日本の皆は2.9にしがみつき続けるのかな?

(なお、この記事に間違いがあるのであれば今すぐ論破してほしい。正直困っている。)

(追記)回避策

根本的な対処策は今あるRoleをCollection形式に変更することだが、とりあえずレガシーなStandalone Roleを手っ取り早く使い続けたいだろう。
そんな時は、Playbookディレクトリに./collections/requirements.ymlを用意することで実行時に必要なCollectionをインストールしてくれる。
(とはいえ今あるRoleを動かす上で何のCollectionに依存しているかは力技で調べるしかない。)

# tree
.
├── collections
│   └── requirements.yml
├── roles
│   └── requirements.yml
└── site.yml
# cat collections/requirements.yml
---
collections:
  - community.general

ansible-galaxy collection install xxxxというコマンドで必要なCollectionを実行環境に追加インストールすることも可能だが、時間が経つとまた何のCollectionをインストールしたか忘れてしまう可能性があるし、他の実行環境にStandalone RoleやPlaybookを移すことを考えると、上記に挙げたrequirements.ymlに指定して、Playbook実行時に自動でCollectionをインストールしてもらった方がマシだと思う。それで最終的にはCollection文化に移行してこうという話。

Discussion