はじめに
Ansibleを使って構成管理していると、よくあるパターンとして、「templatesモジュールでconfファイルを配置して更新があればrestartする」というのがあります。
Playbookとしては似たようなパターンなのにconfファイルごとにいちいち書き分けるのは非効率です。
下記のようにvarsとwith_dictを使うことで、一つのRoleで複数のミドルウェア、複数のconfファイルの管理に対応できます。
メリット
ループするのならwith_items
でもできますが、with_dict
にするのには理由があります。
それは、別のvarsで特定の設定ファイルのパラメータを上書きしたい時に便利だからです。
with_items
だと、親要素単位で上書きされてしまうため、差分のない箇所も重複して定義する必要があります。
例えば、本記事のようにconfig_file
についてwith_items
でループさせた場合、middleware_conf2
にだけ差分がある場合でもmiddleware_conf
も再度定義する必要があります。これは親要素のconfig_file
単位で上書きされてしまうためです。
with_dict
を使うと、config_file
配下のmiddleware_conf
、middleware_conf2
単位での上書きが可能になります。
本番環境とステージング環境で特定の設定ファイルのパラメータだけ違う、というような場合に差分だけ上書きできるので効率よくパラメータ管理ができます。
前提
ansible.cfgに下記が設定されていること
[defaults]
hash_behaviour = merge
sample
ディレクトリ構成
site.yml
roles/
|--put_conf_and_restart/
| |--handlers/
| | |--main.yml
| |--tasks/
| | |--main.yml
| |--templates/
| | |--middleware.conf.j2
| | |--middleware.conf2.j2
group_vars/
|--targetgroup.yml
host_vars/
|--targethost.yml
vars
varsの記載箇所は環境に合わせてください。まずはgroup_varsで定義します。
---
my_vars:
middlewares:
middleware:
service:
name: middleware
configs:
config_file:
middleware_conf:
template: middleware.conf.j2
owner: user
group: group
mode: '0644'
path: /path/to/middleware.conf
params:
parameter: PARAMETER
middleware_conf2:
template: middleware.conf2.j2
owner: user
group: group
mode: '0644'
path: /path/to/middleware2.conf
params:
parameter2: PARAMETER2
Role
with_dictでmy_vars.middlewares.middleware.configs.config_file以下でループさせています。配置したいconfファイルが複数ある場合でも、ここに複数定義することで対応できます。
テンプレートファイルはそれぞれ用意する必要があります。
なお、owner, group, modeについてはデフォルト値を用意しておくと、varsに定義がない場合デフォルト値が採用されるので便利です。
---
- name: put Middleware config files
template:
src: "{{ item.value.template }}"
dest: "{{ item.value.path }}"
owner: "{{ item.value.owner | default('root') }}"
group: "{{ item.value.group | default('root') }}"
mode: "{{ item.value.mode | default('0644') }}"
with_dict: "{{ my_vars.middlewares.middleware.configs.config_file }}"
notify:
- restart service
template
テンプレートについては、冒頭でmy_vars配下のそれぞれのconfファイルごとに定義したparamsの値が変数paramsにセットされます。
デフォルト値を用意しておくことで、my_varsに定義していないパラメータについてはデフォルト値が採用されます。
{% set params = item.value.params %}
{% if params.parameter is defined %}
parameter = {{ params.parameter }}
{% else %}
parameter = default value
{% endif %}
{% set params = item.value.params %}
{% if params.parameter2 is defined %}
parameter2 = {{ params.parameter2 }}
{% else %}
parameter2 = default value
{% endif %}
handlers
handlersについては、定義したservice.nameに基づいてrestartをかけます。
---
- name: restart service
service:
name: "{{ my_vars.middlewares.middleware.service.name }}"
state: restarted
when: not ansible_check_mode
site.yml
---
- hosts: targethost
roles:
- role: put_conf_and_restart
差分をhost_varsに定義してgroup_varsを上書きする
ここでgroup_varsで定義した変数をhost_varsで上書きする例を見てみましょう。
Ansibleでは、varsの記載箇所によって採用される優先度が変わります。
参考:公式ドキュメント
group_varsよりhost_varsの方が優先度が高いので、同じ項目が両方に定義されていた場合、host_varsの値に「上書き」されます。
例えばmiddleware_conf2のみに差分がある場合、host_varsに下記のように定義すればOKです。
(ここではparameter2の値が異なる)
---
my_vars:
middlewares:
middleware:
configs:
config_file:
middleware_conf2:
template: middleware.conf2.j2
owner: user
group: group
mode: '0644'
path: /path/to/middleware2.conf
params:
parameter2: PARAMETER2_HOST
こうすることで、共通するmiddleware.confのパラメータはgroup_varsの値を採用しつつ、差分であるmiddleware_conf2のパラメータのみを上書きすることができます。