Moleculeは、Ansibleのロール・playbook・collectionを使い捨ての環境へ適用し、その結果を検証するテストフレームワークです。最新リリースはv26.8.0(2026年8月12日公開)で、PyPI上の要求Pythonは3.10以上になっています。この記事では、インストールからmolecule testが走らせる12ステップの中身、v25系以降で入ったansible-native設定と旧来のplatforms記法の違い、podmanコンテナを使ったscenarioの実装、GitHub Actionsでの実行までを公式ドキュメントに当たりながら順に追います。受託開発で入れる条件と見送る案件の見分け方も、最後に条件付きで示すつもりです。
まとめ:Molecule導入の可否を分けるロール規模とCI運用の条件
Moleculeが効くのは、複数の案件やサーバー群へ繰り返し当てるロールを持ち、そのロールを月単位で更新している組織です。逆に、1つの環境に一度だけ流すplaybookしか無いなら、scenario一式(create・converge・verify・destroy)の保守コストが本体のコード量を上回ります。
導入の実務は3点に絞れます。pipでmoleculeを入れansible-lintを併せて導入すること。v25系以降の設定はansible:セクション中心の記法へ移り、日本語記事に多いdriver: docker+platforms:は旧系統として分離されていること。test_sequenceは既定で12ステップ動くため、CIでは4〜7ステップへ削ること。この3点です。
判断を分ける線はロール数ではなく変更頻度にあります。半年に一度しか触らないロールは、テストが腐って偽陽性を出す側に回ります。
MoleculeがAnsibleロールのテストで受け持つ範囲とv26系の現在地
Moleculeの守備範囲を最初に固定しておくと、導入後の期待値がずれません。構文チェックや規約違反の検出はansible-lintの仕事で、Moleculeは「適用した結果、対象がどうなったか」を見ます。
Moleculeが検証するのはロール適用後の状態でありlintではない
Moleculeは使い捨てのインスタンスを作り、そこへロールを当て、状態をアサートし、最後に壊します。本体リポジトリのREADMEは自身を「Ansibleネイティブなテストフレームワーク」と位置づけ、テスト対象をコンテナや仮想マシンに限定せず、クラウドインフラ、API、データベース、ネットワーク機器まで、Ansibleから到達できる対象すべてとしています。ライセンスはMIT、star数は4,147(2026年9月時点)です。
Ansible自体を採るかどうかの段階なら、構成管理ツールの比較と選び方で土俵を決めるほうが先です。Moleculeは、Ansibleを既に採っている前提のうえに載ります。
v26.8.0が前提とするPython3.10以上とansible-coreの範囲
バージョン表記はCalVerで、v26.8.0は2026年8月12日のリリースです。PyPIのメタデータ上の要求Pythonは3.10以上で、3.9以前の環境ではそもそも入りません。サポート対象のansible-coreは、READMEの記述では最新の2メジャーバージョン(N/N-1)のみです。
RHEL系の古いシステムPythonへ素で入れて失敗する相談が多いのは、この要求が上がり続けているためです。仮想環境を切る前提で計画してください。
molecule testが実行する12ステップとplaybookごとの役割分担
molecule testは単一のコマンドに見えて、内部では順序の決まったアクション列を走らせます。何が動いているかを把握しないまま失敗ログを読むと、原因の切り分けに時間を取られます。
既定のtest sequence12ステップとidempotenceの判定内容
公式のWorkflow Referenceは、molecule testが展開する既定のシーケンスを次の順で示しています。dependency → cleanup → destroy → syntax → create → prepare → converge → idempotence → side_effect → verify → cleanup → destroy の12ステップです。各アクションは同名のplaybook(create.yml、converge.yml、verify.ymlなど)に対応し、実際の作業はそのplaybookのタスクが担います。
特徴的なのがidempotenceで、convergeをもう一度流してchangedが出ないかを見ます。つまりロールの冪等性を機械判定する工程です。冪等性とは何かを設計側から押さえておくと、このステップで落ちたときに直す場所の見当が付きます。
test_sequenceを4ステップへ短縮する判断基準と副作用
シーケンスは設定で差し替えられます。公式が例示する最短形は create → converge → verify → destroy の4ステップです。開発中のループを速くしたいときは、molecule convergeでインスタンスを残したまま当て直し、状態を見てからmolecule verifyを単独で回すほうが手数が減ります。
molecule test
molecule converge
molecule verify -s default
molecule destroy
短縮の副作用は2つあります。syntaxを外すと構文エラーがconverge時まで顕在化しません。idempotenceを外すと、2回目の適用で毎回changedを返すタスク(後述のcommandモジュール直書きなど)が素通りします。CIでは短縮形、夜間の定期ジョブでは既定の12ステップ、という二段構えが扱いやすい構成です。
pip導入の手順とansible-dev-tools・ansible-lintの使い分け
導入方法は公式が明確に絞っています。ここを外すと、後の設定が正しくても動きません。
pipでmoleculeだけ入れる場合とansible-dev-toolsの選択
公式のInstallationページは「pipが唯一サポートされるインストール方法」と明記し、推奨としてansible-dev-toolsパッケージを挙げています。これはAnsibleコンテンツ作成に要るツール群をまとめたPythonパッケージで、ansible-coreが未導入なら一緒に入る構成です。単体で入れるならmoleculeとansible-coreを指定します。
ansible-lintはmoleculeに含まれません(lintのextraにも入りません)。同じページが別途の導入を案内しているため、セットで入れる書き方にしておくと環境差が減ります。CentOS系ではgcc・python3-devel・openssl-develなどOSパッケージの追加が要る点も、公式が挙げています。
python3 -m pip install --user molecule ansible-lint
python3 -m pip install --user "molecule-plugins[podman]"
molecule --version
driverがdelegatedとdefaultだけになった経緯と代替手段
公式ドキュメントは「Moleculeは既定でdelegatedドライバーを使う。他のドライバーはPyPIから別途入れる」と書いています。実際、本体のスキーマ定義(driver.json)でnameに許されている値はdelegatedとdefaultの2つだけです。dockerやpodmanをdriver名として書く記法は本体から外れました。
代替は2つです。molecule-pluginsを入れてプラグイン側のドライバーを使うか、create.ymlとdestroy.ymlを自分で書き、community.dockerやcontainers.podmanのモジュールでコンテナを操作するか。公式のロール入門は後者で、プラグイン追加なしに完結します。既存のscenario資産がどちらの記法かで決めてください。
旧platforms記法からansible-native記法へ移す手順と勘所
日本語で読める解説の大半は、driver: name: dockerとplatforms:を並べる旧記法です。この記法は公式側で「pre-ansible-native」として別ページへ分離され、新しい系統とは設定の骨格そのものが違います。
ansibleセクションのcfg・env・executor・playbooksの書き方
新しい記法では、設定の中心がansible:セクションへ移ります。Ansible-Native Configurationが示すトップレベルは、ansible(cfg・env・executor・playbooks)、scenario、verifierの3系統です。cfgはscenario用のansible.cfgへマージされる設定、envは実行時の環境変数、executorは実行バックエンド(ansible-playbookまたはansible-navigator)と渡す引数、playbooksは各アクションに対応するファイル名を指します。
---
ansible:
cfg:
defaults:
host_key_checking: false
roles_path: ${MOLECULE_PROJECT_DIRECTORY}/..
executor:
backend: ansible-playbook
args:
ansible_playbook:
- --inventory=inventory/
dependency:
name: galaxy
options:
requirements-file: ${MOLECULE_SCENARIO_DIRECTORY}/requirements.yml
scenario:
test_sequence:
- dependency
- destroy
- create
- converge
- idempotence
- verify
- destroy
テスト対象のホストは、molecule.ymlのplatforms:ではなく、通常のAnsibleインベントリーで定義します。静的なYAMLインベントリーのほか、amazon.aws.aws_ec2のような動的インベントリープラグイン、constructedプラグインもそのまま使えます。
旧platforms記法からの書き換えで詰まりやすい設定の場所
書き換えで壊れやすい箇所は決まっています。第一に、ホスト定義の引っ越しです。旧記法でplatforms:に書いていたイメージ名やコマンドは、インベントリーのhostvars(container_image、container_commandなど)へ移し、create.ymlがそこを読む形に変えます。
第二に、接続方法の指定です。旧記法ではドライバーが暗黙に決めていた接続プラグインを、インベントリー側でansible_connection: containers.podman.podmanのように明示します。第三に、ANSIBLE_*の環境変数はansible.envへ、ansible.cfg相当の設定値はansible.cfgへ振り分けること。両記法が混在すると読み込み順の把握が難しくなるため、scenario単位で一気に切り替えてください。
podmanコンテナでロールを検証するscenario一式の作成手順
最小構成を1つ通しておくと、以降の案件へ複製できます。公式のTest a roleはpodmanを前提に、containers.podmanコレクションでコンテナのライフサイクルと接続を扱う例を示しています。
molecule init scenarioが作るディレクトリ構成と役割
ロールのディレクトリでmolecule init scenario defaultを実行すると、molecule/default配下に molecule.yml・requirements.yml・inventory/hosts.yml・create.yml・converge.yml・verify.yml・destroy.yml が展開されます。初期化処理そのものがAnsibleのplaybookとして実装されており、出力先に既存ファイルがあると「destination folder is not empty」で止まります。
展開されるmolecule.ymlのテンプレートには、既定の12ステップがtest_sequenceとして書かれています。moleculeディレクトリはロール本体の一部ではないため、配布時に含めるかどうかはgalaxy.ymlのbuild_ignoreで決める形です。大量のロールをplaybookで束ねる実例としてはKubesprayの構築手順が近く、Moleculeが要る典型に当たります。
inventoryにコンテナを定義するcreate・verifyの最小実装
インベントリーにコンテナの素性を書き、create.ymlがそれを読んで起動します。ホスト名・イメージ・起動コマンドの出どころを1か所にまとめられるため、scenarioを増やすときの差分が小さくなります。
---
all:
children:
molecule:
hosts:
molecule-fedora:
ansible_connection: containers.podman.podman
container_image: quay.io/centos/centos:stream9
container_command: sleep 1d
container_privileged: false
create.ymlはlocalhostで動き、groups[‘molecule’]をループしてコンテナを作り、wait_for_connectionで接続可能になるまで待ちます。
- name: Create container instances
hosts: localhost
gather_facts: false
tasks:
- name: Create containers from inventory
containers.podman.podman_container:
name: "{{ item }}"
image: "{{ hostvars[item].container_image }}"
command: "{{ hostvars[item].container_command | default('sleep 1d') }}"
state: started
loop: "{{ groups['molecule'] }}"
- name: Wait for containers to be ready
ansible.builtin.wait_for_connection:
timeout: 30
delegate_to: "{{ item }}"
loop: "{{ groups['molecule'] }}"
verify.ymlはassertでロールの結果を判定します。ファイルの存在、サービスの起動状態、設定値の中身など、ロールが約束している出力だけを見る書き方にすると、実装を変えたときの手戻りが減る構造です。requirements.ymlにはcontainers.podmanのバージョン下限(公式例では1.10.0以上)を書き、dependencyステップで取得させます。ロールの雛形づくり(ansible-galaxy role init)やGalaxyからの依存取得の書き方は、Ansible Galaxyの使い方を解説した記事にまとめています。
GitHub Actionsでmolecule testを回すCI設定と実行時間の抑え方
ローカルで通ったscenarioは、そのままCIへ載せられます。ここで効いてくるのが前述のシーケンス短縮です。
公式が示すGitHub Actionsのワークフロー例と実行環境の指定
公式のContinuous integrationページは、ubuntu-24.04ランナー上でPython 3.10と3.11のマトリクスを回す例を載せています。checkoutとsetup-pythonはv7、依存はrequirements.txtから入れ、最後にmolecule testを叩く構成です。ANSIカラーがTTY判定で落ちる環境ではPY_COLORS=1を定義するとログが読みやすくなります。
name: Molecule Test
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-24.04
strategy:
max-parallel: 4
matrix:
python-version: ["3.10", "3.11"]
steps:
- uses: actions/checkout@v7
with:
path: molecule_demo
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: python3 -m pip install -r requirements.txt
- name: Test with molecule
env:
PY_COLORS: "1"
run: molecule test
ワークフローの基本構造から確認したい場合は、GitHub Actionsでビルド・自動テストを組む手順を先に読むと、matrixやstepsの意味を追いやすくなります。
CI実行時間を抑えるtest_sequence分割とキャッシュの置き所
実行時間の大半はコンテナイメージの取得とgalaxyの依存解決に消えます。対策は3つあり、効果の大きい順に並べます。まず、プルリクエスト時のシーケンスを create → converge → idempotence → verify → destroy に削ること。次に、コレクションのインストール先をキャッシュ対象へ含めること。最後に、マトリクスのPythonバージョンを常用の1つへ絞り、複数版の検証は定期実行へ回すことです。
プライベートリポジトリの依存を引く場合は、GIT_CREDENTIALSをシークレットに置き、テスト実行の前段へ認証設定のステップを挟みます。この手順も公式のCIページに例があります。
受託開発でMoleculeを入れる条件と入れない方がよい案件の見分け
ここからは判断の話です。ツールとしての出来と、案件に入れるべきかは別問題になります。
Moleculeを入れる条件はロールの再利用数と変更頻度で決まる
採用の条件は2つとも満たすときに限ります。第一に、同じロールを2つ以上の環境または案件へ当てていること。第二に、そのロールを四半期に1回以上更新していること。この2つが揃うと、変更時の回帰確認を人手でやる負担がscenarioの保守を上回ります。
テスト全体のどこに置くかという配分の話は、テストピラミッドの考え方と同じ枠で整理できます。Moleculeは結合テスト寄りで、1回の実行にコンテナ起動ぶんの時間がかかります。単位時間あたりの検出効率で言えば、ansible-lintのほうがはるかに上です。lintを先に入れ、それでも取りこぼす「適用結果の誤り」をMoleculeで拾う順序にしてください。
一度きりのplaybookや本番SSH前提の構成で見送る判断基準
見送る場面は明確です。納品後に触らない一回限りの構築playbook、対象が本番サーバーのSSH接続だけで使い捨て環境を作れない構成、ロールが1本しか無く社内の1環境でしか動かない案件。このいずれかに当たるなら、Moleculeは入れないほうが総コストは下がります。使い捨て環境を用意できない案件でdelegatedドライバーを無理に使い、検証用の実機を常設した結果、その実機の状態管理が新しい保守対象になった例は珍しくありません。
判断に迷う中間帯——ロールは複数あるが運用体制が定まっていない場合は、CIの整備と運用の引き取りをセットで考える必要があります。システム保守運用・内製化支援では、こうした自動テストとCIの土台づくりから内製化までを引き受けています。
idempotenceが通らない書き方とcommandモジュールの扱い
失敗パターンで最も多いのが、idempotenceステップで落ちるケースです。原因はほぼcommandやshellモジュールの直書きで、これらは毎回changedを返します。回避策は、専用モジュール(ansible.builtin.copy、ansible.builtin.serviceなど)へ置き換えるか、createsやchanged_whenで変更判定を明示することです。
次に多いのが、タイムスタンプや乱数を含むテンプレートです。2回目の適用でファイル内容が変わるため、必ずchangedになります。時刻を埋めたいなら、その行をテンプレートから外すか、テスト時は固定値を渡してください。落ちたらmolecule convergeを2回続けて手で流し、どのタスクがchangedを返すかを目で確かめるのが最短です。
よくある質問
導入前後で相談の多い点をまとめます。
Moleculeはplaybookやcollectionのテストにも使えますか?
使えます。公式ドキュメントは入口を「ロールのテスト」「playbookプロジェクトのテスト」「collectionのテスト」の3つに分け、それぞれ別の手順ページを用意しています。ディレクトリの形だけで道が決まるわけではなく、何を検証したいかで選ぶ構成です。collectionではscenario名をスラッシュ区切りで指定するため、-sオプションの書き方が変わります。
molecule initでdockerドライバーを指定するとエラーになります
本体のスキーマでdriverのnameに許される値はdelegatedとdefaultだけです。dockerやpodmanをドライバー名として書く記法は本体から外れ、molecule-pluginsパッケージ側へ移りました。プラグインを入れて使うか、create.ymlとdestroy.ymlをcommunity.dockerやcontainers.podmanのモジュールで自分で書くか、どちらかを選んでください。公式のロール入門は後者の書き方です。
molecule testが途中で止まったコンテナはどう片づけますか?
シーケンスの末尾にdestroyが入っているため通常は自動で消えますが、途中で中断すると残ります。molecule destroyを単独で実行すればdestroy.ymlが走り、インベントリーに定義したコンテナが片づく流れです。scenarioを複数持っている場合は--allで全シナリオを対象にでき、状態ファイルごとリセットしたいときはmolecule resetを使います。
ansible-lintとMoleculeはどちらを先に入れるべきですか?
ansible-lintが先です。Moleculeはコンテナの起動と破棄を伴うぶん1回の実行が重く、構文や規約の誤りを拾う効率ではlintに及びません。公式もMoleculeにansible-lintは含まれないと明記し、別途の導入を案内しています。CIではlintのジョブを先に走らせ、そこを通ったものだけmolecule testへ進める段構えが扱いやすい形です。
既存のmolecule.ymlはv26系でもそのまま動きますか?
旧記法は「pre-ansible-native」として公式ドキュメントに残っており、docker例のページも維持されています。ただし新記法とは設定の骨格が違うため、片方の解説をもう片方に当てはめると噛み合いません。新規に書くならansible-native記法を選び、既存資産はscenario単位で切り替える進め方を勧めます。
関連記事
- 冪等性とは?読み方・意味からAPI・IaCでの担保方法まで実装者向けに解説:idempotenceステップで落ちたときに、設計側から直す観点を整理しています。
- 構成管理ツールの比較と選び方|Ansible・Terraform・Chef・Puppet・OpenTofuの選定条件:Ansibleを採るかどうかの手前の判断材料です。
- Kubesprayとは?構築手順・kubeadmとの違い・CNI選択を解説:大量のロールをplaybookで束ねる実例として読めます。
- GitHub Actionsでビルド・自動テストを自動化する方法|YAML設定の基本と具体例:CIへ載せる前にワークフローの基本構造を確認できます。
- Packerとは?HashiCorpのマシンイメージ自動構築をTerraform・構成管理との違いと実装視点で解説:検証用イメージを事前に焼く選択肢との比較に使えます。