【Ansible 2.10】いつの間にかRoleが終焉していた【オワコン】
気づいたら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