2026年6月1日

2026年6月1日

Ansibleのロール(Role)の作成と活用|ディレクトリ構成・変数の置き場所・再利用の方法

Ansibleのロールは、「Nginxを入れて設定する」「PHP-FPMを調整する」といった1つの役割に必要なタスク、変数、テンプレート、ハンドラーを決まったディレクトリ構成にまとめたものです。ロールに分けておくと、長くなったプレイブックが読みやすくなり、別のサーバーや別のプロジェクトでも同じ部品を使い回せます。この記事では、Nginxのロールを例に、ひな形の作成、変数の置き場所の決め方、プレイブックからの呼び出し方、外部ロールの取り込み、テストまでを説明します。

プレイブックの基本(インベントリや ansible-playbook の実行方法)は分かっている前提で進めます。

ロールに分けるべきタイミング

1つのプレイブックに数十個のタスクが並び、「どこまでがNginxの設定で、どこからがPHPか」が見た目で分からなくなってきたら、ロールに分ける時期です。また、本番とステージング、あるいは複数のサイトで同じ設定を少しずつ値を変えて使いたい場合も、ロールにすると変数だけを差し替えて再利用できます。

逆に、1回きりの作業や数行で終わる処理まで無理にロール化すると、ファイルが分散してかえって追いにくくなります。「繰り返し使うか」「独立した役割として説明できるか」を基準にすると判断しやすくなります。

ひな形を作る

ロールのディレクトリは手で作ってもかまいませんが、ansible-galaxy コマンドで標準のひな形を生成できます。

mkdir -p roles
ansible-galaxy role init roles/nginx

生成される主なディレクトリと役割は次のとおりです。

roles/nginx/
├── defaults/main.yml   # 利用者が上書きしてよい既定値
├── vars/main.yml       # ロール内部で使う固定値
├── tasks/main.yml      # 実行するタスク本体
├── handlers/main.yml   # 変更時に呼ばれる処理(再読み込みなど)
├── templates/          # Jinja2 テンプレート(.j2)
├── files/              # そのままコピーするファイル
├── meta/main.yml       # 作者情報・依存ロール
├── tests/              # 簡易テスト用
└── README.md

使わないディレクトリは削除してかまいません。Ansibleは各ディレクトリの main.yml を自動で読み込むので、tasks/main.yml や handlers/main.yml のパスを自分で指定する必要はありません。

タスク・テンプレート・ハンドラーを書く

まずタスク本体です。Ubuntuを想定し、Nginxを入れてサイト用の設定ファイルを置きます。

# roles/nginx/tasks/main.yml
- name: Nginx をインストールする
  ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true
    cache_valid_time: 3600

- name: サイト設定を置く
  ansible.builtin.template:
    src: site.conf.j2
    dest: "/etc/nginx/conf.d/{{ nginx_site_name }}.conf"
    owner: root
    group: root
    mode: "0644"
  notify: Reload nginx

- name: Nginx の設定を検証する
  ansible.builtin.command: nginx -t
  changed_when: false

- name: Nginx を起動し、自動起動を有効にする
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: true

テンプレートは templates/ に置き、src にはファイル名だけを書きます。ロール内のテンプレートは自動で templates/ から探されます。

# roles/nginx/templates/site.conf.j2
# {{ ansible_managed }}
server {
    listen 80;
    server_name {{ nginx_server_name }};
    root {{ nginx_document_root }};
    index index.html;

    client_max_body_size {{ nginx_client_max_body_size }};

    location / {
        try_files $uri $uri/ =404;
    }
}

WordPressのようにPHPを動かす場合は、PHP-FPMへ渡す location を別途足します。PHP側の設定はPHPのロールに分け、Nginxのロールは「静的な配信と共通設定」に絞ると、役割の境界がはっきりします。

ansible_managed は「このファイルはAnsibleが管理している」という注記を入れるための変数です。サーバー上で誰かが手で直接編集してしまうと、次回の実行で上書きされます。その事故を防ぐ目印になります。

ハンドラーは、設定ファイルに変更があったときだけ呼ばれる処理です。

# roles/nginx/handlers/main.yml
- name: Reload nginx
  ansible.builtin.service:
    name: nginx
    state: reloaded

ここで nginx -t をタスクとして挟んでいるのには理由があります。ハンドラーはプレイの最後にまとめて実行されるため、テンプレートの書き損じがあると、壊れた設定で再読み込みが走るおそれがあります。検証タスクが失敗すればプレイはその場で止まり、ハンドラーは実行されません。

defaults と vars の使い分け

ロールで最も迷いやすいのが変数の置き場所です。ポイントは「優先順位の違い」にあります。

  • defaults/main.yml は変数の優先順位が最も低い場所です。インベントリの group_vars、プレイの vars、コマンドラインの -e など、ほかのどこで指定しても上書きされます。
  • vars/main.yml はそれより高い優先順位を持ち、group_vars などからは上書きされにくくなります。

