【Ansible応用講座 第5回】品質を保証する。MoleculeによるRoleの自動テストとCI連携完全ガイド

「動くかどうかは、運次第」からの脱却。

こんにちは!「LINUX工房」管理人の「リナックス先生」です。
前回は、Pythonを使ってAnsibleを拡張するカスタムモジュールの開発を行いました。

さて、あなたが苦労して作り上げた最強のRole。これ、「半年後も確実に動く」と保証できますか?
OSのバージョンが上がったり、依存ライブラリが変わったり、あるいはチームメンバーがうっかり変な修正を加えたり…。
「久しぶりに実行したらエラーで止まって、冷や汗をかいた」という経験は、エンジニアなら誰しもあるはずです。

コウ君

先生、耳が痛いです…。
この前、先輩が作ったRoleを使おうとしたら全然動かなくて。
直そうと思っても、どこを直すと他に影響が出るか分からなくて、結局ゼロから作り直しちゃいました。
プログラムみたいに「テスト」ができればいいんですけど、サーバー構築のテストってどうやるんですか? まさか毎回サーバー立てて壊すんですか?

リナックス先生

その「まさか」を全自動でやるのが、今回のテーマ「Molecule(モレキュール)」よ。
Dockerコンテナを一瞬で立ち上げて、Ansibleを実行して、正しく設定されたかチェックして、最後に破棄する。
これをコマンド一発、あるいはGitにプッシュするたびに自動でやってくれるの。
これができれば、インフラエンジニアとしての信頼度は爆上がりよ!

本記事では、AlmaLinux 9 をベースに、Ansible専用テストフレームワーク Molecule の導入、テストシナリオの作成、そして GitHub Actions と連携したCIパイプラインの構築までを徹底解説します。

🚀 Ansible応用講座(全8回)

現在地:【第5回】品質を保証する。MoleculeによるRoleの自動テストとCI連携


第1章:Molecule(モレキュール)とは何か?

Moleculeは、AnsibleのRole(ロール)を開発・テストするための公式プロジェクトです。
「インフラコードの単体テストツール」とイメージしてください。

Moleculeがやってくれること

molecule test というコマンドを叩くだけで、以下のフローを全自動で行います。

  1. Dependency: 依存するRoleをGalaxyからダウンロード。
  2. Lint: 構文チェック(yaml-lint, ansible-lint)を実行。
  3. Create: テスト用の環境(DockerコンテナやVagrant VMなど)を作成。
  4. Converge: 作成した環境に対してPlaybookを実行。
  5. Idempotence: もう一度Playbookを実行し、変更(Changed)がないか確認(冪等性チェック)。
  6. Verify: サーバーの状態(ポートが開いているか、ファイルがあるか等)を検証。
  7. Destroy: テスト環境を削除。

これを手動でやろうとすると大変ですが、Moleculeなら一瞬です。

なぜDockerを使うのか?

VM(仮想マシン)を立ち上げるのは時間がかかりますが、Dockerコンテナなら数秒で起動します。
Systemdが使えるコンテナイメージを利用することで、本物のサーバーに近い環境で高速にテストを回すことができます。


第2章:テスト環境の構築 (Docker + Molecule)

まずは、コントロールノード(あなたのPCや開発サーバー)に環境を作ります。
ここではPythonとDockerがインストールされている前提で進めます。

1. 必要なパッケージのインストール

Molecule本体と、Dockerを操作するためのドライバをインストールします。

pip install molecule molecule-docker docker ansible-lint
  • molecule: 本体
  • molecule-docker: Dockerドライバ
  • docker: Python用のDocker SDK
  • ansible-lint: 構文チェッカー

2. Dockerの動作確認

Dockerが動いており、sudoなしで実行できることを確認してください。

docker ps
# エラーが出なければOK

第3章:【実践】既存Roleへのテスト追加

