Amazon EFSをマウントしているのは誰だ?
NFS ファイルシステムのマネージド・サービス Amazon EFS は EC2/Lambda/Fargate など複数のサービスから利用することができます。
Amazon EFSが活用が広まるにつれ、EFSをマウントしているクライアントを把握したことがあります。
そのようなときは、VPC フローログを有効化し、ログからEFS(NFS)用ポート(2049)に通信しているクライアントを特定します。
本ブログでは、次のナレッジベースを参考に、VPCフローログを CloudWatch Logs・S3 それぞれに出力したケースに置いて、クライアントを絞り込む方法を紹介します。
Amazon EFS に接続されている EC2 インスタンスを確認する
構成図
VPC フローログの有効化
次のドキュメントを参考に、VPC フローログを有効化し、CloudWatch Logs または S3 に出力します。
VPC フローログ - Amazon Virtual Private Cloud
Log record formatは次の2種類から選べます。
- AWS default format
- Custom format
まずはシンプルなデフォルトフォーマットを検討し、要件を満たせない場合は、カスタムフォーマットを検討することをおすすめします。
以下の探索では、デフォルトフォーマットを前提とします。
CloudWatch Logs のフローログを探索
CloudWatch コンソールから、フローログが CloudWatch Logs に出力されていることを確認します。
コンソールから確認
CloudWatch Logs Insights で ポート 2049 へのフローログを探索します。
ソースIPの件数ごとにソートする場合、次のクエリーを実行します。
filter dstPort="2049" | stats count(*) as FlowLogEntries by srcAddr | sort FlowLogEntries desc
コマンドラインから確認
コマンドラインから探索する場合、Logs::StartQuery API を利用します。
クエリーは非同期に実行されるため、クエリーをキューイング後、少し間をおいてから Logs::GetQueryResults でクエリー結果を取得します。
クエリーのキューイングからクエリー結果の取得までをまとめたのが、次のコマンドです。
$ aws logs start-query \ --log-group-name LOG-GROUP-NAME \ --start-time 1614174045 \ --end-time 1614174645 \ --query-string 'filter dstPort="2049" | stats count(*) as FlowLogEntries by srcAddr| sort FlowLogEntries desc' > test.json && \ sleep 10 && \ jq .queryId test.json | xargs aws logs get-query-results --query-id { "status": "Complete", "statistics": { "recordsMatched": 37.0, "recordsScanned": 874.0, "bytesScanned": 122012.0 }, "results": [ [ { "field": "srcAddr", "value": "172.31.33.180" }, { "field": "FlowLogEntries", "value": "19" } ], [ { "field": "srcAddr", "value": "172.31.41.13" }, { "field": "FlowLogEntries", "value": "18" } ] ] }
- ログ探索範囲は
--start-time/--end-time
引数に UNIX TIME で指定します。 --query-string
にはコンソールと同じクエリーを指定します- クエリーの実行は非同期に実行されます。完了までの待ち時間は
sleep 10
で調整しています。
S3 のフローログを探索
S3 コンソールから、フローログが S3 バケット の次のパス以下に出力されていることを確認します。
s3://BUCKET-NAME/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/YYYY/MM/dd/
Athena テーブルの作成
次のドキュメントを参考に、VPC Flow Logs用のAthenaテーブルを作成します。
Amazon VPC フローログのクエリ - Amazon Athena
Athena でS3のフローログを探索
テーブルを定義したあとは、SQL で問い合わせるだけです。
先程の CloudWatch Insights のクエリーを Athena に置き換えます。
SELECT sourceaddress, count(*) AS FlowLogEntries FROM vpc_flow_logs WHERE destinationport = 2049 AND starttime >= 1614174045 AND endtime <= 1614174645 AND date = DATE('2021-02-24') GROUP BY sourceaddress ORDER BY FlowLogEntries desc;
startdate/enddate
だけを指定するとフルスキャンになるため、パーティション化されたdate
も WHERE 条件に渡すと良いでしょう。
インスタンスIDを特定したいときはカスタムフィールドを利用
Log record formatにAWSデフォルトフォーマットを指定すると、VPC Flow Logs からは Amazon Elastic Network Interfaces(ENI)単位のフローログしかわかりません。
調査目的によっては、ENI(ソースIP)を利用しているインスタンスIDを特定したいこともあるでしょう。
そのようなときは、VPC Flow Logs作成時にカスタムフォーマットを選択し、${interface-id}
と ${dstport}
を出力させます。
filter @message like /2049/ | stats count(*) as FlowLogEntries by @message
のようにすれば、NFS 通信しているクライアントをインスタンスIDで類別できます。
ただし、Lambda など非EC2インスタンスはインスタンスIDが「-」で出力され、識別できないことにご留意ください。
まとめ
EFS を利用しているクライアントを特定するにはVPC Flow Logsを利用します。 CloudWatch Logs に出力されたログは CloudWatch Insightsで探索し、S3に出力されたログは Athena で探索します。
インスタンスIDなど、デフォルトフォーマットに存在しないフィールドが必要な場合は、ログフォーマットをカスタマイズしてください。
それでは。