AWS

CodePipelineに承認アクションを設定する

スポンサーリンク
CodePipelineに承認アクションを設定する AWS
スポンサーリンク
スポンサーリンク

CodePipelineに承認アクションを設定する

Codepipelineのステージに承認(Approval)アクションを追加することができます。

パイプラインが承認ステージまで進むと、一度動作が停止し、手動による承認を待機するステータスとなります。

今回は承認ステージになりましたら、SNSでメール通知する構成を目指します。

構築する環境

Diagram of setup Approval Action in CodePipeline.

CodePipelineを構成し、4つのリソースを連携させます。

1つ目はCodeCommitです。
CodeCommitはCodePipelineのソースステージを担当します。
Gitリポジトリとして使用します。

2つ目はCodeBuildです。
CodeBuildはCodePipelineのビルドステージを担当します。
CodeCommitにプッシュされたコードから、Dockerイメージをビルドします。
ビルドしたイメージをECRにプッシュします。

3つ目はSNSです。
SNSはCodePipelineの承認ステージを担当します。
パイプラインが承認ステージになりましたら、一旦パイプラインが停止し、SNSでメール通知します。
メールによる通知を受けたユーザは、パイプラインのページにアクセスし、承認ボタンを押すとパイプラインが再開されます。

4つ目はLambda関数です。
この関数の働きは、ECS(Fargate)サービスのタスク希望数を変更することです。
具体的には希望数を0から1に変更します。

CodePipelineにデプロイステージを作成します。
後述のFargateにデプロイするように設定します。

SSMパラメータストアにDockerHubアカウント情報を保存します。
DockerBuildでイメージを生成する際に、DockerHubにサインインした上でベースイメージをプルするために、これらを使用します。

CodePipelineが開始されるきっかけですが、CodeCommitへのプッシュを条件とします。
具体的には、EventBridgeに上記を満たすルールを用意します。

プライベートサブネットに、FargateタイプのECSを作成します。

EC2インスタンスを作成します。
Fargate上に作成されたコンテナにアクセスするためのクライアントして使用します。

CloudFormationテンプレートファイル

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

awstut-fa/080 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

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

本ページはCodepipeline内に承認ステージを作成し、SNSでメール通知する方法を取り上げます。

CodePipelineに関する基本的な事項については、以下のページをご確認ください。

CodePipelineにデプロイステージを作成し、ECS(Fargate)にデプロイする方法については、以下のページをご確認ください。

CodePipeline内でLambda関数を呼び出すアクションを定義し、ECS(Fargate)サービスの希望数を変更する方法については、以下のページをご確認ください。

プライベートサブネットにFargateを構築する方法については、以下のページをご確認ください。

CloudFormationカスタムリソースを使用して、CloudFormationスタック削除時に、自動的にS3バケット内のオブジェクトと、ECRリポジトリ内のイメージを削除します。
詳細につきましては、以下のページをご確認ください。

SNS

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

SNSトピックを作成します。
通知先にメールを指定します。

詳細については、以下のページをご確認ください。

CodePipeline

Resources: Pipeline: Type: AWS::CodePipeline::Pipeline Properties: ArtifactStore: Location: !Ref BucketName Type: S3 Name: !Ref Prefix RoleArn: !GetAtt CodePipelineRole.Arn Stages: - Actions: - ActionTypeId: Category: Source Owner: AWS Provider: CodeCommit Version: 1 Configuration: BranchName: !Ref BranchName OutputArtifactFormat: CODE_ZIP PollForSourceChanges: false RepositoryName: !GetAtt CodeCommitRepository.Name Name: Source OutputArtifacts: - Name: !Ref PipelineSourceArtifact Region: !Ref AWS::Region RunOrder: 1 Name: Source - Actions: - ActionTypeId: Category: Build Owner: AWS Provider: CodeBuild Version: 1 Configuration: ProjectName: !Ref CodeBuildProject InputArtifacts: - Name: !Ref PipelineSourceArtifact Name: Build OutputArtifacts: - Name: !Ref PipelineBuildArtifact Region: !Ref AWS::Region RunOrder: 1 Name: Build - Actions: - ActionTypeId: Category: Approval Owner: AWS Provider: Manual Version: 1 Configuration: CustomData: hoge hoge hoge. ExternalEntityLink: http://example.com NotificationArn: !Ref TopicArn InputArtifacts: [] Name: Approval OutputArtifacts: [] Region: !Ref AWS::Region RunOrder: 1 Name: Approval - Actions: - ActionTypeId: Category: Deploy Owner: AWS Provider: ECS Version: 1 Configuration: ClusterName: !Ref ECSClusterName FileName: !Ref ImageDefinitionFileName ServiceName: !Ref ECSServiceName InputArtifacts: - Name: !Ref PipelineBuildArtifact Name: Deploy Region: !Ref AWS::Region RunOrder: 1 Name: Deploy - Actions: - ActionTypeId: Category: Invoke Owner: AWS Provider: Lambda Version: 1 Configuration: FunctionName: !Ref ECSFunctionName InputArtifacts: [] Name: Invoke OutputArtifacts: [] Region: !Ref AWS::Region RunOrder: 1 Name: Invoke
Code language: YAML (yaml)