ゼロからRoleを作る場合は molecule init role my_role を使いますが、今回は「すでにあるRole」にテスト環境を追加する手順を紹介します。
実務ではこちらの方が圧倒的に多いはずです。

1. シナリオの初期化

テストしたいRoleのディレクトリ(例: roles/apache)に移動し、以下のコマンドを実行します。

cd roles/apache
molecule init scenario --driver-name docker

すると、Roleの中に molecule/default/ というディレクトリが生成されます。
これがテストの設定ファイル群です。

roles/apache/
├── molecule/
│   └── default/
│       ├── molecule.yml    # 全体の設定
│       ├── converge.yml    # テスト実行用Playbook
│       └── verify.yml      # 検証コード
├── tasks/
│   └── main.yml
...

2. molecule.yml の設定(コンテナ定義)

どのようなコンテナを立ち上げるかを定義します。
今回はSystemdが使える AlmaLinux 9 のイメージを指定します。

molecule/default/molecule.yml を編集します。

---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: instance
    image: geerlingguy/docker-almalinux9-ansible
    # Systemdを動かすための特権設定
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:rw
    cgroupns_mode: host
    privileged: true
    pre_build_image: true
provisioner:
  name: ansible
verifier:
  name: ansible

ポイント: Jeff Geerling氏(Ansible界の有名人)が公開している geerlingguy/docker-almalinux9-ansible イメージを使うと、コンテナ内でSystemdが使えるため、service モジュールのテストが容易になります。

3. converge.yml の確認

これは「テスト時に実行されるPlaybook」です。
デフォルトでは「対象のRoleをインクルードする」だけになっています。通常はそのままでOKです。

---
- name: Converge
  hosts: all
  tasks:
    - name: "Include apache"
      include_role:
        name: "apache"

第4章:テストの実行と検証コードの記述

準備ができたら、一度動かしてみましょう。

1. コンテナ作成とPlaybook実行 (converge)

いきなり test コマンドを叩くと、成功時にコンテナが消えてしまいデバッグできません。
まずは converge で「作成〜実行」までを行います。

molecule converge

Dockerイメージのプル、コンテナ起動、そしてRoleの実行が行われます。
エラーが出なければ、コンテナ内でApacheのインストール等が完了しているはずです。

2. コンテナへのログイン

起動中のテスト用コンテナに入って中身を確認できます。

molecule login

シェルに入ったら、systemctl status httpd や curl localhost などで動作確認ができます。
確認したら exit で抜けます。

3. 検証コードの記述 (verify.yml)

手動確認でOKなら、その確認作業を自動化しましょう。
以前は Testinfra というPythonライブラリを使うのが主流でしたが、現在はAnsible自体で検証を行う Ansible Verifier が推奨されています。
学習コストが低く、Ansibleのモジュール知識がそのまま使えるのがメリットです。

molecule/default/verify.yml を編集します。

---
- name: Verify
  hosts: all
  gather_facts: false
  tasks:
    - name: Check if httpd is running
      ansible.builtin.service_facts:

    - name: Assert httpd state
      ansible.builtin.assert:
        that:
          - ansible_facts.services['httpd.service'].state == 'running'
          - ansible_facts.services['httpd.service'].status == 'enabled'

    - name: Check HTTP response
      ansible.builtin.uri:
        url: http://localhost
        return_content: yes
      register: webpage

    - name: Assert content
      ansible.builtin.assert:
        that:
          - "'Hello Ansible' in webpage.content"

ここでは service_facts モジュールでサービスの状態を取得し、assert モジュールで期待値と比較しています。
また、uri モジュールで実際にアクセスしてコンテンツをチェックしています。

4. 検証の実行 (verify)

検証コードだけを実行します。

molecule verify

すべて緑色(OK)になれば、テスト合格です!

5. フルテスト (test)

最後に、破棄から再構築、冪等性チェックまで含めたフルコースを実行します。

molecule test

これが通れば、あなたのRoleは「品質保証済み」です。

