【AWS】【Azure】Azure側のVirtual Machinesに、Amazon CloudWatch Agentをインストールし、AWS側でメトリクスとログを監視してみました

#はじめに
直近では、Azure側の Virtual Machines に、メトリクスとログを監視する必要があるという要望がありました。
いろんな案を考案した結果、最後はAzure側の Virtual Machines に、Amazon CloudWatch Agent をインストールし、AWS側でメトリクスとログを監視することになりました。（笑）Azureには申し訳ないですけど。。。
なお、Azure側で使っている Virtual Machines のOSタイプは、Red Hat Enterprise Linux 7です。
構成イメージ図は下記となります。
![azure_cloudwatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/285fb27f-e02a-6a9d-7a6d-f1ef71fca9c3.png)

#解決案の選別
最初は三つの案を考案していました。 
１．Azure Monitor エージェント （もしくは Log Analytics エージェント）をインストールして監視
２．Zabbix Agentをインストールし、Zabbix Managerサーバーによる監視（※別途Zabbix Managerサーバーを作成する必要があります。）
３．Amazon CloudWatch Agentをインストールし、AWS側にて監視

###・案１：
Azure環境での監視設定は、もちろん一番実施しやすいのは、Azure側に監視サービスを使用することに間違いがありません。Azure Monitorから、仮想マシンのCPU、メモリ等は直接監視することはできますが、ログ監視を実現するには、エージェントのインストールが必要とされます。
~~ただし、Azure Monitor エージェントとLog Analytics エージェントはなんと両方ともRed Hat Enterprise Linux Server 7をサポートしていません。~~
2021/4/20訂正：
出典URLの表を読み違えていました。「X」はバツ（サポートしていない）ではなく、チェック記号（サポートしている）のことです。
Azure Monitor エージェントとLog Analytics エージェントは両方ともRed Hat Enterprise Linux Server 7をサポートしています。
これで、案１はベストプラクティスになるので、今後試してみます！:slight_smile:
（@matarillo さん、@normalian さん、ご指摘ありがとうございました。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/e529be48-7c15-a715-64f9-f647cf125381.png)
出典URL：
https://docs.microsoft.com/ja-jp/azure/azure-monitor/agents/agents-overview#linux


###・案２：
Zabbix Agentをインストールして、ログ監視やメトリクス監視は実現できそうです。
ただし、Zabbix Managerサーバーを作成しなくてはなりません。
費用面と設定手間から見れば、時間と料金がかかり、ベストプラクティスな案とは言えません。なので、当案は保留することとなりました。

###・案３：
CloudWatch Agent はサーバーログを監視できるほか、メトリクスも監視できます。
メトリクスには、3種類のメトリクスレベル（Basic、Standard、Advanced）から選べられます。
詳細は下記のURLにご参照下さい。
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-cloudwatch-agent-configuration-file-wizard.html

CloudWatch Agent を Azure側の Virtual Machinesにインストールする発想は、多分なかなかそう考えている人がいないのではとは思いますが、実は技術的から言えば実現できます。方法はオンプレミス環境のサーバーに、CloudWatch Agent を実装することと同じです。

AWS側のCloudWatch Agentで実現できれば、Zabbix 監視手法より、ある意味の「サーバーレス監視手法」ではないでしょうか（笑）

AWSとAzureを跨いてメトリクスとログデータ転送するので、もちろん転送中にセキュリティを懸念する方もいらっしゃると思います。実はメトリクスとログは転送中に暗号化されています。
>CloudWatch Logs は、転送中のデータのエンドツーエンドの暗号化を使用します。CloudWatch Logs サービスは、サーバー側の暗号化キーを管理します。

出典URL：https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/data-protection.html
暗号化だけではご安心できない方は、別のセキュリティ方式をご検討下さい。
当案の設定はそこまで複雑ではなく、手軽に実施できます。


#１．AWS側でIAMユーザーに、アクセスキーとシークレットキーを発行
AWSのIAMサービスで、ユーザーを作成し、下記のロールを付与しました。
・CloudWatchAgentAdminPolicy
・AmazonSSMFullAccess
※今回は検証のため、SSMの権限を大きくしました。実際構築する際に、AWS最小権限原則をお忘れなく！なお、直近CloudTrail イベントに基づいてポリシーを生成できるようになりましたので、AWS最小権限に悩む方はぜひご利用下さい！
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/b50e580a-7205-5950-f8ce-e97989d2b92e.png)

IAMユーザーのアクセスキー、シークレットキーを発行します。
「アクセスキーの作成」ボタンを押していただきますと作成できますので、作成後にCSVファイルをダウンロードしてください。
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/ccda65e8-6ab4-1889-bb06-79987bb04541.png)

#２．Azure側の Virtual Machines に、Amazon CloudWatch Agentをインストールします。
Azure側に Virtual Machines は作成してあります。
（Virtual Machines の作成方法はこちらで割愛させていただきます）
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/66b63608-8bdf-1f42-1d5e-65c2c01102cd.png)

