ようへいの日々精進XP

よかろうもん

「Ansible 徹底入門」を読んでる途中だけど Ansible Callback Plugin(CloudWatch Logs にイベントを送信するプラグイン) を作ってみたのメモ

Ansible 徹底入門

www.shoeisha.co.jp

自分自身はまだ読んでいる途中ですが、Ansible をこれから利用しようと考えている方から、各種クラウド環境と組み合わせた一歩踏み込んだ利用を考えて方まで幅広い層の皆さんにお薦め出来ると思います。

燃えてキタ━━━━(゚∀゚)━━━━!!

Ansible 徹底入門を読み進めているうちに、燃えてきたので Ansible Callback Plugin(CloudWatch Logs にイベントを送信するプラグイン) を作ってみました。

Ansible Plugin について

以下の資料にまとめました。

speakerdeck.com

作った Ansible Plugin

github.com

Playbook の実行結果等を CloudWatch Logs に転送するやつです。

プラグインを実装するにあたり、logstash プラグインの実装を参考にさせて頂きました。ありがとうございます。

デモ

デモ環境

$ python --version
Python 2.7.13

$ ansible --version
ansible 2.2.1.0
  config file = /path/to/.ansible.cfg
  configured module search path = Default w/o overrides

プラグインの置き場

ansible.cfg で指定します。

[default]
callback_plugins = ~/path/to/plugins
callback_whitelist = cloudwatch_logs

callback_plugins に指定したディレクトリにプラグインを設置。設置しただけではダメのようで、callback_whitelist に利用したいプラグイン名を記述する必要があるとのことです。(実施に試してところ、callback_whitelist への記載が不要な挙動だったので引き続き調べたい)

Playbook

引き続き、前の記事で紹介した Datadog のタグを管理するモジュールを利用する Playbook を利用します。

- hosts: localhost
  tasks:
    - name: Test datadog_tags(present)
      datadog_tags:
        state: present
        host: myhost
        tags: 'aa,bb,cc,dd'
        api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    - name: Test datadog_tags(absent)
      datadog_tags:
        state: absent
        host: myhost
        api_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        app_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

プロビジョニング

$ ansible-playbook datadog.yml
 [WARNING]: Host file not found: /etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [Test datadog_tags(present)] **********************************************
changed: [localhost]

TASK [Test datadog_tags(absent)] ***********************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=2    unreachable=0    failed=0

CloudWatch Logs を確認

プラグインのデフォルトでは AWS_PROFILE は default が設定され、Log Group は ansible 及び Log Stream が provision が設定されます。

$ aws --profile ${AWS_PROFILE} --region ${AWS_REGION} \
  logs get-log-events \
    --log-group-name ansible --log-stream-name provision | jq '.events|sort_by(.timestamp)|.[-2,-1]'
{
  "ingestionTime": 1490456583837,
  "timestamp": 1490456583257,
  "message": "{'log_action': 'ansible ok', 'status': 'OK', 'host': 'myhost', 'session': 'b8891b28-1171-11e7-9524-3c15c2bdc014', 'ansible_type': 'task', 'ansible_playbook': 'datadog.yml', 'ansible_host': 'localhost', 'ansible_task': TASK: Test datadog_tags(present), 'ansible_result': '{\"changed\": false}'}"
}
{
  "ingestionTime": 1490456583837,
  "timestamp": 1490456583260,
  "message": "{'log_action': 'ansible stats', 'status': 'OK', 'host': 'myhost', 'session': 'b8891b28-1171-11e7-9524-3c15c2bdc014', 'ansible_type': 'finish', 'ansible_playbook': 'datadog.yml', 'ansible_result': '{\"localhost\": {\"ok\": 2, \"failures\": 0, \"unreachable\": 0, \"changed\": 0, \"skipped\": 0}}'}"
}

実装にあたり

Callback Plugin では以下のようなイベントをフックすることが出来ます。

$ grep v2_ plugins/cloudwatch_logs.py
    def v2_playbook_on_start(self, playbook):
    def v2_playbook_on_stats(self, stats):
    def v2_runner_on_ok(self, result, **kwargs):
    def v2_runner_on_skipped(self, result, **kwargs):
    def v2_playbook_on_import_for_host(self, result, imported_file):
    def v2_playbook_on_not_import_for_host(self, result, missing_file):
    def v2_runner_on_failed(self, result, **kwargs):
    def v2_runner_on_unreachable(self, result, **kwargs):
    def v2_runner_on_async_failed(self, result, **kwargs):

また、Python Logging のハンドラで CloudWatch Logs に転送出来る watchtower を利用することで、Logging のインターフェースを利用しています。(参考にした logstash プラグインも同様の実装になっています)

github.com

ということで

CloudWatch Logs に飛ばして(みた)レベルだが、Callback プラグインであれば意外に簡単に実装することが出来ました。

モジュールの実装に関する情報はチラホラ見かけることが出来ますが、プラグインそのものに関する情報があまり見かけない気がしていますが、モジュールやプラグインの側面から Ansible を見てみるのも面白いと考えています。