💡 プロの視点:冪等性テストの重要性
Moleculeはデフォルトで Idempotence check を行います。
「2回実行して Changed が出たらテスト失敗」と判定されます。
これにより、「設定変更していないのに毎回再起動してしまう」といった品質の低いRoleを排除できます。
このチェックを通すことは、実務において非常に重要です。


第5章:CI/CDパイプラインへの統合 (GitHub Actions)

手元のPCでテストが通っても、チームメンバーがテストを実行するとは限りません。
コードをGitHubにプッシュしたら、クラウド上で勝手にテストが走るようにしましょう。

ワークフローファイルの作成

リポジトリの .github/workflows/molecule.yml を作成します。

name: Molecule Test

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10"]

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}

      - name: Install dependencies
        run: |
          pip install molecule molecule-docker docker ansible-lint

      - name: Run Molecule tests
        run: molecule test
        env:
          ANSIBLE_FORCE_COLOR: '1'  # ログに色をつける

これだけで世界が変わる

このファイルをコミットしてプッシュすると、GitHubの「Actions」タブでテストが走り出します。
これ以降、誰かがバグを含んだコードをPR(プルリクエスト)しようとしても、テストが失敗して「×」が付くため、マージを阻止できます。

これが「品質をシステムで担保する」ということです。


第6章:トラブルシューティングとTips

Molecule導入時によくある悩みと解決策です。

Q1. Systemdが動かない (Failed to get D-Bus connection)

原因: Dockerコンテナは通常Systemdを持っていません。
対策: molecule.yml で privileged: true にし、/sys/fs/cgroup をマウントする必要があります(第3章の設定を参照)。また、イメージもSystemd対応のもの(geerlingguy製など)を使うのが近道です。

Q2. テストが遅い

原因: 毎回Dockerイメージをプルしていたり、依存パッケージのインストールに時間がかかっています。
対策:
1. GitHub Actionsのキャッシュを使って、pipのインストール時間を短縮する。
2. 必要なツールをあらかじめ入れたカスタムDockerイメージを作成し、それを使ってテストする。

Q3. 特定のタスクだけ冪等性チェックで失敗する

原因: command モジュールなどで、常にChangedになってしまうタスクがある。
対策: changed_when を適切に設定するか、テスト時だけスキップするタグ(molecule-notestなど)を付けて回避します。


まとめ:自信を持ってデプロイするために

お疲れ様でした!
これで、あなたのAnsibleコードは「いつ誰が実行しても動くことが保証された」堅牢な資産となりました。

今回の重要ポイント:

  • Moleculeを使えば、コンテナを使ってRoleの単体テストができる。
  • verify.yml でインフラの状態をアサーション(検証)する。
  • GitHub Actionsと連携して、プルリクエストのたびにテストを回す。
  • 冪等性テスト(Idempotence)は品質保証の要。

「テストコードを書く時間がない」と言う人がいますが、手動で何度も確認したり、障害対応に追われたりする時間に比べれば、テストを書く時間は微々たるものです。
自動テストは、未来のあなたとチームを守る最強の盾になります。

さて、ここまではLinuxサーバーの話が中心でしたが、企業のインフラには「Windowsサーバー」も存在します。
「AnsibleってLinux専用でしょ?」と思っていませんか? 実はWindowsもバリバリ管理できるんです。

次回、応用講座 第6回は「Windowsも支配する。WinRM接続とPowerShell操作の完全ガイド」です。
SSHではなく WinRM を使った接続方法、Windows特有のモジュール、そしてPowerShellスクリプトとの連携など、Windows管理者のためのAnsible術を伝授します。
Active Directory環境の自動化などに興味がある方は必見です。お楽しみに!

▼ テスト駆動開発(TDD)を始める ▼

Docker環境で実験
「VPS」で自分専用環境

おすすめVPSを見る

品質保証のプロへ
「ITエンジニア転職」

転職エージェントを見る

コメント