IBM Cloud：Cloud メンテナンス通知をZabbix Serverへ転送する

# 概要
IBM CloudではCloudのメンテナンス通知をメールで受信することができます。一方でオンプレ等の監視にZabbixを利用している方の中には、Cloud通知も一括でZabbixで管理したい方がいるかもしれません。

本記事では、Event Notification・IBM Cloud Functionsを利用し、Cloud通知をZabbixへ転送する方法を記載します。

# 検証構成
今回は以下の構成で検証しています。 
![構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/8a8d92d4-4323-f109-93f6-95a90f5070d1.png)
Event Notificationは2022年12月現在、以下のリージョンのみで提供されています。
> - ダラス（us-south）
> - ロンドン（eu-gb）
> - シドニー（au-syd）
> - フランクフルト（eu-de）


# Zabbix Serverの設定
## Zabbix Serverのインストール
こちらに従い「**Ubuntu Linux 22.04 LTS**」にインストールしました。
[Zabbix Server 6.0 を、Ubuntu 20.04にインストール](https://server-recipe.com/3869/)

## zabbix trapperの設定
「設定」->「ホスト」を選択し、対象サーバーの「アイテム」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/71bc582d-1310-f543-71cb-7ce59b6e7c3d.png)

タイプを「Zabbixトラッパー」を選択して保存します。
![Screen Shot 2022-12-13 at 0.31.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/63686929-eabb-86ed-be9e-42c7f2a1d751.png)