このため、**利用者が変えてよい値は defaults、ロールの内部事情で決まり外から変えてほしくない値は vars** に置くのが基本です。ここを逆にすると、「group_vars で値を変えたのに反映されない」という分かりにくい問題が起きます。

# roles/nginx/defaults/main.yml
nginx_site_name: example
nginx_server_name: example.com
nginx_document_root: /var/www/example
nginx_client_max_body_size: 64m

変数名の先頭にロール名(nginx_)を付けておくと、複数のロールを組み合わせたときに同名の変数が衝突するのを防げます。ansible-lint もロール名の接頭辞を付けることを推奨しています。

ロールに渡す変数の型や必須項目を検証したい場合は、meta/argument_specs.yml に仕様を書いておくと、ロールの実行前にチェックされます。

# roles/nginx/meta/argument_specs.yml
argument_specs:
  main:
    short_description: Nginx とサイト設定を入れる
    options:
      nginx_server_name:
        type: str
        required: true
        description: server_name に入れるホスト名
      nginx_client_max_body_size:
        type: str
        default: 64m
        description: アップロードの上限サイズ

プレイブックからロールを呼び出す

ロールを使う方法は大きく3つあります。

# site.yml
- name: Web サーバーを構成する
  hosts: web
  become: true
  roles:
    - role: nginx
      vars:
        nginx_server_name: blog.example.com
        nginx_document_root: /var/www/blog

roles: に並べる方法が最も基本的で、プレイの tasks: より先に実行されます。順番を細かく制御したい場合は、タスクの中で呼び出します。

  tasks:
    - name: 共通設定のあとで Nginx ロールを適用する
      ansible.builtin.import_role:
        name: nginx

    - name: 条件に応じて PHP ロールを適用する
      ansible.builtin.include_role:
        name: php
      when: install_php | default(false)

import_role はプレイブックを読み込んだ時点で展開される静的な取り込み、include_role は実行時に評価される動的な取り込みです。when や loop で実行するかどうかを切り替えたいときは include_role が向いています。import_role に when を付けると、ロール内の全タスクそれぞれに条件が付く動きになり、意図と異なる結果になることがあります。

なお、ロールを置く場所は、プレイブックと同じ階層の roles/ が既定で探されます。別の場所に置く場合は ansible.cfg の roles_path で指定します。

外部のロールやコレクションを取り込む

よく使われる構成なら、自分で書かずにAnsible Galaxyで公開されているロールを利用する手もあります。ただし、公開ロールは作者によって保守状況や対応OSがまちまちです。最終更新日、対応するOSの版、ソースコードを確認し、本番に入れる前にテスト環境で動作を見てから採用してください。

使うロールとコレクションは requirements.yml に版を固定して書いておくと、別の人や別のPCでも同じ組み合わせを再現できます。

# requirements.yml
roles:
  - name: internal_php
    src: https://github.com/your-org/ansible-role-php.git
    scm: git
    version: v1.2.0

collections:
  - name: community.general
  - name: ansible.posix
ansible-galaxy role install -r requirements.yml
ansible-galaxy collection install -r requirements.yml

version にブランチ名ではなくタグやコミットを指定しておくと、相手のリポジトリが更新されても勝手に中身が変わりません。

ロールをテストする

ロールを複数の場所で使うようになると、1か所の修正がほかの環境を壊していないかが気になります。まず手軽なのは次の確認です。

  • ansible-lint で書き方の問題(非推奨の書き方、FQCNでないモジュール名、冪等でない command など)を拾う
  • ansible-playbook site.yml --check --diff で変更内容を事前に見る
  • テスト用サーバーで2回実行し、2回目が changed=0 になることを確かめる

本格的に自動化したい場合は、Molecule というテスト用ツールがあり、コンテナや仮想マシンを立ててロールを適用し、結果を検証する流れを組めます。設定ファイルの書式や対応ドライバーは版によって変わるため、導入時は公式ドキュメントを参照してください(2026年10月現在)。

まとめ

  • ロールはタスク・変数・テンプレート・ハンドラーを決まった構成にまとめた再利用の単位で、ansible-galaxy role init でひな形を作れます。
  • 利用者が変えてよい値は defaults、内部の固定値は vars に置きます。逆にすると上書きが効かない原因になります。変数名にはロール名の接頭辞を付けます。
  • 設定ファイルを置いたら検証コマンドを挟み、再読み込みはハンドラーに任せると、壊れた設定が反映されるのを防げます。
  • 呼び出しは roles:、静的な import_role、動的な include_role を目的で使い分けます。
  • 外部ロールは保守状況を確かめ、requirements.yml で版を固定します。ansible-lint と2回実行で冪等性を確認します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