AWX(Ansible Tower)とZabbixを連携させて自動化ジョブの標準化を図ってみる

ここでは、Ansible TowerのOSS版であるAWXとZabbixを連携させて自動ジョブの標準化ができないか考えてみました。

# 1. 背景

Zabbixではトリガーが発生したら指定したジョブ(スクリプトなど)を実行して対処をすることができます。
自由度が高くスクリプトなどで書けば簡単に動いて便利です。
ただ、以下のような課題がありました。

* スクリプトやコーディングは利用者のスキル依存になるため言語が統一できず属人化になりがち(bashやPerlやPythonや...)
* コードの品質にも課題あり
* コードの管理方法がバラバラ(Git使う人もいればCIFSにファイルをそのまま入れてる人もいる)
* それぞれの言語で必要なモジュールが出てきてZabbixに都度インストールする必要があり、最終的に構成管理がしきれなくなる(スクリプトもZabbix/Proxy毎にどんどん入れるともはやワケワカメ)
* etc...

そこで、AWXとZabbixを連携すれば自動ジョブは標準化できないか検証してみました。

# 2. 使うもの

* AWX(ansible)
* Zabbix
* 自作Goツール [awx-exec-job](https://github.com/sky-joker/awx-exec-job)

# 3. 考えたこと

## 3-1. ZabbixとAWXを連携させるツール

ここでは [awx-exec-job](https://github.com/sky-joker/awx-exec-job) というツールをGoで作ったので使用してみます。
これは、AWXのジョブテンプレート名を指定して実行するだけのツールです。
何故、Goで作ったかというとワンバイナリ化ができZabbixサーバ側には追加でモジュールをインストールしなくてもよいという点です。
例えば、運用でGoのツールを更新する場合はビルドしたバイナリを置き換えるだけで済みます。

## 3-2. コードの標準化

次に、それぞれの言語で作っていた処理の標準化については、Ansibleが使えるかなと思いAWXを使ってみます。
AnsibleのPlaybook(YAML)でコードを標準化しておくことでバラバラで作っていたコードを標準化できないかと考えています。
また、AnsibleはPythonで自作モジュールも作成できるため `Python` と `Playbook(YAML)` を覚える形かなと思っています。

## 3-3. 実行結果や証跡について

Zabbixでスクリプト実行の自動化はできますが、Zabbix側でわかるのはスクリプトの実行結果の戻り値が問題ないか位で失敗した時に `どこでコケたか？` などがわかりません。
AWXを使う事で例え処理が失敗しても `いつ実行してどこのタスクで失敗して結果はこうだった` というところまで記録に残ります。


# 4. 検証

ここでは、簡単なイメージがつくようにVMwareのVM再起動をしてみようと思います。
以下は検証のイメージ図です。

![AWXとZabbixの検証図.png](https://qiita-image-store.s3.amazonaws.com/0/180118/8b84379b-a0fc-0c9c-b821-943b8d68eff7.png)

## 4-1. 検証内容

* Zabbix側でzabbix_senderを使って意図的にトリガーを発生させる
* トリガーにはAWXのジョブ(VMが再起動する)をキックするアクションを紐づけておく
    * Zabbixのマクロに `AWX` `AWXユーザー名` `AWXパスワード` を設定しておく
    * `awx-exec-job` の引数には設定したマクロと `extra_vars` を指定する
* トリガーが発生してアクションが実行されたことを確認する
* AWX側でも実行された確認する
* VM(ここでは`devel2`というホストを指定する)が問題なく再起動したことを確認する

## 4-2. 検証環境

| 項目         | バージョン         |
|:-------------|:-------------------|
| RHEL         | 7.5                |
| Zabbix       | 3.4                |
| AWX          | この時点での最新版 |
| awx-exec-job | 0.2                |
| vCenter      | 6.5                |

## 4-3. awx-exec-jobのインストール

(1) [ここ](https://github.com/sky-joker/awx-exec-job)の手順を元にビルドしてZabbixサーバへコピーします。

```
[root@localhost ~]$ scp awx-exec-job root@zabbix34:
```

(2) ここでは、ツールを `externalscripts` ディレクトリへ移動します。インストール場所は環境に合わせて変更します。

```
[root@zabbix34 ~]# mv awx-exec-job /usr/lib/zabbix/externalscripts/
```

(3) 動作確認用でヘルプが表示されれば問題ありません。

```
[root@zabbix34 extralscript]# ./awx-exec-job -h
NAME:
   awx-exec-job - Tool to execute AWX job

USAGE:
   awx-exec-job [global options] command [command options] [arguments...]

VERSION:
   0.2

AUTHOR:
   sky_joker

COMMANDS:
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --host value                IP or HostName for AWX (default: "127.0.0.1")
   --username value, -u value  Login UserName (default: "admin")
   --password value, -p value  Login Password
   --template value, -t value  Specify the template name to execute
   --ssl                       Specified only when using SSL
   --extra value, -e value     Specify extra vars
   --help, -h                  show help
   --version, -v               print the version
```

## 4-4. Zabbixの設定

### 4-4-1. ホスト設定

#### 4-4-1-1. ホスト

![スクリーンショット 2018-06-24 16.20.26.png](https://qiita-image-store.s3.amazonaws.com/0/180118/47f40ffa-c3b9-e961-f12c-f844e30c49db.png)

#### 4-4-1-2. マクロ

マクロには以下を設定しています。

| 項目            | 説明                        |
|:----------------|:----------------------------|
| {$AWX}          | AWXのIPまたはホスト名       |
| {$AWX_USER}     | AWXへログインするユーザー名 |
| {$AWX_PASSWORD} | AWXへログインするパスワード |

![スクリーンショット 2018-06-24 16.21.02.png](https://qiita-image-store.s3.amazonaws.com/0/180118/dacf7cce-f293-d252-8bcb-9b1ca74c8ca5.png)

#### 4-4-1-3. アプリケーション・アイテム

![スクリーンショット 2018-06-24 16.23.29.png](https://qiita-image-store.s3.amazonaws.com/0/180118/3e94356e-7278-f838-0488-51a00cc131e0.png)

![スクリーンショット 2018-06-24 16.24.04.png](https://qiita-image-store.s3.amazonaws.com/0/180118/afc498ff-1d03-ecd3-f54f-d6dafb018aa4.png)

#### 4-4-1-4. トリガー

![スクリーンショット 2018-06-24 16.24.40.png](https://qiita-image-store.s3.amazonaws.com/0/180118/4da2fbdb-51bb-ceee-881f-ccdf600387c6.png)


### 4-4-2. アクション設定

#### 4-4-2-1. アクション

![スクリーンショット 2018-06-24 16.25.23.png](https://qiita-image-store.s3.amazonaws.com/0/180118/1f0a8f11-4fff-0b68-8156-dc720deea44a.png)

#### 4-4-2-2. 実行内容

![スクリーンショット 2018-06-24 16.26.49.png](https://qiita-image-store.s3.amazonaws.com/0/180118/0969af58-b85f-f25e-b1fb-51cc48956dad.png)


`コマンド` には以下を指定しています。

```
/usr/lib/zabbix/externalscripts/awx-exec-job --host {$AWX} -u {$AWX_USER} -p {$AWX_PASSWORD} -t vm_reboot -e '{"extra_vars": {"vm":"{HOST.HOST}"}}'
```

`vm` のキーに対して動的にZabbixで設定したホスト名が入るようにしています。

## 4-5. AWXの設定

`vm` はextra_varsから受けれるようにしています。
ここでは、vCenterの認証関係はPlaybookに記述していますが変数化して外部から受けれるよう設計するのもいいと思います。

### 4-5-1. Playbook

```yaml:main.yml
---
- name: VMware Job
  hosts: localhost
  gather_facts: no
  tasks:
    - name: "{{ vm }} reboot"
      vmware_guest:
        hostname: 192.168.0.253
        username: administrator@vsphere.local
        password: secret
        validate_certs: no
        name: "{{ vm }}"
        state: rebootguest
```

### 4-5-2. テンプレート

![スクリーンショット 2018-06-24 16.29.56.png](https://qiita-image-store.s3.amazonaws.com/0/180118/f682e644-cdbc-f01e-93c7-fd87f5d771e8.png)

`extra_vars` が渡せるようにテンプレートの `起動プロンプト` を有効にしておく必要があります。

## 4-6. 検証実行

### 4-6-1. トリガー実行

(1) Zabbix Senderを使って意図的にトリガーを発生します。

```
[root@zabbix34 externalscripts]# zabbix_sender -z 127.0.0.1 -s devel2 -k reboot_flag -o 1
info from server: "processed: 1; failed: 0; total: 1; seconds spent: 0.000070"
sent: 1; skipped: 0; total: 1
```

(2) Zabbixでトリガーに紐づけられたコマンドアクションが実行されていることを確認します。

![スクリーンショット 2018-06-24 16.33.17.png](https://qiita-image-store.s3.amazonaws.com/0/180118/7e4958ed-035e-22d3-5dc9-b0fab1f9738f.png)

(3) AWXのジョブで問題なく実行された確認します。

![スクリーンショット 2018-06-24 16.34.58.png](https://qiita-image-store.s3.amazonaws.com/0/180118/cb0906be-3140-f95f-fea3-f3dac8d3bd40.png)

(4) vCenter側でVMが再起動されたことを確認します。

![スクリーンショット 2018-06-24 16.35.30.png](https://qiita-image-store.s3.amazonaws.com/0/180118/fb912020-35d0-05e5-2587-2793be98af93.png)

問題なく実行されていることが確認できました :-)

# 5. まとめ

* Zabbix側はAWXのテンプレートを実行するツール(Go)を入れておく事でツールの保守や構成管理の負荷が減りそう
* ジョブの処理はAnsibleのPlaybookで記述しておくことで自動化処理(スケールアウトや復旧など)のソースが標準化できそう
* 足りないモジュールはPythonで標準化することでAWXを利用する運用者は `Playbook(YAML)` と `Python` を覚えればよさそう(Zabbix運用者は `Go` のスキルも必要になる)
* AWXでは実行結果が記録されるので、失敗時の確認が容易にできそう
* 監査・証跡ログも残せるのでエンタープライズでも使えそう
* (ここでは出てないが)Playbookや自作モジュールはGitLabなどで管理してAWXと連携すれば管理の効率化ができそう

# 6. 最後に

`awx-exec-job` はAWXのみサポートしていますが時間があればAnsible Towerもサポートできるように改修...したいな...

# 2018/07/14追加

`HTTP BASIC認証の有効化` が `オン` になっていればAnsible Towerでも動作することを確認しまいsた。

![スクリーンショット 2018-07-14 20.26.46.png](https://qiita-image-store.s3.amazonaws.com/0/180118/0322b524-fac2-d581-dd37-e0637e6408f5.png)