# PythonによるZabbixへの転送コード作成
今回はzabbixが提供している「**zabbix sender**」機能を使用します。zabbix senderは、zabbix server内で作成したzabbix trapperを指定して、希望のデータをpushすることができます。
またコマンドとしても提供されており、`yum install zabbix-sender`でインストール可能です。
本記事ではコマンドではなくプログラム内にsenderを組み込み自動化したいので、pythonの[**py-zabbix**](https://github.com/adubkov/py-zabbix/blob/master/pyzabbix/sender.py)ライブラリを用いて、Event Notificationsからzabbixへ転送するコードを書きます。

pythonのバージョンは以下の通りです。
```
$ python3 --version
Python 3.10.8
```

以下、転送プログラムです。
functionsでは受信したデータを`param`に格納して`main()`を実行します。
`param`はデバッグも考慮して分岐させています。
```
from pyzabbix import ZabbixMetric, ZabbixSender

HOST = "[zabbix host名]"
KEY = "[zabbixの設定Key名]"
PORT = [zabbixの待ち受けポート] 　　# デフォルトは "10051"
ADDRESS = "[宛先IPアドレス]"


def sendto_zabbix(param):
    metrics = []
    mtrc = ZabbixMetric(HOST, KEY, param)
    metrics.append(mtrc)
    zbx = ZabbixSender(ADDRESS)
    zbx.send(metrics)


def main(param):　　　# "param"にEvent Notificationsからの転送イベント内容が格納
    if param:
        sendto_zabbix(param)
        return { 'massage': param }
    else:
        return { 'message': 'No massage' } 　　# Cloud Functionsでのデバグ用
```

# IBM Cloud Functionsの作業
## IBM Cloud Functionsの作成
上部タブにて「Event Notifications」で検索、または以下よりオーダーします。
https://cloud.ibm.com/catalog/services/event-notifications

Namespaceを新規作成する場合は、
左タブ「Namespace setting」をクリック -> 上部の" **^** "をクリック -> 「Create Namespace」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/90487e29-eb16-128a-bb7a-014566d2b617.png width=70%>

名前とリージョンを選択し「Create」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/66a6af34-1a3e-2276-4cc8-dd2f1f9d2235.png width=70%>

## コードをIBM Cloud Functionsへアップロード
IBM Cloud Functionsでは、実行コードと一緒に外部パッケージをzip化・アップロードすることで使用することが出来ます。
本記事では、**virtualenv** を使用してパッケージ化します。 virtualenvを使用すると、 **pip**を使用してインストールできる追加のパッケージをリンクできます。

※参考
- [IBM Cloud Functions の Python で外部パッケージを利用する](https://qiita.com/khayama/items/e4a8b13ff0b8378ceb9e)
- [docs: Python コードを Docker ローカル仮想環境と一緒にアーカイブとしてパッケージ化する](https://cloud.ibm.com/docs/openwhisk?topic=openwhisk-prep&locale=ja#prep_python_virtenv)

### アップロード用コンテナイメージの作成・zip化
dockerイメージをダウンロードします。
```
$ docker pull ibmfunctions/action-python-v3.9
```

zip にパッケージ化するための作業ディレクトリを準備し、import したい外部パッケージを requirements.txt にリストで書いておきます。(py-zabbixはpipでインストール可能です。)

```:作業ディレクトリ内のファイルリスト
$ ls workspace
__main__.py
requirements.txt
```
```:requirements.txtの中身
$ cat requirements.txt
py-zabbix
```

virtualenvを作成します。
```
$ docker run --rm -v "$PWD:/tmp" --entrypoint "/bin/bash" ibmfunctions/action-python-v3.9:latest -c "cd /tmp && virtualenv virtualenv && source virtualenv/bin/activate && pip install -r requirements.txt"

created virtual environment CPython3.9.13.final.0-64 in 40219ms
  creator CPython3Posix(dest=/tmp/virtualenv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
    added seed packages: ZabbixSender==0.2.7, pip==21.3.1, py_zabbix==1.1.7, setuptools==60.2.0, wheel==0.37.1
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
Requirement already satisfied: py-zabbix in ./virtualenv/lib/python3.9/site-packages (from -r requirements.txt (line 1)) (1.1.7)
WARNING: You are using pip version 21.3.1; however, version 22.3.1 is available.
You should consider upgrading via the '/tmp/virtualenv/bin/python -m pip install --upgrade pip' command.
```
virtualenvとたくさんのpemファイルが作成されます。
```
$ ls -l
jp419713$ ls -l
total 22456
-rw-r--r--  1 jp419713  staff      557 Nov 20 13:10 __main__.py
-rw-r--r--  1 jp419713  staff       10 Nov 20 13:03 requirements.txt
-rw-------  1 jp419713  staff   259465 Nov 18 23:08 tmp1cxl01kgcacert.pem
-rw-------  1 jp419713  staff   259465 Nov 18 23:08 tmp43ze4fdocacert.pem
.
.
.
-rw-------  1 jp419713  staff   259465 Nov 18 23:08 tmpvyopq50bcacert.pem
-rw-------  1 jp419713  staff   259465 Nov 18 23:08 tmpxzg8gn1tcacert.pem
drwxr-xr-x  6 jp419713  staff      192 Nov 18 22:51 virtualenv
```
virtualenvとコードをzip化します。
```
zip -r zabbix.zip virtualenv __main__.py
```

### IBM Cloudへアップロード
```
$ ibmcloud login -apikey xxxxxx -r jp-tok
$ ibmcloud plugin install cloud-functions
$ ibmcloud fn namespace target Namespace-test
$ ibmcloud fn action create sendto-zabbix [ファイルパス]/zabbix.zip --kind python:3.9
```
作成されたことをIBM Cloudポータルで確認します。
「**Functions**」->「**Action**」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/ccb245bc-dabc-63af-c65c-3ebce12659ed.png width=90%>


アップロードしたパッケージを選択すると以下のような画面になるので、左メニューの「**Endpoints**」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/48bbd4dd-e038-57fc-c869-b5908a442bf1.png)

「**Endpoints**」記載のREST APIをコピーしておきます。（Event Notificationsで使用します）

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/6b2751b0-8584-6535-9594-1f1e3b1bd27b.png width=100%>


# Event NotificationsからIBM Cloud Functionsへのアクセス許可
IBM Cloud Functionsへのアクセスが許可されたAPI Keyを発行します。後の手順でEvent Notificationsへ登録することでイベントの転送を許可します。

初めに、IBM Cloudポータルホーム画面から「管理」->「アクセス (IAM)」に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/47824cef-434d-e76b-770b-af838b529b68.png)

「Service IDs」を選択して「Create」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/4ac5e8f3-8f4c-3d91-1b96-2f354e856068.png)

名前空間を作成します。
(どのサービスに対してのアクセスを管理するのか分かれば大丈夫です)
![Screen Shot 2022-12-10 at 17.59.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/d2004706-23e5-2c26-3077-cc0127e193c6.png)