Stagesプロパティに承認ステージを定義します。
Configurationプロパティ内で、承認ステージの詳細設定を行います。特に重要なパラメータはNotificationArnプロパティです。本プロパティに先述のSNSトピックを指定します。
InputArtifactsおよびOutputArtifactsプロパティは空の配列を指定します。今回の挙動では、アーティファクトに対する読み書きは発生しないためです。

以下がCodePipeline用のIAMロールです。

Resources: CodePipelineRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - codepipeline.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: PipelinePolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - lambda:invokeFunction Resource: - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${ECSFunctionName}" - Effect: Allow Action: - codecommit:CancelUploadArchive - codecommit:GetBranch - codecommit:GetCommit - codecommit:GetRepository - codecommit:GetUploadArchiveStatus - codecommit:UploadArchive Resource: - !GetAtt CodeCommitRepository.Arn - Effect: Allow Action: - codebuild:BatchGetBuilds - codebuild:StartBuild - codebuild:BatchGetBuildBatches - codebuild:StartBuildBatch Resource: - !GetAtt CodeBuildProject.Arn - Effect: Allow Action: - s3:PutObject - s3:GetObject - s3:GetObjectVersion - s3:GetBucketAcl - s3:GetBucketLocation Resource: - !Sub "arn:aws:s3:::${BucketName}" - !Sub "arn:aws:s3:::${BucketName}/*" - Effect: Allow Action: - sns:Publish Resource: - !Ref TopicArn - Effect: Allow Action: - ecs:* Resource: "*" - Effect: Allow Action: - iam:PassRole Resource: "*" Condition: StringLike: iam:PassedToService: - ecs-tasks.amazonaws.com
Code language: YAML (yaml)

承認ステージ用の権限を設定します。
SNSトピックに対して、「sns:Publish」を許可します。

(参照)アプリコンテナ

Dockerfile

FROM amazonlinux RUN yum update -y && yum install python3 python3-pip -y RUN pip3 install bottle COPY main.py ./ CMD ["python3", "main.py"] EXPOSE 8080
Code language: Dockerfile (dockerfile)

アプリコンテナ用のイメージは、Amazon Linux 2をベースとして作成します。

Python製WebフレームワークのBottleを使用します。
ですからPythonおよびpipをインストール後、これをインストールします。

アプリロジックを記載したPythonスクリプト(main.py)をコピーし、これを実行するように設定します。

先述の通り、アプリはtcp/8080でHTTPリクエストを待ち受けますので、このポートを公開します。

main.py

from bottle import route, run @route('/') def hello(): return 'Hello CodePipeline.' if __name__ == '__main__': run(host='0.0.0.0', port=8080)
Code language: Python (python)

Bottleを使用して、簡易的なWebサーバを構築します。
8080/tcpでHTTPリクエストを待ち受け、「Hello CodePipeline.」を返すという単純な構成です。

環境構築

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

CloudFormationスタックを作成し、スタック内のリソースを確認する

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

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

  • ECR:fa-080
  • CodeCommit:fa-080
  • CodeBuild:fa-080
  • CodePipeline:fa-080
  • Lambda関数:fa-080-function-ecs
  • SNSトピック:fa-080

メールアドレスの認証

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

詳細につきましては、以下のページをご確認ください。

リソース確認

AWS Management Consoleから各リソースを確認します。
CodePipelineを確認します。

Detail of CodePipeline 1.

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

作成されているステージに注目します。
Approvalという名前で、SNSトピックを呼び出すステージが用意されています。
パイプラインがこのステージまで到達すると、一旦停止し、承認を待つことになります。

動作確認

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

まずCodeCommitをプルします。

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

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

リポジトリにDockerfileおよびmain.pyを加えます。

$ ls -al total 8 drwxrwxr-x 3 ec2-user ec2-user 51 Aug 20 23:54 . drwxrwxr-x 3 ec2-user ec2-user 20 Aug 20 23:53 .. -rw-rw-r-- 1 ec2-user ec2-user 187 Aug 12 11:01 Dockerfile drwxrwxr-x 7 ec2-user ec2-user 119 Aug 20 23:53 .git -rw-rw-r-- 1 ec2-user ec2-user 691 Aug 20 11:25 main.py
Code language: Bash (bash)

2ファイルをCodeCommitにプッシュします。

$ git add . $ git commit -m 'first commit' [master (root-commit) 6bfe691] first commit ... 2 files changed, 39 insertions(+) create mode 100644 Dockerfile create mode 100644 main.py $ git push ... * [new branch] master -> master
Code language: Bash (bash)

正常にプッシュできました。

しばらく待機した後、改めてCodePipelineを確認します。

Detail of CodePipeline 2.

パイプラインが開始されました。
SourceおよびBuildステージは正常に完了し、承認(Approval)ステージに到達しました。
ただしステータスは「Pending」とあり、「Waiting for approval」というメッセージが表示されてます。
つまり権限を持つユーザが承認するまで、この状況は継続されることになります。

SNSトピックから、以下の通りメールが届きます。

Detail of CodePipeline 6.

このようにメールによって、ユーザに承認を待っていることを知らせることができます。

パイプラインの承認に必要な権限につきましては、AWS公式ページでは、以下の通り示されています。

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codepipeline:ListPipelines" ], "Resource": [ "*" ] }, { "Effect": "Allow", "Action": [ "codepipeline:GetPipeline", "codepipeline:GetPipelineState", "codepipeline:GetPipelineExecution" ], "Resource": "arn:aws:codepipeline:us-east-2:80398EXAMPLE:MyFirstPipeline" }, { "Effect": "Allow", "Action": [ "codepipeline:PutApprovalResult" ], "Resource": "arn:aws:codepipeline:us-east-2:80398EXAMPLE:MyFirstPipeline/MyApprovalStage/MyApprovalAction" } ] }
Code language: JSON / JSON with Comments (json)
CodePipeline で IAM ユーザーに承認アクセス許可を付与する - AWS CodePipeline
CodePipeline のマネージドポリシーを IAM ユーザーに添付する方法について説明します。

上記の権限を満たすユーザで承認を進めます。

Detail of CodePipeline 3.

「Approval」を押下し、承認します。

Detail of CodePipeline 4.

「Approved」と表示されました。
つまり承認することによって、パイプラインが再開されたということです。
しばらく待機します。

Detail of CodePipeline 5.

パイプラインの全ステージが完了しました。

Fargateを確認します。

Detail of ECS 1.
Detail of ECS 2.

ECS(Fargate)のタスク希望数が1であり、そのタスクのIPアドレスが「10.0.2.4」であることがわかります。

実際にタスク内のコンテナにアクセスします。

% aws ssm start-session --target i-0c41c5926230b480c Starting session with SessionId: root-0c76e08548a26fec6 sh-4.2$
Code language: Bash (bash)

SSM Session Managerの詳細につきましては、以下のページをご確認ください。

curlコマンドを使って、タスク内のコンテナにアクセスします。

sh-4.2$ curl http://10.0.2.4:8080/ Hello CodePipeline.
Code language: Bash (bash)

コンテナから応答がありました。
確かにBottleアプリで設定した文字列です。
このことから、確かにパイプラインが実行されたということがわかります。
このようにCodePipelineに承認ステージを作成することによって、パイプラインの一時停止、SNSによるメール通知、承認によるパイプラインの再開を実装することができました。

まとめ

CodePipelineに承認ステージを作成し、SNSでメール通知する方法を確認しました。

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