概要
掲題をテーマに自社クラウドサービスの運用で培った経験をもとに紹介したいと思います。
あくまでも一つの考え方として参考になれば幸いです。
もし、皆さんの考え方やお勧めがありましたら是非共有して頂けると嬉しいです!
はじめに
Ansibleを習いたての頃はタスクの再利用性を考慮してできるだけRole化していました。むしろ、再利用性を高めるためにはRole化しかないと思っていた。
しかし、簡単な処理もRole化したことにより、handlers、templates、filesなどがないtasksしかないRoleが大量に出来上がったことでフォルダ構成が深くなり、管理しづらい状況でした。また、とあるRoleの一部のタスクを流用したい時にimport_role
のtasks_from
やvars_from
などを使用することでrole内の一部のタスクを再利用できるが、前述のようにフォルダ構成が深くなり、常用的にタスクを再利用しようとした時に検索性が悪い。(ファイル構成を参照)
なので、再利用性を考慮しつつタスクの粒度について以下で紹介したいと思います。
結論
1から順にタスクを構成していくと管理しやすくなると思います。
そして、すべてに共通で言えるのが、横断的にtagsを付与することが大事!
- 再利用しないタスクはそのままベタ書き
- 再利用するタスクはタスクファイルに分割し、
import_tasks
で読み込む - いくつかの処理が複数集まって役割として機能するようになったらRole化し、role内のタスクでも
import_tasks
でタスクを読み込む
具体例
以下の一連の処理を例に説明したいと思います。
※以下はあくまでも流れを説明するためのコードで、動作確認はしていません。
- Apacheのインストール
- Apacheの設定ファイルの展開
- サービスの起動
- コンテンツの配置
そのままplaybookにするとこんな感じになります。
---
- hosts: webservers
remote_user: root
tasks:
- name: Apacheの最新版をインストール
yum:
name: httpd
state: latest
- name: 設定ファイルを展開
template:
src: httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: Apacheサービスの起動
service:
name: httpd
state: started
enabled: yes
- name: コンテンツの配置
copy:
src: hoge_dir
dest: htdocs
handlers:
- name: restart apache
service:
name: httpd
state: restarted
では、タスクファイル化するとどうなるかを見ていきましょう!
再利用するタスクはタスクファイルに分割し、import_tasks
で読み込む
実際は以下のように1タスクごとにタスクファイル化はしませんが、
以下の例のように一連のタスクを1タスクファイルにするとわかりやすいと思います。
また、tasks/httpd_service.yml
の一部のパラメータを変数化(_httpd_service_state
)したことで、呼び出し時に動的にパラメータを指定することで再利用性をさらに高めることができます。
タスクファイル=関数、パラメータ=引数と捉えると理解しやすいかと思います。ただし、変数名の命名規則は明確にしないと思わぬ上書き事故に見舞われるのでご注意!
---
- name: Apachの最新版をインストール
yum:
name: httpd
state: latest
---
- name: 設定ファイルを展開
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
---
- name: Apacheサービスの起動
service:
name: httpd
state: "{{ _httpd_service_state }}"
enabled: yes
---
- name: コンテンツの配置
copy:
src: "{{ _httpd_contents_path }}"
dest: htdocs
上記のタスクファイルを読み込むplaybookは以下のようになります。
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- import_tasks: ./tasks/httpd_install.yml
tags:
- httpd_install
- import_tasks: ./tasks/httpd_config.yml
tags:
- httpd_config
# サービスのstateを動的に指定
- set_fact:
_httpd_service_state: "started"
- import_tasks: ./tasks/httpd_service.yml
tags:
- httpd_service
# コンテンツの配置先のパスを動的に指定
- set_fact:
_httpd_contents_path: "hoge_dir"
- import_tasks: ./tasks/httpd_contents.yml
tags:
- httpd_contents
「タスクファイル」+「パラメータ化」の有効活用の例として、例えばhttpdサービスを停止する処理を追加したい時に、新たにサービス停止するタスクを追加せずに以下のように変数の値を変更するだけで、簡単にタスクの再利用が可能になります。
# サービスのstateを動的に指定
- set_fact:
_httpd_service_state: "stopped"
- import_tasks: ./tasks/httpd_service.yml
tags:
- httpd_service
単一処理ではないタスクファイルの例
上記のような単一処理ではなく、一連の処理をタスクファイル化した時の例になります。
AWSのEC2インスタンスのidをlistで取得する処理になります。
tag:Roleの値を変数化するとより可用性が高まるでしょう!
# EC2インスタンスのタグRole=Webのインスタンスを取得
- ec2_instance_facts:
filters:
tag:Role: "Web"
register: _instance_facts
# レスポンスをリストに整形
- set_fact:
_instance_ids: >-
{%- set ids = [] -%}
{%- for fact in _instance_facts.results -%}
{%- if fact.instances | length > 0 -%}
{%- for instance in fact.instances -%}
{%- set dummy = ids.append(instance.instance_id) -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{{ ids }}
いくつかの処理が複数集まって役割として機能するようになったらRole化し、共通のタスクもimport_tasks
で読み込む
role内も基本的にタスクファイルを再利用する!
上記の例では、handlersやtemplatesがありますが、初期段階でtasksしかない場合は、roleを作成せずにplaybookからはimport_tasks
にとどめ、handlersやtemplates、filesが必要になった段階(役割として機能実装が必要になったら)でRole化で良いかと思います。
---
- import_tasks: ../tasks/httpd_install.yml
- import_tasks: ../tasks/httpd_config.yml
- import_tasks: ../tasks/httpd_service.yml
- import_tasks: ../tasks/httpd_contents.yml
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- import_role:
name: httpd
tags:
- httpd
ファイル構成
前述のRoleのtasks_from
でタスクを読み込む場合は、各タスクファイル(install.yml)がRole配下になるので検索性が悪い。
また、例えば他のRole(hoge)からhttpdのinstall.ymlを呼び出す時のパス参照(../.../httpd
)が複雑になる。
一方タスクファイル化するとすべてのタスクファイルがフラットな構成になり、検索性、可視性が良くなる。
ファイル名に一定の命名規則を設けることが必要です。
ただし、tasksの配下をさらにフォルダ分けすると検索性が下がるのでお勧めしません。
- sample-playbook.yml
- roles
|- httpd
|-handlers
|-tasks
|- main.yml
|- install.yml
|- config.yml
|- service.yml
|- contents.yml
|-templates
|- hoge
- tasks
|- httpd_install.yml
|- httpd_config.yml
|- httpd_service.yml
|- httpd_contents.yml
タグ付け
タスクには極力付けして分類することをおすすめします!
既存の処理に一切影響ないので、今すぐにやってもいいと思います!
タグ付けの理由としては、例えば上記のsample-playbook.yml
のwebコンテンツ配置だけを再実行したい時(コンテンツを更新したい)にコンテンツ更新するPlaybookを再作成するとコードの冗長化になります。なので、こういう時は--tags="httpd_contents"
を加えるだけでスポット実行ができる!
import_tasksとinclude_tasksがあるので用法については注意!
import_tasksとinclude_tasks、import_roleとinclude_roleとありますが、動作に違いがありますので違いを理解しょう!
「Ansible 2.4 で import_tasks/include_tasks に tags を付けるときの注意点」をご参照ください!
コミュニティ
これから始める方なら安心の日本語でコミュニケーションができるので、興味がある方は是非ご参加ください。