LoginSignup
1
1

AWS CDKでLambdaとSQSのエラー送信機能を構築

Last updated at Posted at 2023-10-03

AWS CDKとは

AWS CDK(Cloud Development Kit)は、Amazon Web Services(AWS)のクラウドリソースをプログラム的に構築およびデプロイするためのフレームワークです。CDKを使用すると、プログラミング言語(TypeScript、Python、Java、C#など)を使用して、AWSインフラストラクチャのコードを記述できます。CDKは、AWSリソースのプロビジョニングと設定をコードで管理するためのツールセットを提供し、インフラストラクチャのコード化による可読性、保守性、再利用性を向上させます。

image.png

アーキテクチャー

スクリーンショット 2023-09-28 9.22.02.png

今回実現したい機能はLambdaでエラー発生またはSQSがDLQに溜まってしまった場合、システム管理者へメール送信します。
Lambdaのエラー監視とSQS DLQの数量監視でSNSを用いてメール送信機能を実現しました。

SNSのTopicの事前作成

エラー通知用のSNS Topicを事前に作成した上で、サブスクリプションのメール通知先のメールアドレスを追加しておきます。
スクリーンショット 2023-10-03 13.19.38.png

//通知先の作成
const batchResultNotifyTopic = sns.Topic.fromTopicArn(this, <id>, <topic-ARN>);
const batchResultNotifyDestination = new SnsDestination(batchResultNotifyTopic);

※SDK

CDKの作成

amplify cli

まずはamplify cli を用いてCDKを作成する

amplify add custom
✔ How do you want to define this custom resource? · AWS CDK
✔ Provide a name for your custom resource · testcdk
✅ Created skeleton CDK stack in amplify/backend/custom/testcdk directory
✔ Do you want to edit the CDK stack now? (Y/n) · yes
Edit the file in your editor: ***custom/testcdk/cdk-stack.ts
? Press enter to continue 
import * as cdk from '@aws-cdk/core';
import * as AmplifyHelpers from '@aws-amplify/cli-extensibility-helper';
import { AmplifyDependentResourcesAttributes } from '../../types/amplify-dependent-resources-ref';
//import * as iam from '@aws-cdk/aws-iam';
//import * as sns from '@aws-cdk/aws-sns';
//import * as subs from '@aws-cdk/aws-sns-subscriptions';
//import * as sqs from '@aws-cdk/aws-sqs';

export class cdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps, amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps) {
    super(scope, id, props);
    /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
    new cdk.CfnParameter(this, 'env', {
      type: 'String',
      description: 'Current Amplify CLI env name',
    });
  }
}

Lambda依存関係の追加

import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref";

const dependencies: AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(this,
  amplifyResourceProps.category,
  amplifyResourceProps.resourceName,
  [
    {
        category: "function", // api, auth, storage, function, etc.
        resourceName: "alretNotification" //先に作ったエラー通知先のlamda
        // find the resource at "amplify/backend/<category>/<resourceName>"
    }, /* add more dependencies as needed */
    { 
        category: 'custom', 
        resourceName: '<resource-name>' // SQSリソース名
    }
] 
);

cdk.Fn.ref関数を使用して、依存関係の出力を参照します

const myFunctionArn = cdk.Fn.ref(dependencies.function.<resource-name>.Arn)

Roleインポート

batchFnction.forEach(functionName => {
      //Lamdaの取得
      // Roleインポート
      const targetLamda: lambda.IFunction = lambda.Function.fromFunctionAttributes(this, functionName + 'Lambda', {
        functionArn: cdk.Fn.ref(dependencies.function[functionName].Arn),
        role: iam.Role.fromRoleArn(this, functionName + 'Role', `arn:aws:iam::${cdk.Stack.of(this).account}:role/${cdk.Fn.ref(dependencies.function[functionName].LambdaExecutionRole)}`)
      });
    });

Lambda非同期失敗のSNS通知

batchFnction.forEach(functionName => {
      //Lamdaの実行結果の送信先設定
      // 非同期処理失敗時SNS送信
      //※sns:Publishのポリシーも自動的に追加される
      targetLamda.configureAsyncInvoke({
        onFailure: batchResultNotifyDestination,// 前述の通知先
      });

※SDK
https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.FunctionAttributes.html
https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-lambda.Function.html

SQS DLQの検知と送信

Cloud WatchのAlarm機能を利用して、DLQの件数が1を超えたら、SNS送信を行います。

   //
    //SQS(DLQ)にメッセージ検知し、SNS送信
    //
    const dlqList = [
      { name: <DLQ Name>, Arn: <DLQ ARN> },
    ]

    dlqList.forEach(dlq => {
      //sqsの取得
      const dlqQueue = sqs.Queue.fromQueueArn(this, dlq.name + 'Queue', cdk.Fn.ref(dlq.Arn));

      //アラーム作成(1分間に1件/1データポイント中発生すれば、アラーム)
      const alarm = new cloudwatch.Alarm(this, `Alarm-${dlq.name}`, {
        alarmName: `Alarm-${dlq.name}-${cdk.Fn.ref('env')}`,
        metric: dlqQueue.metricApproximateNumberOfMessagesVisible(),
        period: cdk.Duration.seconds(60), //メトリックまたは式を評価して、アラームの個々のデータポイントを作成する時間の長さ
        evaluationPeriods: 1, //アラーム状態を判断するときに評価する最新の期間またはデータポイントの数
        threshold: 1,
        datapointsToAlarm: 1, //period期間中のEvaluationPeriodsの内、DatapointsToAlarm回発生すれば、アラーム通知
        comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD //評価の比較演算子
      });
      //アラーム通知先設定
      alarm.addAlarmAction(new SnsAction(batchResultNotifyTopic));
    })

Construct Props

属性 タイプ 説明
evaluationPeriods number アラーム状態を判断するときに評価する最新の期間またはデータポイントの数
metric IMetric アラームを追加するメトリック
threshold number 閾値、指定された統計が比較される値
actionsEnabled? boolean このアラームのアクションが有効かどうか。
alarmDescription? string アラームの説明
alarmName? string アラームの名前
comparisonOperator? ComparisonOperator メトリクスが違反しているかどうかを確認するために使用する比較。
datapointsToAlarm? number アラームをトリガーするために違反する必要があるデータポイントの数。
evaluateLowSampleCountPercentile? string データ ポイントが少なすぎて統計的に有意でない場合に、データを評価し、アラーム状態を変更する可能性があるかどうかを指定します。
period? Duration メトリックまたは式を評価して、アラームの個々のデータポイントを作成する時間の長さ
statistic? string 集計に使用する関数。
treatMissingData? TreatMissingDat このアラームが欠落しているデータ ポイントを処理する方法を設定します。

ComparisonOperatorメンバー

名前 説明
GREATER_THAN_OR_EQUAL_TO_THRESHOLD 指定された統計がしきい値以上です。
GREATER_THAN_THRESHOLD 指定された統計はしきい値を厳密に超えています。
LESS_THAN_THRESHOLD 指定された統計は厳密にしきい値未満です。
LESS_THAN_OR_EQUAL_TO_THRESHOLD 指定された統計がしきい値以下です。
LESS_THAN_LOWER_OR_GREATER_THAN_UPPER_THRESHOLD 指定された統計量が異常モデルの帯域よりも小さいか大きいです。
GREATER_THAN_UPPER_THRESHOLD 指定された統計量が異常モデルの帯域よりも大きいです。
LESS_THAN_LOWER_THRESHOLD 指定された統計量は、異常モデルの帯域よりも低いです。

※SDK
https://docs.aws.amazon.com/cdk/api/v1/docs/@aws-cdk_aws-cloudwatch.Alarm.html

トラブルシューティング

遭遇したトラブルをメモします。

  1. CloudWatch アラームトリガーの SNS 通知を受信しなかったのはなぜですか?

ご参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1