Puttyでログインし、EPELリポジトリをインストールします。OSに応じてインストールしておきましょう。
URL：https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-enable-epel/

```
$ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
```

次にAWS CLIをインストールします。OSに応じてインストールしておきましょう。
URL：https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2-linux.html#cliv2-linux-install

```
$ sudo curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
```

collectdをインストールしておきます。

```
$ sudo yum install collectd
```

IAMユーザーのアクセスキー、シークレットキーを実装します。

```
$ sudo aws configure --profile AmazonCloudWatchAgent
AWS Access Key ID [None]: <アクセスキー>
AWS Secret Access Key [None]: <シークレットキー>
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

CloudWatch Agentをダウンロードします。OSに応じてインストールしておきましょう。
URL：https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/download-cloudwatch-agent-commandline.html

```
$ wget https://s3.amazonaws.com/amazoncloudwatch-agent/redhat/amd64/latest/amazon-cloudwatch-agent.rpm
$ sudo yum install ./amazon-cloudwatch-agent.rpm
```

CloudWatch Agentをインストールします。

```
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
```

私はCloudWatch Agentのメトリクスを、「Advanced」レベルを選択しました。
また、監視するログとしては「/var/log/messages」と、自ら作ったログ「/tmp/lalala.log」にしました。

```
=============================================================
= Welcome to the AWS CloudWatch Agent Configuration Manager =
=============================================================
On which OS are you planning to use the agent?
1. linux
2. windows
3. darwin
default choice: [1]:

Trying to fetch the default region based on ec2 metadata...
Are you using EC2 or On-Premises hosts?
1. EC2
2. On-Premises
default choice: [2]:

Please make sure the credentials and region set correctly on your hosts.
Refer to http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html
Which user are you planning to run the agent?
1. root
2. cwagent
3. others
default choice: [1]:

Do you want to turn on StatsD daemon?
1. yes
2. no
default choice: [1]:

Which port do you want StatsD daemon to listen to?
default choice: [8125]

What is the collect interval for StatsD daemon?
1. 10s
2. 30s
3. 60s
default choice: [1]:

What is the aggregation interval for metrics collected by StatsD daemon?
1. Do not aggregate
2. 10s
3. 30s
4. 60s
default choice: [4]:

Do you want to monitor metrics from CollectD?
1. yes
2. no
default choice: [1]:

Do you want to monitor any host metrics? e.g. CPU, memory, etc.
1. yes
2. no
default choice: [1]:

Do you want to monitor cpu metrics per core? Additional CloudWatch charges may apply.
1. yes
2. no
default choice: [1]:

Would you like to collect your metrics at high resolution (sub-minute resolution)? This enables sub-minute resolution for all metrics, but you can customize for specific metrics in the output json file.
1. 1s
2. 10s
3. 30s
4. 60s
default choice: [4]:

Which default metrics config do you want?
1. Basic
2. Standard
3. Advanced
4. None
default choice: [1]:
3
Current config as follows:
{
        "agent": {
                "metrics_collection_interval": 60,
                "run_as_user": "root"
        },
        "metrics": {
                "metrics_collected": {
                        "collectd": {
                                "metrics_aggregation_interval": 60
                        },
                        "cpu": {
                                "measurement": [
                                        "cpu_usage_idle",
                                        "cpu_usage_iowait",
                                        "cpu_usage_steal",
                                        "cpu_usage_guest",
                                        "cpu_usage_user",
                                        "cpu_usage_system"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ],
                                "totalcpu": true
                        },
                        "disk": {
                                "measurement": [
                                        "used_percent"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "diskio": {
                                "measurement": [
                                        "io_time",
                                        "write_bytes",
                                        "read_bytes",
                                        "writes",
                                        "reads"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "mem": {
                                "measurement": [
                                        "mem_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "net": {
                                "measurement": [
                                        "bytes_sent",
                                        "bytes_recv",
                                        "packets_sent",
                                        "packets_recv"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "netstat": {
                                "measurement": [
                                        "tcp_established",
                                        "tcp_time_wait"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "statsd": {
                                "metrics_aggregation_interval": 60,
                                "metrics_collection_interval": 10,
                                "service_address": ":8125"
                        },
                        "swap": {
                                "measurement": [
                                        "swap_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        }
                }
        }
}
Are you satisfied with the above config? Note: it can be manually customized after the wizard completes to add additional items.
1. yes
2. no
default choice: [1]:

Do you have any existing CloudWatch Log Agent (http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html) configuration file to import for migration?
1. yes
2. no
default choice: [2]:

Do you want to monitor any log files?
1. yes
2. no
default choice: [1]:

Log file path:
/var/log/messages
Log group name:
default choice: [messages]
azure-linux-log
Log stream name:
default choice: [{hostname}]
azure-log
Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]:

Log file path:
/tmp/lalala.log
Log group name:
default choice: [lalala]
azure-linux-lalala-log
Log stream name:
default choice: [{hostname}]
azure-lalala
Do you want to specify any additional log files to monitor?
1. yes
2. no
default choice: [1]:
2
Saved config file to /opt/aws/amazon-cloudwatch-agent/bin/config.json successfully.
Current config as follows:
{
        "agent": {
                "metrics_collection_interval": 60,
                "run_as_user": "root"
        },
        "logs": {
                "logs_collected": {
                        "files": {
                                "collect_list": [
                                        {
                                                "file_path": "/var/log/messages",
                                                "log_group_name": "azure-linux-log",
                                                "log_stream_name": "azure-log"
                                        },
                                        {
                                                "file_path": "/tmp/lalala.log",
                                                "log_group_name": "azure-linux-lalala-log",
                                                "log_stream_name": "azure-lalala"
                                        }
                                ]
                        }
                }
        },
        "metrics": {
                "metrics_collected": {
                        "collectd": {
                                "metrics_aggregation_interval": 60
                        },
                        "cpu": {
                                "measurement": [
                                        "cpu_usage_idle",
                                        "cpu_usage_iowait",
                                        "cpu_usage_steal",
                                        "cpu_usage_guest",
                                        "cpu_usage_user",
                                        "cpu_usage_system"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ],
                                "totalcpu": true
                        },
                        "disk": {
                                "measurement": [
                                        "used_percent"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "diskio": {
                                "measurement": [
                                        "io_time",
                                        "write_bytes",
                                        "read_bytes",
                                        "writes",
                                        "reads"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "mem": {
                                "measurement": [
                                        "mem_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "net": {
                                "measurement": [
                                        "bytes_sent",
                                        "bytes_recv",
                                        "packets_sent",
                                        "packets_recv"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "netstat": {
                                "measurement": [
                                        "tcp_established",
                                        "tcp_time_wait"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "statsd": {
                                "metrics_aggregation_interval": 60,
                                "metrics_collection_interval": 10,
                                "service_address": ":8125"
                        },
                        "swap": {
                                "measurement": [
                                        "swap_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        }
                }
        }
}
Please check the above content of the config.
The config file is also located at /opt/aws/amazon-cloudwatch-agent/bin/config.json.
Edit it manually if needed.
Do you want to store the config in the SSM parameter store?
1. yes
2. no
default choice: [1]:
1
What parameter store name do you want to use to store your config? (Use 'AmazonCloudWatch-' prefix if you use our managed AWS policy)
default choice: [AmazonCloudWatch-linux]
Azure-Linux-Test
Which region do you want to store the config in the parameter store?
default choice: [ap-northeast-1]

Which AWS credential should be used to send json config to parameter store?
1. <アクセスキー>(From Profile: AmazonCloudWatchAgent)
2. Other
default choice: [1]:
1
Successfully put config to parameter store Azure-Linux-Test.
Program exits now.

```

続いてAWS Systems Manager⇒パラメーターストアに、上記定義したパラメーターストアが反映できたかどうかを確認します。うまく反映できています！
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/f0583c80-bbff-7975-0171-6bdbac61a08c.png)

Systems ManagerのRun Commandを実行し、CloudWatch Agentを有効化します。
Azureのサーバー側に、下記のコマンドを実行します。
「ssm:<パラメーターストアの名前>」に、上記定義したパラメーターストアの名前を入れてください。

```
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m onPremise -c ssm:<パラメーターストアの名前> -s 
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --download-source ssm:<パラメーターストアの名前> --mode onPrem --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
```

CloudWatch Agentのステータスを確認します。
ActiveであればOKです。

```
$ systemctl status amazon-cloudwatch-agent
```

#３．AWS側でメトリクスとログを確認します。
まずはメトリクスを確認します。確かにメトリクスが反映できました！！
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/4d243956-650f-16d6-3a1a-803deaa32e1c.png)

ログを確認します。確かにロググループが反映できました！！
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/4a4283f6-b8d3-1984-6eb4-ad553fecf59f.png)

続いて試しに、Azure側Virtual Machinesで、先ほど作った「lalala.log」に、適当な文言を加えます。

```
$ echo sdfsdfsdfsdfsfsdfsaaaaaaa111111111111111 > /tmp/lalala.log
$ echo dadada123123 > /tmp/lalala.log
```

上記加えた文言はすぐCloudWatch上で反映することが出来ました！！
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/e989f06d-dcb4-41e7-cdec-1a9e26b55fe2.png)

最後に「/var/log/messages」ログも確認しておきます。確かに反映できました！！
![azure1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/865613/9349b82e-1274-0244-9371-1a73b14563e6.png)

#最後に
Azure側のVirtual Machinesに、AWSのCloudWatch Agentをインストールして、AWS側で監視する発想は、なかなかないのではないかと思います（笑）。
実は思ったより、AWSのCloudWatch Agentをオンプレミス環境にインストールすることと一緒です。
思考回転すれば、いろんな応用ケースは考えられるではないでしょうか？
今回はZabbix Managerサーバーをわざわざ立てる必要なく、ある意味では「サーバーレス」ですね（笑）。
本記事はだれかの役に立てればうれしいです。