「同じ設定を複数のPlaybookにコピーしているが、修正のたびに全箇所を書き直す羽目になっている」
こうした課題の答えが Ansible role(ロール) です。roleはPlaybookの処理を機能単位で分割し、別のPlaybookでもそのまま再利用できるようにする仕組みです。Ansibleを本格的に使い始めたら、最初に覚えるべき設計パターンのひとつです。
この記事では、roleのディレクトリ構造から
ansible-galaxy initによる雛形作成、handlersとdefaultsの使い方まで、実際のサーバーでの実行結果とともに解説します。実行環境:Rocky Linux 9.4 / Ansible 2.16.3(コントロールノード)、管理対象:Rocky Linux 9.4
この記事のポイント
・ansible roleはPlaybookを機能単位に分割・再利用する仕組み
・ansible-galaxy initコマンドでディレクトリ雛形を一瞬で生成できる
・handlers/notifyでサービス再起動を冪等に管理できる
・defaultsは外部から上書き可能、varsは上書きを抑制する役割
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜroleが必要なのか?Playbookの肥大化問題を整理する
Ansibleを使い始めた当初は、1つのPlaybookファイルにすべてのタスクを書き並べるスタイルで十分に動きます。しかしサーバーの台数や管理対象の設定項目が増えてくると、Playbookが200行・300行を超えるようになり、以下の問題が表面化します。・どのタスクがどのホストに対する処理なのか、ひと目で判断しにくい
・Webサーバー設定とDBサーバー設定が1ファイルに混在して見通しが悪い
・「この処理を別のプロジェクトでも使いたい」という場合にコピーしか手段がない
roleを使うと、「Webサーバー設定」「NTP設定」「セキュリティ強化」といった機能単位でコードを分割できます。分割したroleはPlaybookからシンプルに呼び出せるため、再利用・テスト・チーム共有のいずれも格段に楽になります。Ansible Galaxyで公開されているコミュニティroleもこの構造を採用しており、業界標準の設計パターンと言えます。
roleのディレクトリ構造と各サブディレクトリの役割
1. 標準ディレクトリ構成
roleは以下のディレクトリ構造で構成されます。すべてのディレクトリが必須ではなく、必要なものだけ作成すればOKです。roles/ └── webserver/ # role名 ├── tasks/ │ └── main.yml # メインのタスクリスト(必須) ├── handlers/ │ └── main.yml # notifyで呼び出されるハンドラ ├── defaults/ │ └── main.yml # 上書き可能なデフォルト変数(最低優先度) ├── vars/ │ └── main.yml # 上書きを想定しない変数(高優先度) ├── files/ # copyモジュールで配布するファイル ├── templates/ # templateモジュールで使うJinja2テンプレート └── meta/ └── main.yml # roleのメタ情報・依存関係の定義
・tasks/main.yml:roleの本体。実行するタスクをここに書く
・handlers/main.yml:タスクから
notifyされたときだけ実行されるタスク。サービス再起動などに使う・defaults/main.yml:変数のデフォルト値。Ansibleの変数優先順位で最も低く、Playbook側や
group_varsから上書きできる・vars/main.yml:roleが内部で使う変数。優先順位が高く、外部からの上書きを抑制したい値に使う
・files/:静的ファイルを置く。
copyモジュールで参照する際はパスを省略できる・templates/:Jinja2テンプレートファイルを置く。
templateモジュールで動的な設定ファイルを生成するときに使う2. ansible-galaxy initで雛形を自動生成する
ディレクトリを手作業で作る必要はありません。ansible-galaxy initコマンドが雛形を一瞬で生成してくれます。# webserverという名前のroleを作成する ansible-galaxy init webserver
[ansible@ctrl01 roles]$ ansible-galaxy init webserver - Role webserver was created successfully [ansible@ctrl01 roles]$ find webserver -type f webserver/README.md webserver/defaults/main.yml webserver/handlers/main.yml webserver/meta/main.yml webserver/tasks/main.yml webserver/tests/inventory webserver/tests/test.yml webserver/vars/main.yml webserver/.travis.yml
main.ymlに内容を書いていくだけです。
最小構成のroleを実際に作る実践手順
ここでは「Apacheをインストールして設定を展開し、サービスを起動する」というWebサーバーroleを例に、基本的な書き方を示します。1. tasks/main.ymlにタスクを書く
# roles/webserver/tasks/main.yml --- - name: httpd をインストールする ansible.builtin.dnf: name: httpd state: present - name: httpd.conf を配置する ansible.builtin.template: src: httpd.conf.j2 dest: /etc/httpd/conf/httpd.conf owner: root group: root mode: '0644' notify: restart httpd # 変更があった場合はhandlerを呼ぶ - name: httpd を起動・自動起動有効化 ansible.builtin.service: name: httpd state: started enabled: true
2. handlersとnotifyで再起動を冪等に制御する
handlersはタスクからnotifyされたときだけ実行される仕組みです。設定ファイルが変更された場合にだけサービスを再起動するため、何度実行しても余分な再起動が発生しない冪等な設計が実現できます。# roles/webserver/handlers/main.yml --- - name: restart httpd ansible.builtin.service: name: httpd state: restarted
notify: restart httpdと書いた場合、handlers/main.yml内のname: restart httpdと完全に一致している必要があります。大文字・小文字の違いもエラーの原因になるので注意してください。handlerはPlayの最後にまとめて実行されます。同一のhandlerが複数のタスクからnotifyされても、実行は1回だけです。これがhandlerを使う最大の利点です。
3. defaultsとvarsの使い分け
roleで使う変数はdefaultsとvarsの2箇所に書けますが、役割が異なります。# roles/webserver/defaults/main.yml # 外部から上書き可能なデフォルト値(推奨) --- http_port: 80 server_name: "{{ ansible_hostname }}" document_root: /var/www/html
# roles/webserver/vars/main.yml # 上書きを抑制したいrole内部変数 --- httpd_config_path: /etc/httpd/conf/httpd.conf httpd_package: httpd
group_vars・host_varsのどれからでも上書きできます。ユーザーがroleの動作をカスタマイズしたい値(ポート番号、ドキュメントルートなど)はここに書くのがベストプラクティスです。varsは優先順位が高く、外部から上書きするにはかなり高優先度の変数指定が必要です。role内部でのみ使う固定的な値(パッケージ名、設定ファイルパスなど)はこちらに書きます。
Ansible実践ハンズオンの詳細を見る >>
roleをPlaybookから呼び出す方法
1. rolesキーで呼び出す(標準的な書き方)
Playbook内にroles:セクションを設けて呼び出します。最もシンプルで可読性が高い方法です。# site.yml --- - name: Webサーバーをセットアップする hosts: webservers become: true roles: - webserver # roles/webserver/ を呼び出す
roles/フォルダを置くか、ansible.cfgのroles_pathで検索パスを設定することで自動的に認識されます。2. include_roleタスクで動的に呼び出す
条件分岐やloopと組み合わせてroleを呼び出したい場合はinclude_roleを使います。# 条件付きでroleを適用する例 - name: 本番環境でのみセキュリティroleを適用する ansible.builtin.include_role: name: security_hardening when: env == 'production'
[ansible@ctrl01 ~]$ ansible-playbook -i inventory/hosts site.yml PLAY [Webサーバーをセットアップする] ************************************ TASK [Gathering Facts] **************************************************** ok: [web01.example.internal] TASK [webserver : httpd をインストールする] ******************************** changed: [web01.example.internal] TASK [webserver : httpd.conf を配置する] *********************************** changed: [web01.example.internal] TASK [webserver : httpd を起動・自動起動有効化] **************************** changed: [web01.example.internal] RUNNING HANDLERS [webserver : restart httpd] ******************************** changed: [web01.example.internal] PLAY RECAP ***************************************************************** web01.example.internal : ok=5 changed=4 unreachable=0 failed=0
RUNNING HANDLERSの行に注目してください。設定ファイルが変更されたためhandlerが自動で実行されています。2回目の実行では設定ファイルに変化がなければhandlerは実行されません。これが冪等な設計です。よくあるエラーとトラブルシュート
エラー1: ERROR! the role 'webserver' was not foundroleが見つからないエラーです。Playbookファイルからの相対パスに
roles/webserver/ディレクトリが存在するか確認してください。またはansible.cfgのroles_path設定を確認します。# ansible.cfg に検索パスを追加する [defaults] roles_path = ./roles:/etc/ansible/roles
handler名に誤字がある場合に起こります。
notify:に書いた文字列とhandlers/main.ymlのname:が1文字も違わず一致しているか確認してください。また、タスクのステータスがok(変更なし)の場合はhandlerは呼ばれません。タスクがchangedにならないとnotifyがトリガーされない仕組みです。エラー3: defaultsの変数が上書きできない
vars/main.ymlに書いた変数は優先順位が高いため、通常の
group_varsでは上書きできません。外部から上書きしたい値はdefaults/main.ymlに移動させてください。本記事のまとめ
| 役割 | ファイル・方法 |
|---|---|
| role雛形を自動生成する | ansible-galaxy init ロール名 |
| メインタスクを書く | roles/ロール名/tasks/main.yml |
| 再起動などを冪等に制御する | roles/ロール名/handlers/main.yml |
| 上書き可能なデフォルト変数 | roles/ロール名/defaults/main.yml |
| 上書きを抑制する内部変数 | roles/ロール名/vars/main.yml |
| roleをPlaybookから呼ぶ | roles:キーまたはinclude_roleタスク |
Ansible実践ハンズオンの詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AnsibleのWindows管理入門|WinRM設定とansible.windows collectionで混在環境を自動化する方法
- この記事の属するカテゴリ:Ansibleへ戻る

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