slackのIncoming Webhooksで作る簡単監視ツール

# はじめに
本記事は、slackのAPIを使用して、クラウドで構築したサーバに対する死活監視を行うための記事になります。

クラウド環境は、**Oracle Cloud Platform**の**Oracle Cloud Infrastructure - Compute(※)**を使用していますが、プログラム自体はPythonで動き、どのクラウドでも同じ考え方ができるので手法は流用できます。

(※)AWS（Amazon Web Services）のEC2（Amazon Elastic Compute Cloud (Amazon EC2)）や、GCP（Google Cloud Platform）のGCE（Google Compute Engine）に相当

## 目的
クラウドにおけるシステム監視を考えた場合、従来のオンプレミスでやっていたシステム監視ではなく、クラウドに適した監視方式を考えないといけません。

クラウドのシステム監視は、ZabbixなどのOSSや、クラウドに特化した監視ツール等色々ありますが、導入時にコストをかけることなく、スモールスタートで監視を初めるのがクラウドに適したやり方だと考えてます。

そうした際に、クラウドインフラのSDKを使用し、外部サービスのAPIと連携して通知する仕組みを作ることは簡単にできます。

本記事では、以下の仕組みで監視を行い、障害発生時にslackと連携して通知を行います。
Oracle Cloud InfrastructureのLoad Balancerでは、デフォルトで指定したバックエンドに対してヘルスチェックが行われています。ヘルスチェックにより、バックエンドの状態の異常を検知し、監視サーバよりslkackで通知を行います。


![slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/25e3561b-3e77-cfa2-dfce-dcba11b9b6bd.png)

- メッセージ例   
<img width="399" alt="スクリーンショット 2019-06-15 22.28.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221759/a04a3e32-7f19-ba1e-8e3f-0f7c02fc4a3c.png">



## Incoming Webhooks
Incoming Webhooksは、slackが公開しているAPIの一つで、無料で使用できます。slackの数あるAPIの内、最も手軽に使用できます。

但し、Incoming Webhooksを使用する場合は、URLさえ分かれば誰でもメッセージを送ることができるので、注意しましょう。

## 実装
Oracle Linuxを例に環境を構築し、SDKの設定及びslackの設定を行います。
なお、SDKのバージョンは本記事執筆時点のバージョンとなっています。

OS：Oracle Linux 7 

- pythonのインストール  
`yum install -y python36`
- pipのインストール
`yum install -y python36-pip`

- 必要パッケージのインストール　　　
`yum install -y gcc`
`yum install -y python36-devel`
`yum install -y openssl-devel`
- SDKのインストール（GitHubよりダウンロード） 
`unzip oci-python-sdk-2.2.13.zip`
`cd oci-python-sdk/`
`pip3.6 install oci-2.2.13-py2.py3-none-any.whl` 
- slackwebのインストール
`pip3.6 install slackweb`
  
### SDK
Oracle Cloud InfrastructureのSDKを使用するためには、GitHubあるいは、PiPiよりSDKインストールし、configの設定が必要になります。config設定については、公式の[Required Keys and OCIDs](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm)を参照。

### slackの設定
[slask AppのIncoming webhooks](https://slack.com/apps/A0F7XDUAZ--web-)にアクセスし、「設定を追加」をクリックします。チャンネルへの投稿から、通知したいチャンネルを選択し設定します。設定を追加後、webhook用のURLが生成されるので、そのURLを控えます。

### プログラム

```lb_monitoring.py
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import oci
import json
import slackweb
import ssl
import time

# slack連携
slack = slackweb.Slack(url="<URL>")
ssl._create_default_https_context = ssl._create_unverified_context

class Lb_info_get:
    def __init__(self):
        # config設定
        config = oci.config.from_file("~/.oci/config",)
        identity = oci.identity.IdentityClient(config)

        # LB情報取得
        lbc = oci.load_balancer.LoadBalancerClient(config)
        lb_info = lbc.get_backend_health("<lbのocid>", "<バックエンド名>", "<IPアドレス:ポート>").data
        self.lb_info = lb_info

# 定期的に1分毎に監視するため、whileで実行
while True:
    lb_info_get_ins = Lb_info_get()
    lb_info = lb_info_get_ins.lb_info
    # jsonに変換
    lb_info = json.loads(str(lb_info))

    # LBのステータスがOK以外の場合はslackに通知する
    if not lb_info["status"] == "OK":
        attachments = [{"title": "○○サーバで障害発生", "pretext": lb_info["status"], "text": "コンテナがダウンしています", "color": "danger", "mrkdwn_in": ["text", "pretext"]}]
        slack.notify(attachments=attachments)
    time.sleep(60)
```

### ナレッジ
HTTPSのサイトにPythonでアクセスした際に、以下の様な例外エラーが発生する場合は、[PEP 476](https://www.python.org/dev/peps/pep-0476/)による証明書検証が行われているため、通信が失敗します。そのため、単一の接続で証明書の検証を拒否したい場合は、urllib.urlopenにcontext引数を指定することで通信を可能としています。

```text
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)

urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)>
```

# おわりに
Incoming webhooksの様なAPIは、バッチ処理の完了通知や、特定のメッセージを監視する場合に便利です。また、ボタン、メニュー、ダイアログなどのインタラクティブ機能をメッセージに追加して、ワークフローを管理することもできるため、色々な使い方ができそうです。

## 参考
- [Python SDK](https://docs.oracle.com/cd/E97706_01/Content/API/SDKDocs/pythonsdk.htm)
- [Oracle Cloud Infrastructure Python SDK - 2.2.13](https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/)
- [SDK and CLI Configuration File](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/sdkconfig.htm)
- [Incoming Webhooks](https://api.slack.com/incoming-webhooks)
- [Attaching content and links to messages](https://api.slack.com/docs/message-attachments)