OCIの監視設定例

## 概要
パブリッククラウド上にシステムを構築した後、運用を行うためには監視方法の検討が必要になります。
今回OCI上VMやサービスに対してシステム監視を設定しました。

## 監視方法
OCIでは様々な監視のための仕組みが用意されています。

- 標準メトリックを使用したモニタリング（標準モニタリング）
- 個別に収集したメトリックを使用したモニタリング（カスタムモニタリング）
- 特定イベントにおいて特定メッセージが出力された場合に検出するイベントサービス（イベント）

今回監視したい項目と対応する監視設定は以下のとおりとなります
- Webサーバ
   [CPU使用率](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-cpu%E4%BD%BF%E7%94%A8%E7%8E%87):標準モニタリング
   [メモリ使用率](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-%E3%83%A1%E3%83%A2%E3%83%AA%E4%BD%BF%E7%94%A8%E7%8E%87):標準モニタリング
   [Disk使用率](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-disk%E4%BD%BF%E7%94%A8%E7%8E%87): カスタムモニタリング
   [死活監視(不在アラーム)](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-%E6%AD%BB%E6%B4%BB%E7%9B%A3%E8%A6%96%E4%B8%8D%E5%9C%A8%E3%82%A2%E3%83%A9%E3%83%BC%E3%83%A0): 標準モニタリング
   [死活監視(Ping)](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-%E6%AD%BB%E6%B4%BB%E7%9B%A3%E8%A6%96ping): カスタムモニタリング
   [URL監視](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-url%E7%9B%A3%E8%A6%96) : カスタムモニタリング
   [バックアップ監視](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#web%E3%82%B5%E3%83%BC%E3%83%90-%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E7%9B%A3%E8%A6%96): イベント
 - LoadBalancer
   [外部URL監視](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#loadbalancer-%E5%A4%96%E9%83%A8url%E7%9B%A3%E8%A6%96): ヘルスチェック->標準モニタリング
 - MySQL Database Service(MDS)
   [サービス監視](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#mysql-database-servicemds-%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E7%9B%A3%E8%A6%96): カスタムモニタリング
 - ObjectStorage
   [サービス監視](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#objectstorage-%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E7%9B%A3%E8%A6%96): カスタムモニタリング
 - サイト間VPN 
   [VPNステータス監視](https://qiita.com/tktk2712/items/f1c9002ff5fb20040e0a#%E3%82%B5%E3%82%A4%E3%83%88%E9%96%93vpn-vpn%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9%E7%9B%A3%E8%A6%96):標準モニタリング

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/e7a56fb9-8024-616a-77d6-beeb5ed303da.png)


## 通知設定
モニタリングにて設定した閾値を超えた場合やイベントで検知した場合は通知設定で指定した宛先にメール送付します

- OCIコンソールメニューから開発者サービス>>アプリケーション統合>>通知を選択
- 「トピックの作成」ボタンを押下
- トピックの名前を入力して「作成」ボタンを押下
- 作成したトピックを選択
- 「サブスクリプションの作成」ボタンを押下
- プロトコルで通知方法を選択（今回は電子メールを選択）
- メールアドレスを入力し「作成」ボタンを押下。この後メールアドレス検証があります

## Webサーバ CPU使用率
標準機能を使用してCPU使用率アラートを設定します。
- OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
「アラームの作成」ボタンを押下
- アラーム名、重大度選択およびアラーム本体を設定
- メトリック・ネームスペースはoci_computeagentを指定
- メトリック名にCpuUtilizationを指定
- 間隔時間を指定
- 統計にMeanを指定
- メトリック・ディメンションで監視したいVMを選択。リージョン内のすべてのVMを選択することもできますし、VM名を指定することもできます
- トリガー・ルールでアラーム起動条件を指定。例えばCPU使用率80%が10分継続を条件とする場合は、演算子：次より大きい、値：80、トリガー遅延分数：10を指定
- 宛先に作成済の通知設定を選択
- 「アラームの保存」ボタンを押下

## Webサーバ メモリ使用率
標準機能を使用してメモリ使用率アラートを設定します。
- OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
- 「アラームの作成」ボタンを押下
- アラーム名、重大度選択およびアラーム本体を設定
- メトリック・ネームスペースはoci_computeagentを指定
- メトリック名にMemoryUtilizationを指定
- 間隔時間を指定
- 統計にMeanを指定
- メトリック・ディメンションで監視したいVMを選択。リージョン内のすべてのVMを選択することもできますし、VM名を指定することもできます
- トリガー・ルールでアラーム起動条件を指定。例えばCPU使用率80%が10分継続を条件とする場合は、演算子：次より大きい、値：80、トリガー遅延分数：10を指定
- 宛先に作成済の通知設定を選択
- 「アラームの保存」ボタンを押下

## Webサーバ Disk使用率
カスタムメトリックを使用してVMのDisk使用率アラートを設定します。
Linux/WindowsにPythonで作成しています。
Windowsの.NETを使用した検証も行っていますので要件に当てはまる場合はご参考いただければと思います。
[OCI VM(Windows)のディスク使用率を.NETを使って監視](https://qiita.com/tktk2712/items/5ac2d85793b64fd2adf5)

Disk使用率設定に関しては以下の記事を参考にしました。

OCIカスタム・メトリックでディスク使用率を監視
https://qiita.com/liu-wei/items/3f5593eab06c5885a83a

- 準備
Disk使用率を監視するLinuxサーバに以下を準備します
OCIカスタム・メトリック送信時の認証はociユーザー資格情報またはインスタンスプリンシパルが利用可能です。
    - 共通
        - Python, pip
        - pip listでoci, psutil, pytzを確認して、なければinstall
    - ociユーザー資格情報
        - ~/.ociにOCI資格情報が入ったconfigを作成
        - ポリシー作成
　         _Allow 【ユーザーが所属するグループ】 to use metrics in compartment 【対象コンパートメント名】_
    - インスタンスプリンシパル
        - 動的グループ作成
          OCIコンソールのナビゲーションメニューからアイデンティティとセキュリティ>>ドメイン(Default)>>動的グループを選択して「動的グループの作成」を押下
名前：任意の名前を設定
一致ルール：
コンパートメント配下インスタンスを動的グループとして指定
"下で定義したいずれかのルールに一致"を選択してルールを記述
_instance.compartment.id = '【コンパートメントOCID ocid1.compartment.oc1..&#42;&#42;】'_
_resource.compartment.id = '【コンパートメントOCID ocid1.compartment.oc1..&#42;&#42;】'_
参考
[動的グループを定義するための一致ルールの記述](https://docs.oracle.com/ja-jp/iaas/Content/Identity/dynamicgroups/Writing_Matching_Rules_to_Define_Dynamic_Groups.htm)

        - ポリシー作成
      OCIコンソールのナビゲーションメニューからアイデンティティとセキュリティ>>ポリシーを選択して「ポリシーの作成」を押下

          _Allow dynamic-group 【動的グループ】 to use metrics in compartment 【コンパートメント】_
- Python作成
```diskcheck.py
import oci,psutil,datetime
from pytz import timezone
import subprocess

# 認証 ociユーザー資格情報利用の場合
from oci.config import from_file
config = from_file()
monitoring_client = oci.monitoring.MonitoringClient(config,service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com")

# 認証 インスタンスプリンシパル利用の場合
signer = oci.auth.signers.InstancePrincipalsSecurityTokenSigner()
monitoring_client = oci.monitoring.MonitoringClient(config={},signer=signer,service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com")

# time stamp
times_stamp = datetime.datetime.now(timezone('UTC'))

# get disk usage with psutil
# Windowsの場合はc:等を選択してください
disk = psutil.disk_usage('/')
disk_usage=disk.percent

# custom metric
post_metric_data_response = monitoring_client.post_metric_data(
post_metric_data_details=oci.monitoring.models.PostMetricDataDetails(
metric_data=[
    oci.monitoring.models.MetricDataDetails(
        namespace="custom_metrics",
        compartment_id="【コンパートメントOCID】",
        name="disk_usage",
        dimensions={'server_id': "【host名】"},
        datapoints=[
            oci.monitoring.models.Datapoint(
                timestamp=datetime.datetime.strftime(
                    times_stamp,"%Y-%m-%dT%H:%M:%S.%fZ"),
                value=disk_usage)]
        )]
    )
)
```
- 定期実行
例えば1時間ごとに実行するよう定期実行を設定します
Linuxの場合はcron設定、Windowsの場合はタスクスケジューラに設定します


- アラーム定義
    - OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
    - 「アラームの作成」ボタンを押下
    - アラーム名、重大度選択およびアラーム本体を設定
    - メトリック・ネームスペースはcustom_metricsを指定
    - メトリック名にdisk_usageを指定
    - 間隔時間を指定
    - 統計にMeanを指定
    - メトリック・ディメンション名はserver_id、ディメンション値で対象hostを指定します
    - トリガー・ルールでアラーム起動条件を指定。例えばディスク使用率90%超が2時間連続して発生を条件とする場合は、演算子：次より大きい、値：90、トリガー遅延分数：60を指定
    - 宛先に作成済の通知設定を選択
    - 「アラームの保存」ボタンを押下

取得できていればこのようなグラフは以下のように表示されます。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/0c85a205-2e12-19b6-9c13-ce1f02e5aa5b.png">

## Webサーバ 死活監視(不在アラーム)
Compute agentからのメトリックがない場合、VMが異常状態と判断してアラームを起動することができます。
設定は以下を参考に行います。
[不在アラームの作成](https://docs.oracle.com/ja-jp/iaas/Content/Monitoring/Tasks/create-alarm-absence.htm)
- OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
「アラームの作成」ボタンを押下
- アラーム名、重大度選択およびアラーム本体を設定
- 「拡張モードに切替え」をクリック
- メトリック・ネームスペースはoci_computeagentを指定
- 問合せコード・エディタにCpuUtilization[1m]{resourceId = "【VMのOCID】"}.groupBy(resourceId).absent()を入力
- トリガー遅延分数を指定
- 宛先に作成済の通知設定を選択
- 「アラームの保存」ボタンを押下

## Webサーバ 死活監視(Ping)
pingによる死活監視はOCI標準機能ではできません。そのためping用の監視vmを立ててその監視vmから監視対象のvmへのpingを行い、ping結果をカスタムメトリックとして監視を行います。
監視vmは監視対象が少なければ小さい構成（Linux, バースト12.5% 1OCPU, メモリ2G)でよいと思います。また監視対象はpingできれば何でもよいのでVM以外のノードも監視できます。

- 準備
Python導入、OCI環境等準備は Webサーバ Disk使用率を参照ください。

- Python作成
監視対象のリストを作成します
```pingdata.txt
10.1.1.100
10.1.1.101
10.1.1.102
```

監視対象リストからデータを読み取り、pingを実施してOKの場合は0, NGの場合は1をreturncodeとしてOCIに送信します

```Pingmonitor.py
import oci,psutil,datetime
from pytz import timezone
import subprocess

# using default configuration file (~/.oci/config)
from oci.config import from_file
config = from_file()

# initialize service client with default config file
monitoring_client = oci.monitoring.MonitoringClient(config,service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com")

times_stamp = datetime.datetime.now(timezone('UTC'))

with open('/path/to/pingdata.txt') as f:
    l_strip = [s.strip() for s in f.readlines()]
    hosts = (l_strip)

for host in hosts:
    res = subprocess.run(["ping",host,"-c","1", "-W", "1"],stdout=subprocess.PIPE)

    post_metric_data_response = monitoring_client.post_metric_data(
        post_metric_data_details=oci.monitoring.models.PostMetricDataDetails(
        metric_data=[
            oci.monitoring.models.MetricDataDetails(
                namespace="custom_metrics",
                compartment_id="【コンパートメントOCID】",
                name="ping_result",
                dimensions={'server_id': host},
                datapoints=[
                    oci.monitoring.models.Datapoint(
                        timestamp=datetime.datetime.strftime(
                            times_stamp,"%Y-%m-%dT%H:%M:%S.%fZ"),
                            value=res.returncode)]
                )]
            )
        )

```
cron定期実行することにより定期的にping結果をOCIに送信します

- アラーム定義
    - OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
「アラームの作成」ボタンを押下
    - アラーム名、重大度選択およびアラーム本体を設定
    - メトリック・ネームスペースはcustom_metricsを指定
    - メトリック名にping_resultを指定
    - 間隔時間を指定
    - 統計にMeanを指定
    - メトリック・ディメンション名はserver_id、ディメンション値で対象IPを指定します
    - トリガー・ルールでアラーム起動条件を指定。例えばPingNGが5分連続して発生を条件とする場合は、演算子：次より大きい、値：1、トリガー遅延分数：5を指定
    - 宛先に作成済の通知設定を選択
    - 「アラームの保存」ボタンを押下

例：1分ごとのping結果がカスタムメトリックとして保存されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/c66b7caf-c8fc-a87a-d760-ae9ba14c95fe.png)

## Webサーバ URL監視
Webサーバ 死活監視と同様に監視VMから監視対象URLへのcurl結果をカスタムメトリック送信します。
python以外はWebサーバ 死活監視の項を参照ください

- Python作成
監視VMから監視対象URLへのcurl結果（正常なら200)をOCIに送信します

```urlmonitor.py
import oci,psutil,datetime
from pytz import timezone
import subprocess

# using default configuration file (~/.oci/config)
from oci.config import from_file
config = from_file()

# initialize service client with default config file
monitoring_client = oci.monitoring.MonitoringClient(config,service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com")

times_stamp = datetime.datetime.now(timezone('UTC'))

res = subprocess.run(["curl","【https://監視対象URL】","-o","/dev/null","-w","%{http_code}","-s"],stdout=subprocess.PIPE)
returncode = int(res.stdout)

post_metric_data_response = monitoring_client.post_metric_data(
post_metric_data_details=oci.monitoring.models.PostMetricDataDetails(
metric_data=[
    oci.monitoring.models.MetricDataDetails(
        namespace="custom_metrics",
        compartment_id="【コンパートメントOCID】",
        name="https_result",
        dimensions={'server_id': "【host名】"},
        datapoints=[
            oci.monitoring.models.Datapoint(
                timestamp=datetime.datetime.strftime(
                    times_stamp,"%Y-%m-%dT%H:%M:%S.%fZ"),
                value=returncode)]
        )]
    )
)
```
## Webサーバ バックアップ監視
WebサーバのDiskは定期的にバックアップを取得しています。
バックアップが失敗したときにアラート検知する設定を行います

- OCIコンソールメニューから監視および管理>>イベントサービスを選択
「ルールの作成」ボタンを押下
- 表示名を設定
- ルール条件設定
条件：イベントタイプ、サービス名：BlockVplume：イベントタイプ：Create Boot Volume Backup End
条件：属性、属性名：status、属性値：oparation Failed
- アクションに作成済の通知設定を選択
- 「ルールの作成」ボタンを押下

参考url:
ボリューム・バックアップが失敗した場合に通知するイベントの使用
https://docs.oracle.com/ja-jp/iaas/Content/Block/Tasks/backupstatusevents.htm#backupstatusevents

## LoadBalancer 外部URL監視
ヘルスチェック->標準モニタリング
標準機能を使用して外部URL監視を設定します。
- OCIコンソールメニューから監視および管理>>モニタリング>>ヘルス・チェックを選択
- 「ヘルスチェックの作成」ボタンを押下
- ヘルス・チェック名を設定
- ターゲットに監視したいLBのURLを設定
- バンテージ・ポイントは監視元を指定
- リクエスト・タイプにhttpを指定
- 「ヘルスチェックの作成」ボタンを押下
- OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
- 「アラームの作成」ボタンを押下
- アラーム名、重大度選択およびアラーム本体を設定
- メトリック・ネームスペースはoci_healthchecksを指定
- メトリック名にHTTP.StatusCodeを指定
- 間隔時間を指定(例えば5m)
- 統計を指定(例えばmean)
- メトリック・ディメンションで監視したいresourceid
- トリガー・ルールでアラーム起動条件を指定。例えば200以外が10分継続を条件とする場合は、演算子：範囲外、値：200、トリガー遅延分数：10を指定
- 宛先に作成済の通知設定を選択
- 「アラームの保存」ボタンを押下

## MySQL Database Service(MDS) サービス監視
Webサーバ 死活監視と同様に監視VMからMySQL Database Serviceへの監視結果をカスタムメトリックとして送信します。
python以外はWebサーバ 死活監視(Ping)の項を参照ください

- Python作成
監視VMから監視対象URLへのping結果（正常なら0)をOCIに送信します

```mysqlmonitor.py


import oci,psutil,datetime
from pytz import timezone
import subprocess

# using default configuration file (~/.oci/config)
from oci.config import from_file
config = from_file()

# initialize service client with default config file
monitoring_client = oci.monitoring.MonitoringClient(config,service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com")

times_stamp = datetime.datetime.now(timezone('UTC'))

subprocess.run(["mysqladmin","-h【サーバIPアドレス】","-P3306","-u【監視用ユーザ名】","-p【パスワード】","ping","--connect_timeout","2"
])

res = subprocess.run("echo $?",shell=True, stdout=subprocess.PIPE)
returncode = int(res.stdout)

post_metric_data_response = monitoring_client.post_metric_data(
post_metric_data_details=oci.monitoring.models.PostMetricDataDetails(
metric_data=[
    oci.monitoring.models.MetricDataDetails(
        namespace="custom_metrics",
        compartment_id="【コンパートメントOCID】",
        name="MySQL",
        dimensions={'server_id': "【host名】"},
        datapoints=[
            oci.monitoring.models.Datapoint(
                timestamp=datetime.datetime.strftime(
                    times_stamp,"%Y-%m-%dT%H:%M:%S.%fZ"),
                value=returncode)]
        )]
    )
)
```


## ObjectStorage サービス監視
Webサーバ 死活監視と同様に監視VMからObjectStorageの特定URLへの監視結果をカスタムメトリックとして送信します。
python以外はWebサーバ 死活監視(Ping)の項を参照ください

- Python作成
監視VMから監視対象URLへのcurl結果（正常なら200)をOCIに送信します

```objstoragemonitor.py

import oci,psutil,datetime
from pytz import timezone

# using default configuration file (~/.oci/config)
from oci.config import from_file
config = from_file()

# initialize service client with default config file
monitoring_client = oci.monitoring.MonitoringClient(config,service_endpoint="https://telemetry-ingestion.ap-tokyo-1.oraclecloud.com")

times_stamp = datetime.datetime.now(timezone('UTC'))

import subprocess

res = subprocess.run(["curl","ObjectStorageのURL","-o","/dev/null","-w","%{http_code}","-s"],stdout=subprocess.PIPE)
returncode = int(res.stdout)

post_metric_data_response = monitoring_client.post_metric_data(
post_metric_data_details=oci.monitoring.models.PostMetricDataDetails(
metric_data=[
    oci.monitoring.models.MetricDataDetails(
        namespace="custom_metrics",
        compartment_id="【コンパートメントOCID】",
        name="https_result",
        dimensions={'server_id': "ObjStorage-Tokyo"},
        datapoints=[
            oci.monitoring.models.Datapoint(
                timestamp=datetime.datetime.strftime(
                    times_stamp,"%Y-%m-%dT%H:%M:%S.%fZ"),
                value=returncode)]
        )]
    )
)
```

## サイト間VPN VPNステータス監視
サイト間VPNはCPEと2本のtunnelで接続されており1本のtunnel障害は迂回通信可能、2本のtunnel障害は通信不可となります。

ここではそれぞれのtunnel1/2のステータス監視とtunnel両系障害を設定します。
- tunnel1/2のステータス監視
標準機能を使用してそれぞれのVPNステータスのアラートを設定します。
    - OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
    「アラームの作成」ボタンを押下
    - アラーム名、重大度選択およびアラーム本体を設定
    - メトリック・ネームスペースはoci_vpnを指定
    - メトリック名にTunnelStateを指定
    - 間隔時間を5分に設定
    - 統計にMaxを指定
    - ディメンション名はresourceNameを選択
    - ディメンション値は監視するtunnelをそれぞれ選択
    - トリガー・ルールでアラーム起動条件を指定。演算子：次より小さい、値：1、トリガー遅延分数：1を指定
        - 2つのtunnel stateが対象となります
        - tunnel stateはIPSecがupしていれば1,downしていれば0となります
        - 統計にMaxを指定すると以下のような結果となります
            - 間隔時間内にtunnel state=1が1つ以上ある → 1
            - 間隔時間内のtunnel stateはすべて0 → 0
    - 宛先に作成済の通知設定を選択
    - 「アラームの保存」ボタンを押下

- tunnel両系障害監視
  標準機能を使用してtunnel両系障害のアラートを設定します。
    - OCIコンソールメニューから監視および管理>>モニタリング>>アラーム定義を選択
    「アラームの作成」ボタンを押下
    - アラーム名、重大度選択およびアラーム本体を設定
    - メトリック・ネームスペースはoci_vpnを指定
    - メトリック名にTunnelStateを指定
    - 間隔時間を5分に設定
    - 統計にMaxを指定
    - ディメンション名はparentResourceIdを選択
    - ディメンション値は監視するVPNのOCIDを選択
    - 集計メトリックストリームにチェック
    - トリガー・ルールでアラーム起動条件を指定。演算子：次より小さい、値：1、トリガー遅延分数：1を指定
        - 2つのtunnel stateが対象となります
        - tunnel stateはIPSecがupしていれば1,downしていれば0となります
        - 統計にMaxを指定すると以下のような結果となります
            - tunnel1=1(up), tunnel2=1(up) → 1
            - tunnel1=1(up), tunnel2=0(down) → 1
            - tunnel1=0(down), tunnel2=1(up) → 1
            - tunnel1=0(down), tunnel2=0(down) → 0
    - 宛先に作成済の通知設定を選択
    - 「アラームの保存」ボタンを押下