mackerel-agentとAWSインテグレーションを併用する際の注意点について

監視対象ホストがうまく登録されない場合に、確認すべきポイントについて解説します。
2020.03.31

みなさん、こんにちは!
AWS事業本部の青柳@福岡オフィスです。

Mackerel でEC2インスタンスを監視する場合、「mackerel-agent」「AWSインテグレーション」という2通りの監視の仕組みがあります。

「mackerel-agent」は、Linux/Windowsサーバーにインストールしたエージェントのプロセスが、サーバー内で収集したメトリックをMackerelに送信して監視を行います。

「AWSインテグレーション」は、Amazon CloudWatchで収集されたメトリクスをMackerelに連係することで、AWSの各リソースの監視を行います。

mackerel-agentとAWSインテグレーションは単体でも監視を行うことができますが、これらを併用することで、より詳細な監視を行うことができます。

ある日に遭遇した「おかしな事象」・・・

監視を行いたいEC2インスタンスをAWSインテグレーションで監視対象に設定した後、EC2インスタンスにmackerel-agentをインストールしました。

Mackerelのコンソール画面で「Hosts」を開き、EC2インスタンスの情報を参照しようとしたところ・・・

何故か「ホスト」が2つ登録されていました。

よく見るとこれらは同じホスト (EC2インスタンス) を示しています。

Hosts画面で、1行目の「ホスト名」欄に表示されているのはEC2インスタンスの「プライベートDNS」に一致しており、2行目の「ホスト名」欄に表示されているのはEC2インスタンスの「インスタンスID」に一致しています。

これはすなわち、本来は一つの「ホスト」として情報がマージされるはずのものが、別々に扱われてしまっているという事象です。

(なお、プライベートDNSで表示されている方がmackerel-agentにより登録された情報で、インスタンスIDで表示されている方がAWSインテグレーションにより登録された情報です)

原因

何故このような事象になったのか、Mackerelのヘルプページにヒントがありました。

FAQ・mackerel-agent と AWS / Azure インテグレーションを併用した場合の課金体系はどうなりますか? - Mackerel ヘルプ

・インテグレーションによる登録ホストとの紐付けには、各プラットフォームが提供しているインスタンスメタデータAPIから取得できる情報を使用しています。
・AWSの場合、EC2インスタンスメタデータサービスのバージョンには v1 と v2 がありますが、mackerel-agent は v1 のみ対応しています。
・インスタンスメタデータサービス v1、あるいはインスタンスメタデータサービスそのものを無効にすると、Mackerelにはそれぞれ異なるスタンダードホストとして登録されてしまうため、ご注意ください。

つまり、EC2インスタンスの「インスタンスメタデータ」が無効になっていてmackerel-agentがインスタンスメタデータへのアクセスに失敗すると、このような事象になるという訳です。

※ なお、上記ヘルプページには「mackerel-agentはインスタンスメタデータサービスv1 (IMDSv1) のみ対応している」旨の記述がありますが、最新のmackerel-agentではIMDSv2にも対応しています。
参考情報: https://github.com/mackerelio/mackerel-agent/releases/tag/v0.67.0

対処法

インスタンスメタデータへアクセス可能かどうか確認する

インスタンスメタデータへのアクセスが有効になっているか無効になっているかを確認するには、以下のコマンドを実行します。

$ aws ec2 describe-instances \
    --instance-id i-0d7fc8fe840b7570a \
    --query "Reservations[].Instances[].MetadataOptions"
[
    {
        "State": "applied",
        "HttpTokens": "optional",
        "HttpPutResponseHopLimit": 1,
        "HttpEndpoint": "disabled"
    }
]

ここで HttpEndpoint の値が enabled であればインスタンスメタデータへのアクセスは有効ですが、disabled の場合はアクセスが無効になっています。

実際に、インスタンスメタデータへのアクセスが無効になっている場合に、アクセスを試みると以下のような結果になります。

IMDSv1へのアクセス:

$ curl -v http://169.254.169.254/latest/meta-data/
*   Trying 169.254.169.254...
* TCP_NODELAY set
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> GET /latest/meta-data/ HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Content-Length: 0
< Date: Tue, 31 Mar 2020 04:57:41 GMT
< Server: EC2ws
< Connection: close
< Content-Type: text/plain
<
* Closing connection 0

IMDSv2へのアクセスに必要なトークンの取得:

$ curl -v -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"
*   Trying 169.254.169.254...
* TCP_NODELAY set
* Connected to 169.254.169.254 (169.254.169.254) port 80 (#0)
> PUT /latest/api/token HTTP/1.1
> Host: 169.254.169.254
> User-Agent: curl/7.61.1
> Accept: */*
> X-aws-ec2-metadata-token-ttl-seconds: 21600
>
< HTTP/1.1 403 Forbidden
< Content-Length: 0
< Date: Tue, 31 Mar 2020 04:59:04 GMT
< Server: EC2ws
< Connection: close
< Content-Type: text/plain
<
* Closing connection 0

いずれも「403 Forbidden」が返ってきており、アクセスが拒否されたことが分かります。

インスタンスメタデータへのアクセスを有効にする

インスタンスメタデータへのアクセスを「無効」から「有効」に変更するには、以下のコマンドを実行します。

$ aws ec2 modify-instance-metadata-options \
    --instance-id i-0d7fc8fe840b7570a \
    --http-endpoint enabled
{
    "InstanceId": "i-0d7fc8fe840b7570a",
    "InstanceMetadataOptions": {
        "State": "pending",
        "HttpTokens": "optional",
        "HttpPutResponseHopLimit": 1,
        "HttpEndpoint": "enabled"
    }
}

これで、mackerel-agentがインスタンスメタデータへアクセスできるようになりました。

※ インスタンスメタデータへのアクセスの有効化・無効化については、AWSドキュメントの下記ページを参照してください。
インスタンスメタデータサービスの構成 - Amazon Elastic Compute Cloud

mackerel-agent側で修正を行う

これだけではMackerelの事象は解消されませんので、次に、mackerel-agent側での修正を行います。

mackerel-agentでホストを識別するために用いられる id ファイルの内容が古いままになっているため、一旦削除して、正しい内容で再生成させる必要があります。

まず、現在の id ファイルを削除します。

$ sudo rm /var/lib/mackerel-agent/id

mackerel-agentサービスを再起動します。

$ sudo systemctl restart mackerel-agent.service

これで、正しい内容で id ファイルが再生成されます。

Mackerelのコンソール画面を確認してみましょう。

2行目の「ホスト名」欄の表示が、インスタンスIDからDNS名に変わりました。
AWSインテグレーションにより登録された情報に対して、mackerel-agentからの情報がマージされた形になります。

なお、1行目のホストの表示は、mackerel-agentからの情報を受け取らなくなるため、しばらく経つと「connectivity」アラートが発生して「赤丸アイコン」が点灯します。

これを確認したら、この不要なホスト表示は「退役」してしまって構いません。

インスタンスメタデータへのアクセスを「有効」に設定しているのに、アクセスできない場合

インスタンスメタデータのへのアクセスが「有効」に設定されているのに、インスタンスメタデータにアクセスできない、という場合もあります。

  • Linuxインスタンスの場合:
    • iptablesによって、インスタンスメタデータへのアクセスが遮断されている
  • Windowsインスタンスの場合:
    • Windowsファイアウォールによって、インスタンスメタデータへのアクセスが遮断されている
    • netshルールによって、インスタンスメタデータへのアクセスが遮断されている

そのような場合は、以下のAWSドキュメントページを参考にして、インスタンスメタデータサービスが制限されていないか確認してください。

Linuxインスタンス - インスタンスメタデータサービスの制限
Windowsインスタンス - インスタンスメタデータサービスの制限

また、上記のようなOS標準機能の他にも、ウイルス対策ソフトウェア、セキュリティソフトウェアなどがアクセスを遮断している可能性も考えられます。
併せて確認するのが良いでしょう。

Windowsインスタンスのみ発生し得る事象

これは、Windowsインスタンス (Windows Server 2016以降) にのみ発生し得る事象ですが、EC2インスタンスを別サブネットに移行した際にインスタンスメタデータへアクセスできなくなる場合があります。

Windows Server EC2インスタンスを別サブネットに移行する際に注意すべきこと | Developers.IO

Windowsインスタンスでは、OSのルートテーブルにインスタンスメタデータのIPアドレス (169.254.169.254) に対するルート情報が初期設定されているのですが、サブネットを移行することによってルート情報の整合性が取れなくなってしまうという問題です。

この事象に該当した場合には、上記のブログ記事を参照してルート情報の再初期化を行ってください。

Linuxインスタンスの場合にはこの問題は発生しないのですが、インスタンスメタデータへのアクセスができない際に考えられる原因の一つとして、ルートテーブルの確認は行うと良いと思います。

おわりに

Mackerelの導入は何度も行っていますが、今回のような「おかしな」事象は初めて遭遇しました。

一見「なんのこっちゃ??」となって原因が何なのかサッパリ見当がつかなかったのですが・・・実は、社内のMackerelエキスパートに聞いてみると「こんな事例が過去にあったよ」と教えてもらい、原因・対処法が分かったという訳です。

もし、同様の事象に遭遇した場合は、今回のブログ記事を参考にしてください。