Lambda + SQS サーバーレスアプリのデプロイ後に発生した Amazon DevOps Guru インサイトに対応してみる
いわさです。
先日見慣れない通知を受信しました。
30 分 ~ 1 時間ごとに 2 ~ 3 通繰り返し受信しています。
{ : "InsightId": "AMxSFH12NiEZZsr-jfHFv2kAAAAAAAAAAo9JEljAspyrigPkDSFhyIgEF5aXkZgR", "InsightDescription": "SQS triggered Lambda does not have a Dead Letter Queue", "InsightSeverity": "medium", "StartTime": 1669356000000, "Anomalies": [ { "Id": "AcnYFT7UD35NVOSXRDW6XZX67EOHVN7OTUHMFJPAZKDKOCRERB6YTKQF2M5RZ2WU", "StartTime": 1669356000000, "Description": "SQS triggered Lambda does not have a Dead Letter Queue", "AnomalyResources": [ { "Type": "AWS::Lambda::Function", "Name": "hoge1125lambdaevent-SQSPayloadLogger-8yaFk7Vyfx5J" } ] } ], "awsInsightSource": "aws.devopsguru" }
{ : "InsightId": "AM8mvERGkPsU6dwcJ85E6ygAAAAAAAAAAAL0QXTA2FI4Jd01RiVZPixSlpaMyPeM", "InsightDescription": "Lambda timeout exceeds recommended SQS visibility timeout", "InsightSeverity": "medium", "StartTime": 1669359600000, "Anomalies": [ { "Id": "AcnYZ2I6EEU7EP5VH2PZCZFW3DVS22XLQFJHMZBXYWA3ORR5UU7RB6OI6UXBECQN", "StartTime": 1669359600000, "Description": "Lambda timeout exceeds recommended SQS visibility timeout", "AnomalyResources": [ { "Type": "AWS::Lambda::Function", "Name": "hoge1125lambdaevent-SQSPayloadLogger-8yaFk7Vyfx5J" } ], "SourceDetails": [ { "DataSource": "CW_METRICS", "DataIdentifiers": { "period": "3600", "stat": "Maximum", "unit": "MILLISECONDS", "ResourceId": "hoge1125lambdaevent-SQSPayloadLogger-8yaFk7Vyfx5J", "name": "Duration", "namespace": "AWS/Lambda", "ResourceType": "Lambda/Function", "dimensions": "{\"FunctionName\":\"hoge1125lambdaevent-SQSPayloadLogger-8yaFk7Vyfx5J\"}" } } ] } ], "ResourceCollection": { "CloudFormation": { "StackNames": [ "hoge1125lambdaevent" ] } }, "awsInsightSource": "aws.devopsguru" }
awsInsightSource
にはaws.devopsguru
と出力されています。
どうやら Amazon DevOps Guru による通知のようです。
たしかに以前 DevOps Guru を有効化し通知を ON にしていた記憶があります。
本日はインサイトを確認しアプリケーションを修正、インサイトの解決を確認するところまでを通して行ってみました。
これが DevOps Guru のベーシックな流れなのだと思いますが、事象がわかれば同様にインサイトを簡単に発生させることも出来るので今後の検証時に利用出来そうです。
デプロイしたアプリケーション
別の検証のために以下のサーバーレスアプリケーションをデプロイしていました。
EventBridge で定期的に Lambda 関数を実行し SQS キューへメッセージを送信します。別の Lambda でキューをトリガーに処理実行するというイベント駆動のベーシックなやつです。
アプリケーション自体は特に問題は発生せず動作しているように見受けられました。
参考までに、SAM テンプレートは以下のようなものをデプロイしていました。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: --- Globals: Function: Timeout: 10 Tracing: Active Api: TracingEnabled: True Resources: ScheduledEventLogger: Type: AWS::Serverless::Function Properties: CodeUri: ./src/hoge1125dotnet/ Handler: hoge1125dotnet::hoge1125dotnet.Function1::FunctionHandler Runtime: dotnet6 Architectures: - x86_64 MemorySize: 256 Events: CloudWatchEvent: Type: Schedule Properties: Schedule: cron(0/1 * * * ? *) Environment: Variables: SQS_URL: !Ref SimpleQueue HogeConnector: Type: AWS::Serverless::Connector Properties: Destination: Id: SimpleQueue Source: Id: ScheduledEventLogger Permissions: - Write SimpleQueue: Type: AWS::SQS::Queue SQSPayloadLogger: Type: AWS::Serverless::Function Properties: CodeUri: ./src/hoge1125dotnet/ Handler: hoge1125dotnet::hoge1125dotnet.Function2::FunctionHandler Runtime: dotnet6 Architectures: - x86_64 MemorySize: 256 Events: SQSQueueEvent: Type: SQS Properties: Queue: !GetAtt SimpleQueue.Arn Policies: - AWSLambdaBasicExecutionRole
インサイトを確認
では Amazon DevOps Guru のダッシュボードからインサイトを確認出来るので見てみましょう。
ダッシュボード上には継続中の予測的インサイトが 3 と表示されており、異常なアプリケーションとして hoge1125lambdaevent という先ほどのアプリケーションが示されています。
インサイト一覧からは大きく事後的(リアクティブ)インサイトと予測的(プロアクティブ)インサイトが確認出来ます。
事後的インサイトには現在発生している異常な動作の修復に使用出来る推奨事項とデータが含まれています。
予測的インサイトには将来発生すると予測される異常な動作を修正するために使用出来る推奨事項とデータが含まれています。
今回通知されたインサイトは予測的インサイトでした。
今時点で問題が起きているわけではないですが、将来発生する可能性のある異常に備えて対策が推奨されています。
何も意識せずデプロイして動作確認していましたが、以下のインサイトから大きく2つの推奨事項を確認することが出来ました。
デッドレターキュー
SQS triggered Lambda does not have a Dead Letter Queue
SQS キューにはデッドレターキューという取得回数が一定以上を超えた場合の別のキューを設定しておくことが可能です。
1つ目の推奨事項ではデッドレターキューが設定しましょうという推奨がされています。
可視性タイムアウト
またまた SQS に関してですが、キューからメッセージを取得しても削除するまで残ります。
重複した取得を緩和するための機能として一定期間メッセージを取得できなくする可視性タイムアウトという機能があります。
この推奨事項では使用状況から可視性タイムアウトに 60 秒を設定することが推奨されています。
推奨事項に対処する
まずは実際の各設定値を確認しました。
Lambda のタイムアウトは 10 秒となっていました。
SQS の可視性タイムアウトは 30 秒、デッドレターキューはなしという状態でした。
ここで推奨事項に対応するべきなのかを先に軽く調べます。
以下は AWS re:Invent 2020 のサーバーレス + イベント駆動アーキテクチャーに関するセッションレポートです。
その中で多くのベストプラクティスが挙げられているのですが、今回の推奨事項と同じようなプラクティスも登場します。
- 低並列、長時間の関数の場合、可視性タイムアウトを関数タイムアウトの 6 倍に設定する。受信カウントが不要に増加し、デッドレターキューに送られることを避けられる
- SNS や非同期イベントがソースの場合は常にデッドレターキューを設定することを強くお勧めします
実際に問題がまだ起きているわけではないのですが、DevOps Guru がベストプラクティス非準拠の設定内容について検知し推奨してくれている形です。
早速対応してみましょう。
修正箇所は具体的に挙げられていますのでそのまま対応します。
SAM テンプレートを以下のように修正して、可視性タイムアウトに 60 秒を設定、デッドレターキューを設定しました。
Resources: : SimpleQueue: Type: AWS::SQS::Queue Properties: VisibilityTimeout: 60 RedrivePolicy: deadLetterTargetArn: !GetAtt MyDeadLetterQueue.Arn maxReceiveCount: 3 MyDeadLetterQueue: Type: AWS::SQS::Queue :
対処後
対処後すぐにはインサイトステータスは変わりません。
インサイトステータスが変わらない間は引き続き定期的に通知が送信され続けます。
対処後に手動でアラートを抑制あるいは強制的にステータスを更新させる機能があるとありがたいのですが本日時点で確認は出来ませんでした。
だいたい設定変更から 10 時間後、インサイトステータスが更新され、アラートが通知されなくなりました。
ダッシュボードでも以下のように異常なアプリケーションとして認識されなくなりました。
インサイト画面では「期限切れ」というステータスが過去のインサイトを確認することが出来ます。
さいごに
本日は Lambda + SQS サーバーレスアプリ で Amazon DevOps Guru のインサイトに対応しました。
セキュリティ周りは Security Hub をきっかけにベストプラクティスに沿っているか見直しをすることが出来て恩恵を感じる人も多いと思いますが、セキュリティ以外のベストプラクティスにもこういった形で推奨を出してくれるサービスがあるというのはありがたいなと思いました。
DevOps Guru でカバー出来る範囲のリソースであればとりあえず有効化してインサイトを取得出来るようにしておくのはとても有効だと感じました。