作成が完了するとService ID詳細画面に移ります。
続いてアクセス権限を設定するため、「Assign Access」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/0d6ee179-f608-d8ee-74fe-112bf974a101.png)

以下のように権限設定しました。設定後、「Add」->「Assign」をクリックします。
- Service：Functions
- Resource：All
    - (「Specific Resource」->「Service Instance」で特定のNamespaceのみ指定可能です)
- Role and actions：全て
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/d8abb28a-4941-3164-a24c-a774ee1e64d4.png)


続いて「API Keys」タブを選択し、「Create」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/5df100cb-39a4-28b4-945c-fbfe6103d1a0.png)

名前を設定して「Create」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/21b9c5ff-eab1-e5cc-1d04-e5af6a371a82.png width=70%>

API keyが表示されますが、表示は一度きりなのでダウンロードしておきます。
(後でEvent Notificationsの設定で使用します)
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/e04f2930-8e69-6399-4d27-e8bcd60d065f.png width=80%>


# Event Notificationsの設定
## Event Notificationsの作成
上部タブにて「Event Notifications」で検索、または以下よりオーダーします。
https://cloud.ibm.com/catalog/services/event-notifications

private経由で管理する必要がある場合は`Service Endpoints`にて「Both public & private network」を選択します。そのほかの注意事項は以下を参照ください。
https://cloud.ibm.com/docs/event-notifications?topic=event-notifications-en-regions-endpoints#en-service-endpoints

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/969d00bd-868b-6f8a-364c-74ee6e0d925f.png width=70%>

## Event Notificationsでのイベント転送設定
### source の設定
イベントのソースを指定します。
作成したEvent Notificaitons画面に移動し、「source」タブを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/f3c8e2cf-3943-59d4-95d2-4dbe7ea739da.png)

「Add」->「IBM Cloud Source」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/cc34dfb3-7921-fa35-bc36-983700f0d6ea.png width=50%>

「Platform Notifications for IBM Cloud」の「View configuration」をクリックします。!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/bc4d014c-5292-e0a3-669c-093fbf8f613e.png)

「Notification distribution list」ページに飛ぶので、「Add」->「Event Notificaitons」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/2184c936-aa2c-8a54-c28b-c5938298f410.png)

作成したEvent Notificaitonsリソースを選択し、「Add」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/9d16089c-5d42-0d0e-3fd3-d20c931cae93.png width=80%>

Sourceに追加されたのが確認できます。
![Screen Shot 2022-12-10 at 17.26.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/b9adae40-3848-4ff5-2c66-2c3fe1d01541.png)


### Destinationの設定
イベントの送信先を指定します。
作成したEvent Notificaitons画面にて、「Destinations」タブを選択します。デフォルトでSMSとEMailのチャネルが作成されます。編集することで特定のSMS/Emailへの転送が可能です。
「**Add**」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/875e4361-491d-9ac9-8b49-0d3ffc7a05d1.png)


「Name」と先ほどコピーしたFunctionsの「REST API」と「APIキー」を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/3f423d0a-bcfd-2534-f6a6-3bea4cd7597b.png)


### Topicsの設定
Topicsでは、発生したイベントの中で特定のイベントのみを転送したい場合のフィルタを定義します。

Event Notificaitons画面の「Topics」タブを選択し、「Create」をクリックします。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/20b45da2-eae9-1daa-4aaa-d0acf0b2d176.png width=100%>

「name」を入力して「Create」をクリックします。
optionでは、特定の"イベント・タイプ"や"重大度"に制限することが出来ます。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/f6dab240-561b-246e-3df6-78dba8144592.png width=90%>


### Subscriotionsの設定
「Subscriptions」タブを選択して「Create」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/237a72ee-0bdb-784d-7779-c8c8f89772b0.png)

これまで作成した"Topic"と"Destination"を選択、「Create」をクリックします。
![Screen Shot 2022-12-13 at 0.12.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/5b8d5d5b-db7d-1f55-b030-a65c4a928248.png)

# 転送の確認
イベントが発生すると、以下のようにzabbixでイベントを受信することが出来ました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199676/958b744e-0d3b-a372-a912-d8ddd7413fa2.png)