Ansibleの運用経験が増えるほど、こういったヒヤリハットが積み重なっていきます。
ansible-lintとMoleculeを組み合わせれば、コードを実際に本番へ流す前に大多数の問題を事前検出できます。ansible-lintが構文・スタイルの静的解析を担い、Moleculeがroleの実行テストと冪等性確認を担います。この2段構えの仕組みをCIに組み込めば、Pushのたびに自動でコード品質を守れます。
この記事では、RHEL 10 / Rocky Linux 9の実行環境を前提に、ansible-lintのインストールから
.ansible-lintでのルール調整、Moleculeの初期化からmolecule testの全フェーズ実行、そしてGitHub Actionsへの組み込みまでを手順ごとに解説します。
この記事のポイント
・ansible-lintはPlaybookとroleのコード品質違反を静的解析で即座に検出するツール
・Moleculeはroleをコンテナで実行して冪等性テストを自動化するフレームワーク
・molecule testで全フェーズ(create/converge/idempotence/verify/destroy)を一括実行できる
・GitHub Actionsに組み込めばPushごとにlintとroleテストが自動実行される
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜansible-lintとMoleculeが必要なのか|手作業チェックの限界
Ansibleは「書いてすぐ動く」手軽さが魅力ですが、その手軽さが落とし穴になることがあります。・
yes/noを真偽値として使っているコードがバージョンアップで警告に変わる・モジュール名を短縮形(
yum)で書いているとFQCN(完全修飾コレクション名)への移行で動作が変わる・roleの途中でエラーが起きても
ignore_errors: yesで握り潰していると、実は冪等でない処理が混入しているこれらを人間の目視だけでチェックするのは限界があります。特にチーム開発では「誰かがレビューするだろう」という抜け漏れが積み重なります。
ansible-lintの役割
ansible-lintはAnsibleコードに対して静的解析を実行するツールです。実際にコマンドを実行せずに、コードを解析してルール違反を報告します。主な検出対象は以下のとおりです。・YAML構文の問題: インデントや真偽値の書き方(
yes/noは非推奨)・FQCN違反:
yum/copy等の短縮形はansible.builtin.yum/ansible.builtin.copyに変更が推奨・冪等性の疑い(要注意):
command/shellモジュールでchanged_when: falseなし等・命名規則: task名がない、role名がスネークケースでない等
Moleculeの役割
Moleculeはroleを実際のコンテナや仮想環境で実行してテストするフレームワークです。単純に「エラーなく動いた」ではなく、「2回実行しても結果が同じか(冪等性)」「意図した状態になっているか(verify)」まで自動確認します。ansible-lintが「設計図に誤りがないか」を確認するとすれば、Moleculeは「実際に建てたら設計通りに仕上がるか」を確認する工程です。
ansible-lintの基本的な使い方
1. ansible-lintのインストールと動作確認
ansible-lintはPython製のツールで、pipで導入します。RHEL 10 / Rocky Linux 9ではPython 3.11以上が標準で利用できます。# 仮想環境を作成してansible-lintをインストール(推奨) python3 -m venv ~/.venv/ansible source ~/.venv/ansible/bin/activate # ansible-coreとansible-lintをインストール pip install ansible-core ansible-lint # バージョン確認 ansible-lint --version
ansible-lint 25.1.0 using ansible-core:2.17.8 ansible:10.7.0 python:3.11.9 config-file: None rulesdir: /home/user/.venv/ansible/lib/python3.11/site-packages/ansiblelint/rules
ansible-lintとansible-coreのバージョンの組み合わせが表示されます。ansible-core 2.17以上を使う場合はansible-lint 25.x系を使うのが基本です。2. PlaybookとRoleを対象に実行する
最もシンプルな実行はPlaybookファイルを引数に渡す方法です。# Playbookを直接対象にする ansible-lint site.yml # roleディレクトリ全体をチェックする ansible-lint roles/webserver/ # カレントディレクトリ配下を全部スキャンする ansible-lint
WARNING Listing 3 violation(s) that are fatal yaml[truthy]: Use 'true' instead of 'yes'. (Line: 12, Column: 9) yaml[truthy]: Use 'false' instead of 'no'. (Line: 24, Column: 9) fqcn[action-core]: Use FQCN for builtin actions: yum -> ansible.builtin.yum Action: yum [roles/webserver/tasks/main.yml:8] Finished with 3 failure(s), 0 warning(s) on 2 files.
yaml[truthy]はYAML真偽値の書き方、fqcn[action-core]はFQCNへの変更が必要な箇所です。それぞれ以下のように修正します。# yaml[truthy] の修正例 # 修正前 - name: Ensure httpd is enabled ansible.builtin.service: name: httpd enabled: yes # ← NG # 修正後 - name: Ensure httpd is enabled ansible.builtin.service: name: httpd enabled: true # ← OK # fqcn[action-core] の修正例 # 修正前 - name: Install httpd yum: # ← NG(短縮形) name: httpd state: present # 修正後 - name: Install httpd ansible.builtin.dnf: # ← OK(RHEL 10はdnf推奨) name: httpd state: present
3. .ansible-lintでルールをカスタマイズする
プロジェクトルートに.ansible-lintファイルを置くことで、スキャン対象・除外ルール・警告レベルを細かく制御できます。# .ansible-lint の設定例 --- # チェック対象のPlaybook/roleを明示(省略時はカレントディレクトリ全体) # lint_paths: # - site.yml # - roles/ # 特定のルールIDをスキップする(チームで合意した例外を記載) skip_list: - yaml[line-length] # 長い行を許容する場合 # 警告扱いにするルール(NG→警告に緩和) warn_list: - experimental # Moleculeのテスト用シナリオを除外(lint対象外にする) exclude_paths: - molecule/ - .git/ - .github/ # 実行環境プロファイル(min/basic/moderate/safety/shared/production) profile: production
profileをproductionにすると最も厳格なルールセットが適用されます。チームで統一した.ansible-lintをリポジトリに含めることで、個人の環境差を排除できます。MoleculeによるroleのテストフローをCIへ
1. Moleculeのインストールとrole初期化
Moleculeのドライバーとしてはdockerが最もよく使われます。検証機にDockerをインストールしておいてください。# molecule本体とdockerドライバーをインストール pip install molecule molecule-plugins[docker] # バージョン確認 molecule --version
molecule init roleを使うと、roleのディレクトリ骨格とMoleculeのテスト設定が同時に生成されます。# dockerドライバーでwebserverというroleを初期化 molecule init role --driver-name docker webserver # 生成されたディレクトリ構造を確認 find webserver -type f | sort
webserver/ defaults/ main.yml handlers/ main.yml meta/ main.yml molecule/ default/ converge.yml ← roleを適用するシナリオPlaybook molecule.yml ← テスト環境の定義ファイル verify.yml ← 検証タスクの定義ファイル tasks/ main.yml vars/ main.yml
molecule init scenarioを実行します。# 既存roleのディレクトリに移動してMoleculeシナリオを追加 cd roles/webserver molecule init scenario --driver-name docker default
2. molecule.ymlのシナリオ設計(platforms・driver設定)
molecule.ymlはテスト環境全体の設定ファイルです。どのコンテナイメージを使うか、どのドライバーを使うかを定義します。# molecule/default/molecule.yml --- dependency: name: galaxy driver: name: docker platforms: - name: instance # RHEL 10互換のRocky Linux 9イメージ(systemdが使えるAnsiblize済みイメージ) image: geerlingguy/docker-rockylinux9-ansible pre_build_image: true # systemdを使うサービス管理が必要な場合 command: /usr/sbin/init privileged: false volumes: - /sys/fs/cgroup:/sys/fs/cgroup:ro tmpfs: - /run - /tmp provisioner: name: ansible config_options: defaults: interpreter_python: auto_silent env: ANSIBLE_FORCE_COLOR: "1" verifier: name: ansible lint: | set -e ansible-lint
platformsには複数のOSを並べることで、RHEL 10互換・Ubuntu 24.04の両方でテストするマトリクス実行も可能です。3. verify.ymlで検証タスクを定義する
verify.ymlはroleを適用した後の状態確認(assertion)を記述します。単に「エラーなく終わった」だけでなく、「サービスが起動しているか」「ポートが開いているか」を明示的に確認します。# molecule/default/verify.yml --- - name: Verify hosts: all gather_facts: false tasks: - name: httpd サービスが起動していることを確認する ansible.builtin.service_facts: - name: httpdがactiveであることをassertする ansible.builtin.assert: that: - "'httpd.service' in ansible_facts.services" - "ansible_facts.services['httpd.service'].state == 'running'" fail_msg: "httpd は起動していません" success_msg: "httpd が正常に起動しています" - name: ポート80が開いていることを確認する ansible.builtin.wait_for: port: 80 timeout: 10
4. molecule testで全フローを実行する
molecule testを実行すると、destroy→syntax→create→converge→idempotence→verify→destroyの全フェーズが自動で実行されます。# テストシナリオ全体を実行する molecule test # または個別フェーズだけ実行する(開発中に便利) molecule create # コンテナを起動する molecule converge # roleを適用する molecule idempotence # 2回目の適用で変更なしを確認する molecule verify # verify.ymlの検証タスクを実行する molecule destroy # コンテナを削除する
molecule testの出力例です。Idempotence completed successfully.が表示されれば冪等性OK、Verifier completed successfully.が表示されれば検証もOKです。INFO Running default > create PLAY [Create] ****************************************************************** TASK [Create molecule instance(s)] ******************************************** changed: [localhost] PLAY RECAP ********************************************************************* localhost : ok=2 changed=1 unreachable=0 failed=0 INFO Running default > converge PLAY [Converge] **************************************************************** TASK [Gathering Facts] ********************************************************* ok: [instance] TASK [webserver : Install httpd] *********************************************** changed: [instance] TASK [webserver : Start and enable httpd] ************************************** changed: [instance] PLAY RECAP ********************************************************************* instance : ok=3 changed=2 unreachable=0 failed=0 INFO Running default > idempotence TASK [webserver : Install httpd] *********************************************** ok: [instance] TASK [webserver : Start and enable httpd] ************************************** ok: [instance] PLAY RECAP ********************************************************************* instance : ok=3 changed=0 unreachable=0 failed=0 INFO Idempotence completed successfully. INFO Running default > verify TASK [httpd サービスが起動していることを確認する] ***** ok: [instance] TASK [httpdがactiveであることをassertする] ***** ok: [instance] INFO Verifier completed successfully. INFO Running default > destroy PLAY RECAP ********************************************************************* instance : ok=2 changed=1 unreachable=0 failed=0
idempotenceフェーズではchanged=0になることが必須です。changed=1以上になると「冪等性テスト失敗」として処理が止まります。roleの設計とテストフローを実機でハンズオン体験したい方は、>> Ansibleハンズオン講座の詳細を見る をご覧ください。
GitHub ActionsでCI/CDパイプラインに組み込む
ansible-lintとMoleculeをGitHub Actionsに組み込むことで、Pull Requestのたびに自動でコード品質チェックが走ります。1. ワークフローファイルの作成
.github/workflows/ansible-ci.ymlとして以下のファイルをリポジトリに含めます。# .github/workflows/ansible-ci.yml --- name: Ansible CI on: push: branches: [main, develop] pull_request: branches: [main] jobs: lint: name: ansible-lint runs-on: ubuntu-latest steps: - name: コードをチェックアウトする uses: actions/checkout@v4 - name: Python環境をセットアップする uses: actions/setup-python@v5 with: python-version: "3.11" - name: ansible-lintをインストールする run: pip install ansible-core ansible-lint - name: ansible-lintを実行する run: ansible-lint molecule: name: Molecule Test runs-on: ubuntu-latest needs: lint # lintが通過してからtestを実行する strategy: matrix: role: - webserver - dbserver steps: - name: コードをチェックアウトする uses: actions/checkout@v4 - name: Python環境をセットアップする uses: actions/setup-python@v5 with: python-version: "3.11" - name: MoleculeとDockerドライバーをインストールする run: pip install ansible-core molecule molecule-plugins[docker] - name: Moleculeテストを実行する working-directory: roles/${{ matrix.role }} run: molecule test env: PY_COLORS: "1" ANSIBLE_FORCE_COLOR: "1"
needs: lintを設定することで、ansible-lintが通過したroleだけMoleculeテストを実行します。静的解析でNGになったコードをコンテナ起動の費用を使ってテストする無駄を省けます。2. PRチェックとキャッシュ最適化のTips
・pipキャッシュ:actions/cacheでpipパッケージをキャッシュするとジョブ時間を40%以上短縮できる・Dockerイメージのキャッシュ: GHA(GitHub Actions)上でDockerイメージをpullする時間が長い場合は
pre_build_image: falseにしてGHAキャッシュと組み合わせる方法もある・Branch protectionルール: リポジトリの設定でmainブランチのPRにansible-lintとMoleculeジョブのステータスチェックを必須化すると、CI通過前のマージを防げる
トラブルシュート|よくあるエラーと対処法
「yaml[truthy]: Use 'true' instead of 'yes'」が大量に出る
原因: 古いPlaybookやroleでyes/noを真偽値として使っている。YAML 1.2以降ではこれらは文字列として扱われる変更が行われており、ansible-lintはYAML 1.2準拠のルールで警告する。対処: プロジェクト全体を一括置換する。
# enabled: yes を enabled: true に一括置換(バックアップ付き) find . -name "*.yml" -not -path "./molecule/*" -exec sed -i.bak 's/: yes$/: true/g' {} \; # バックアップファイルを削除する find . -name "*.yml.bak" -delete
ansible-lintを再実行して他の違反がないことを確認してください。「TASK [Create molecule instance(s)] FAILED!」が出る
原因: Dockerデーモンが起動していない、または現在のユーザーがdockerグループに属していない。対処: 検証機でDockerの状態を確認する。
# Dockerデーモンの状態を確認する systemctl status docker # 起動していなければ起動する sudo systemctl start docker sudo systemctl enable docker # 現在のユーザーをdockerグループに追加する(再ログイン必要) sudo usermod -aG docker $USER # グループ変更を即時反映する(ログアウト不要) newgrp docker # 動作確認 docker run --rm hello-world
「Idempotence test failed」が出る
原因: 2回目のmolecule convergeでもchangedタスクが残っている。roleの設計が冪等でない箇所がある。典型的なパターンと対処法:
・
command/shellモジュールの無条件実行: createsパラメータかchanged_when/when条件を追加する# NG: 毎回変更ありになる - name: アーカイブを展開する ansible.builtin.command: tar xzf /tmp/app.tar.gz -C /opt/app # OK: 展開済みならスキップする - name: アーカイブを展開する ansible.builtin.command: tar xzf /tmp/app.tar.gz -C /opt/app args: creates: /opt/app/bin/app # このファイルが存在すればスキップ
ansible.builtin.templateやansible.builtin.copyでコンテンツが同一ならchangedにならない。差分が生まれているなら元ファイルとテンプレートの内容を見直す・サービス再起動の無条件実行:
notifyとhandlersを使って「設定ファイルが変更されたときのみ再起動」に変える本記事のまとめ
| やりたいこと | コマンド/設定 |
|---|---|
| ansible-lintをインストールする | pip install ansible-core ansible-lint |
| Playbookを静的解析する | ansible-lint site.yml |
| ルールをカスタマイズする | プロジェクトルートに.ansible-lintを配置する |
| MoleculeとDockerドライバーをインストールする | pip install molecule molecule-plugins[docker] |
| 新規roleとMoleculeシナリオを生成する | molecule init role --driver-name docker role名 |
| 既存roleにMoleculeシナリオを追加する | molecule init scenario --driver-name docker default |
| テストの全フェーズを一括実行する | molecule test |
| convergeだけ実行する(開発中のデバッグ) | molecule converge |
| 冪等性チェックだけ実行する | molecule idempotence |
| verify.ymlの検証タスクだけ実行する | molecule verify |
「変更するたびに本番で何かが壊れるかもしれない」という不安から解放され、安心してroleを改善し続けられる開発体制への第一歩です。
Ansible実践ハンズオンの詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 前のページへ:Ansibleの変数優先順位と設定スコープを整理する|vars・defaults・group_vars・host_varsの使い分け
- この記事の属するカテゴリ:Ansibleへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます