DVA

CodePipelineでエラー発生時にSNSでメール通知する

CodePipelineでエラー発生時にSNSでメール通知する

AWS DVAの出題範囲の1つでもある、モニタリング・トラブルシューティングに関する内容です。

CodePipelineでCI/CD環境においてエラーが発生した際の通知方法について考えます。

AWS公式では、通知方法について以下の通りに説明されています。

You can set up notifications so that users of a resource, such as a build project, repository, deployment application, or pipeline, receive emails about the event types you specify according to the notification rule you create.

Notification concepts

本ページではこの通知ルールを使用して、パイプライン上で発生したエラーメッセージを、SNSを通じてメール通知する方法をご紹介します。

構築する環境

Diagram of email notification via SNS when error occurs in CodePipeline.

基本的な構成は、以下のページでご紹介したものと同様です。

これはCodePipelineを使用したCloudFormation用のCI/CD環境です。

本ページにおける変更点は、以下の2点です。

1点目はCodePipelineに通知ルールを設定する点です。
ルールは、パイプライン上で発生し得るエラー情報を通知するものです。

2点目は通知ルールの通知先に関する設定です。
内容をSNSを通じてメール通知します。

今回はテストスタック作成に、意図的に失敗を発生させます。
パイプラインのそれ以降のアクション・ステージには進みません。
失敗を受けて、通知ルールに従って、SNS経由でメールが通知されます。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

awstut-dva/05/002 at main · awstut-an-r/awstut-dva
Contribute to awstut-an-r/awstut-dva development by creating an account on GitHub.

テンプレートファイルのポイント解説

本ページでは、CodePipelineにおける通知ルールに関する内容を中心に取り上げます。

それ以外の内容については、冒頭のページをご確認ください。

通知ルール

Resources:
  NotificationRule:
    Type: AWS::CodeStarNotifications::NotificationRule
    Properties: 
      DetailType: BASIC
      EventTypeIds: 
        - codepipeline-pipeline-action-execution-failed
        - codepipeline-pipeline-stage-execution-failed
        - codepipeline-pipeline-pipeline-execution-failed
        - codepipeline-pipeline-manual-approval-failed
      Name: !Sub "${Prefix}-NotificationRule"
      Resource: !Sub "arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}"
      Status: ENABLED
      Targets: 
        - TargetAddress: !Ref TopicArn
          TargetType: SNS
Code language: YAML (yaml)

通知ルールを作成する上でのポイントは3点です。

1点目は通知元です。
ResourceプロパティにCodePipelineのARNを指定します。

2点目は通知先です。
TargetsプロパティにSNSトピックのARN等を指定します。

3点目は通知するイベントに関する情報です。
EventTypeIdsプロパティに通知するイベントのIDを指定します。
通知可能なイベントですが、以下のAWS公式ページでまとめられています。

Notification concepts - Developer Tools console
Learn about important notification concepts.

今回はCodePipelineに関する4つのFailed通知を指定します。

SNS

トピック

Resources:
  Topic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription: 
        - Endpoint: !Ref MailAddress
          Protocol: email
      TopicName: !Ref Prefix
Code language: YAML (yaml)

特別な設定は不要です。
サブスクライバーにメールアドレスを指定します。

アクセスポリシー

Resources:
  TopicPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties: 
      PolicyDocument:
        Statement:
          - Principal:
              Service: codestar-notifications.amazonaws.com
            Action: sns:Publish
            Effect: Allow
            Resource: !Ref TopicArn
            Condition:
              StringEquals:
                aws:SourceAccount: !Ref AWS::AccountId
      Topics: 
        - !Ref TopicArn
Code language: YAML (yaml)

通知先にSNSを指定する場合に、重要なポイントはSNSのアクセスポリシーです。

以下のAWS公式ページに従い、アクセスポリシーを設定します。

Configure Amazon SNS topics for notifications - Developer Tools console
The easiest way to set up notifications is to create an Amazon SNS topic when you create a notification rule. You can use an existing Amazon SNS topic if it mee...

上記の通り、プリンシパルにCodeStarを指定した上で、「sns:Publish」を許可します。

CloudFormation関係のファイル

CodePipeline内のCloudFormationを実行するためのファイルを確認します。

テンプレートファイル

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  Prefix:
    Type: String
    Default: dva-05-002-sample-lambda

  Environment:
    Type: String
    Default: test
    
  Handler:
    Type: String
    Default: index.lambda_handler
    
  MemorySize:
    Type: Number
    Default: 128
    
  Runtime:
    Type: String
    Default: python3.8
    
  Timeout:
    Type: Number
    Default: 5
    
    
Resources:
  Function:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          def lambda_handler(event, context):
            print('sample lambda')
      FunctionName: !Sub "${Prefix}-${Environment}-Function"
      Handler: !Ref Handler
      MemorySize: !Ref MemorySize
      Runtime: !Ref Runtime
      Role: !GetAtt LambdaRole.Arn

  LambdaRole:
    Type: AWS::IAM::Role
    DeletionPolicy: Delete
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Action: sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Code language: YAML (yaml)

Lambda関数およびIAMロールを定義します。

関数名(FunctionName)とメモリサイズ(MemorySize)がポイントです。
それぞれパラメータを埋め込む形で指定しますが、これらの値は後述のテンプレート設定ファイルによって、テストスタック・本番スタックで異なる値を設定します。

テストスタック用テンプレート設定ファイル

{
  "Parameters" : {
    "Environment": "test",
    "MemorySize": "0"
  }
}
Code language: JSON / JSON with Comments (json)

メモリサイズの値がポイントです。
あえて0 (MB)を指定します。
これでスタック作成時に失敗させます。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • SNSトピック:fa-117
  • CodeCommit:dva-05-002
  • CodePipeline:dva-05-002

メールアドレスの認証

SNSトピックのサブスクライバーとしてメールアドレスを指定した場合、そのメールアドレスを認証する必要があります。
指定したメールアドレスに、以下のような認証メールが送られてきます。

Detail of SNS 1.

「Confirm subscription」を押下して、認証を進めます。

Detail of SNS 2.

上記のページが表示されて、認証が完了したことがわかります。

リソース確認

AWS Management Consoleから各リソースを確認します。
まずSNSトピックを確認します。

Detail of SNS 3.

SNSトピックのサブスクライバーとして、メールアドレスが指定されています。

CodePipelineを確認します。

Detail of CodePipeline 1.

パイプラインの実行に失敗しています。
これはCloudFormationスタック作成時に、CodeCommitが作成されたことがきっかけとして、パイプラインが実行されたためです。
現時点ではCodeCommitにコードをプッシュしていないため、パイプライン実行の過程でエラーが発生しました。

通知ルールを確認します。

Detail of CodePipeline 2.

確かに通知ルールが作成されています。

通知先に先述のSNSトピックが指定されており、有効化されていることがわかります。
つまりCodeStarがSNSトピックに対して、メッセージを通知する権限が適切に設定されているということです。

詳細も確認します。

Detail of CodePipeline 3.

CodePipelineに関するFailed通知を送信する内容です。

動作確認

準備が整いましたので、CodeCommitにコードをプッシュします。

$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dva-05-002
Cloning into 'dva-05-002'...
warning: You appear to have cloned an empty repository.
Code language: Bash (bash)

空のリポジトリがプルされました。

リポジトリに3つのファイル(sample-lambda.yaml、test-stack-configuration.json、prod-stack-configuration.json)を加えます。

$ ls -al
total 12
drwxrwxr-x 3 ec2-user ec2-user  118 Jan 22 11:31 .
drwxrwxr-x 4 ec2-user ec2-user  151 Jan 22 11:31 ..
drwxrwxr-x 7 ec2-user ec2-user  119 Jan 22 11:31 .git
-rw-rw-r-- 1 ec2-user ec2-user   98 Jan 18 12:43 prod-stack-configuration.json
-rw-rw-r-- 1 ec2-user ec2-user 1667 Jan 18 11:40 sample-lambda.yaml
-rw-rw-r-- 1 ec2-user ec2-user   95 Jan 21 11:55 test-stack-configuration.json
Code language: Bash (bash)

3ファイルをプッシュします。

$ git add .

$ git commit -m 'first commit'
...
 create mode 100644 prod-stack-configuration.json
 create mode 100644 sample-lambda.yaml
 create mode 100644 test-stack-configuration.json

$ git push
...
 * [new branch]      master -> master
Code language: Bash (bash)

正常にプッシュできました。
これでパイプラインが開始されました。

しばらく待つと、パイプラインが途中が失敗します。

Detail of CodePipeline 4.

テストスタックの作成に失敗しています。
先述の通り、Lambda関数のメモリサイズを「0」としたことが原因です。

すぐに以下にメールが届きました。

Detail of SNS 4.

メールは3件届きました。
Pipeline execution、Stage execution、Action executionに関するエラーが発生した旨が記されています。

CloudFormationスタックも確認します。

Detail of CloudFormation 1.

確かにテストスタックの作成に失敗しています。

このように通知ルールを作成し、その通知先にSNSトピックを指定することによって、CodePipeline実行時のエラーをメール通知することができました。

まとめ

CodePipelineでエラー発生時にSNSでメール通知する方法をご紹介しました。

タイトルとURLをコピーしました