こんにちは、SCSK の広野です。
私は Amazon API Gateway と AWS Lambda 関数の CI/CD を学習する社内研修を開催しておりまして、研修用 CI/CD パイプラインを AWS Code シリーズのサービスと AWS SAM (Serverless Application Model)、AWS CloudFormation で作成しています。
本記事では、その環境を抜粋して AWS CloudFormation でデプロイできるようにしたものを紹介します。
アーキテクチャ
以下のように、AWS サービスを組み合わせて作成しています。
- 開発環境は AWS Cloud9 を使用。
- ソースコード管理に AWS CodeCommit を使用。Lambda 関数コードだけでなく、ビルド設定ファイル buildspec.yml と AWS SAM テンプレートファイル template.yml もセットで管理する。
- コードの変更検知に Amazon EventBridge を使用。AWS CodeCommit のソースコードが変更されると CI/CD パイプラインを開始させる。
- CI/CD パイプラインに AWS CodePipeline を使用。ビルドステージで AWS CodeBuild、AWS SAM を、デプロイステージで AWS CloudFormation を使用。AWS SAM で API Gateway と Lambda 関数をデプロイする。
- パイプラインの各ステージで作成される成果物 (アーティファクト) 置き場に Amazon S3 を使用。
※図は簡略化していますが 2つのバケットがあります。SAM テンプレート (API Gateway と Lambda 関数リソース作成) と Lambda 関数コードの ZIP で。
CI/CD パイプライン準備
CI/CD パイプラインは、以下の AWS CloudFormation テンプレートを流すことでデプロイできます。※ Cloud9 や VPC は除く
AWSTemplateFormatVersion: 2010-09-09
Description: The CloudFormation template that creates a S3 bucket, a CI/CD environment with Code service series, and relevant IAM roles.
Parameters:
# ------------------------------------------------------------#
# Input Parameters
# ------------------------------------------------------------#
YourID:
Type: String
Description: Please fill your full name and today's date, or another unique name. (e.g. yujihirono20231202) You can not use any upper cases and special characters.
MaxLength: 100
MinLength: 5
Resources:
# ------------------------------------------------------------#
# CodeCommit Repository
# ------------------------------------------------------------#
SampleProjectRep:
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: !Sub SampleProject-${YourID}
Tags:
- Key: Cost
Value: !Ref YourID
# ------------------------------------------------------------#
# EventBridge Rule for Starting CodePipeline
# ------------------------------------------------------------#
SampleProjectRepPipelineEventsRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub SampleProject-StartPipelineRule-${YourID}
EventBusName: !Sub "arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/default"
EventPattern:
source:
- aws.codecommit
resources:
- !GetAtt SampleProjectRep.Arn
detail-type:
- "CodeCommit Repository State Change"
detail:
event:
- referenceCreated
- referenceUpdated
referenceName:
- master
State: ENABLED
Targets:
- Arn:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codepipeline:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- ":"
- Ref: Pipeline
Id: Target0
RoleArn: !GetAtt PipelineEventsRole.Arn
DependsOn:
- PipelineEventsRole
- Pipeline
# ------------------------------------------------------------#
# CodeBuild Project Role (IAM)
# ------------------------------------------------------------#
BuildProjectRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub BldPrjRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodeBuild Project Role Policy (IAM)
# ------------------------------------------------------------#
BuildProjectRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub BldPrjRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/
- Ref: BuildProject
- :*
- Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":logs:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :log-group:/aws/codebuild/
- Ref: BuildProject
- Action:
- codebuild:BatchPutCodeCoverages
- codebuild:BatchPutTestCases
- codebuild:CreateReport
- codebuild:CreateReportGroup
- codebuild:UpdateReport
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codebuild:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- :report-group/
- Ref: BuildProject
- -*
- Action: s3:PutObject
Effect: Allow
Resource:
Fn::Join:
- ""
- - !GetAtt PipelinePackageBucket.Arn
- /*
- Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Effect: Allow
Resource:
- !GetAtt PipelineArtifactBucket.Arn
- Fn::Join:
- ""
- - !GetAtt PipelineArtifactBucket.Arn
- /*
Version: "2012-10-17"
Roles:
- Ref: BuildProjectRole
DependsOn:
- BuildProjectRole
- PipelineArtifactBucket
- PipelinePackageBucket
# ------------------------------------------------------------#
# CodeBuild Project
# ------------------------------------------------------------#
BuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub SampleProjectBuild-${YourID}
Artifacts:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
EnvironmentVariables:
- Name: S3_BUCKET
Type: PLAINTEXT
Value:
Ref: PipelinePackageBucket
Image: "aws/codebuild/standard:7.0"
ImagePullCredentialsType: CODEBUILD
PrivilegedMode: false
Type: LINUX_CONTAINER
ServiceRole: !GetAtt BuildProjectRole.Arn
Source:
Type: CODEPIPELINE
Cache:
Type: NO_CACHE
Tags:
- Key: Cost
Value: !Ref YourID
DependsOn:
- BuildProjectRole
# ------------------------------------------------------------#
# CodePipeline Build Package Bucket (S3)
# ------------------------------------------------------------#
PipelinePackageBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub codepipeline-package-${YourID}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Key: Cost
Value: !Ref YourID
# ------------------------------------------------------------#
# CodePipeline Artifact Bucket (S3)
# ------------------------------------------------------------#
PipelineArtifactBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub codepipeline-artifact-${YourID}
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Key: Cost
Value: !Ref YourID
# ------------------------------------------------------------#
# CodePipeline Role (IAM)
# ------------------------------------------------------------#
PipelineRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: codepipeline.amazonaws.com
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Role Policy (IAM)
# ------------------------------------------------------------#
PipelineRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Effect: Allow
Resource:
- !GetAtt PipelineArtifactBucket.Arn
- Fn::Join:
- ""
- - !GetAtt PipelineArtifactBucket.Arn
- /*
- Action: sts:AssumeRole
Effect: Allow
Resource:
- !GetAtt PipelineBuildCodeBuildActionRole.Arn
- !GetAtt PipelineDeployCreateChangeSetActionRole.Arn
- !GetAtt PipelineDeployExecuteChangeSetActionRole.Arn
- !GetAtt PipelineSourceCodeCommitActionRole.Arn
Version: "2012-10-17"
Roles:
- Ref: PipelineRole
DependsOn:
- PipelineRole
- PipelineArtifactBucket
- PipelineBuildCodeBuildActionRole
- PipelineDeployCreateChangeSetActionRole
- PipelineDeployExecuteChangeSetActionRole
- PipelineSourceCodeCommitActionRole
# ------------------------------------------------------------#
# CodePipeline
# ------------------------------------------------------------#
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub SampleProjectPipeline-${YourID}
RoleArn: !GetAtt PipelineRole.Arn
Stages:
- Actions:
- ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: "1"
Configuration:
RepositoryName: !GetAtt SampleProjectRep.Name
BranchName: master
PollForSourceChanges: false
Name: CodeCommit
OutputArtifacts:
- Name: Artifact_Source_CodeCommit
RoleArn: !GetAtt PipelineSourceCodeCommitActionRole.Arn
RunOrder: 1
Name: Source
- Actions:
- ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: "1"
Configuration:
ProjectName:
Ref: BuildProject
InputArtifacts:
- Name: Artifact_Source_CodeCommit
Name: CodeBuild
OutputArtifacts:
- Name: Artifact_Build_CodeBuild
RoleArn: !GetAtt PipelineBuildCodeBuildActionRole.Arn
RunOrder: 1
Name: Build
- Actions:
- ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: "1"
Configuration:
StackName: !Sub SampleProject-Stack-${YourID}
Capabilities: CAPABILITY_NAMED_IAM
RoleArn: !GetAtt PipelineDeployCreateChangeSetRole.Arn
ActionMode: CHANGE_SET_REPLACE
ChangeSetName: !Sub SampleProject-Deploy-${YourID}
TemplatePath: Artifact_Build_CodeBuild::packaged.yaml
ParameterOverrides: !Sub '{"YourID": "${YourID}"}'
InputArtifacts:
- Name: Artifact_Build_CodeBuild
Name: CreateChangeSet
RoleArn: !GetAtt PipelineDeployCreateChangeSetActionRole.Arn
RunOrder: 1
- ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CloudFormation
Version: "1"
Configuration:
StackName: !Sub SampleProject-Stack-${YourID}
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: !Sub SampleProject-Deploy-${YourID}
Name: ExecuteChangeSet
RoleArn: !GetAtt PipelineDeployExecuteChangeSetActionRole.Arn
RunOrder: 2
Name: Deploy
ArtifactStore:
Location:
Ref: PipelineArtifactBucket
Type: S3
Tags:
- Key: Cost
Value: !Ref YourID
DependsOn:
- SampleProjectRep
- PipelineRoleDefaultPolicy
- PipelineRole
- PipelineSourceCodeCommitActionRole
- PipelineBuildCodeBuildActionRole
- PipelineDeployCreateChangeSetActionRole
- PipelineDeployExecuteChangeSetActionRole
- PipelineArtifactBucket
# ------------------------------------------------------------#
# CodePipeline Source Code Commit Action Role (IAM)
# ------------------------------------------------------------#
PipelineSourceCodeCommitActionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlSrcCcActionRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Source CodeCommit Action Role Policy (IAM)
# ------------------------------------------------------------#
PipelineSourceCodeCommitActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlSrcCcActionRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action:
- s3:Abort*
- s3:DeleteObject*
- s3:GetBucket*
- s3:GetObject*
- s3:List*
- s3:PutObject
- s3:PutObjectLegalHold
- s3:PutObjectRetention
- s3:PutObjectTagging
- s3:PutObjectVersionTagging
Effect: Allow
Resource:
- !GetAtt PipelineArtifactBucket.Arn
- Fn::Join:
- ""
- - !GetAtt PipelineArtifactBucket.Arn
- /*
- Action:
- codecommit:CancelUploadArchive
- codecommit:GetBranch
- codecommit:GetCommit
- codecommit:GetUploadArchiveStatus
- codecommit:UploadArchive
Effect: Allow
Resource: !GetAtt SampleProjectRep.Arn
Version: "2012-10-17"
Roles:
- Ref: PipelineSourceCodeCommitActionRole
DependsOn:
- PipelineArtifactBucket
- SampleProjectRep
- PipelineSourceCodeCommitActionRole
# ------------------------------------------------------------#
# CodePipeline Events Role (IAM)
# ------------------------------------------------------------#
PipelineEventsRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlEventsRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: events.amazonaws.com
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Events Role Policy (IAM)
# ------------------------------------------------------------#
PipelineEventsRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlEventsRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action: codepipeline:StartPipelineExecution
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":codepipeline:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- ":"
- Ref: Pipeline
Version: "2012-10-17"
Roles:
- Ref: PipelineEventsRole
DependsOn:
- PipelineEventsRole
# ------------------------------------------------------------#
# CodePipeline Build CodeBuild Action Role (IAM)
# ------------------------------------------------------------#
PipelineBuildCodeBuildActionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlBldCbActionRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Build CodeBuild Action Role Policy (IAM)
# ------------------------------------------------------------#
PipelineBuildCodeBuildActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlBldCbActionRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
- codebuild:StopBuild
Effect: Allow
Resource: !GetAtt BuildProject.Arn
Version: "2012-10-17"
Roles:
- Ref: PipelineBuildCodeBuildActionRole
DependsOn:
- BuildProject
- PipelineBuildCodeBuildActionRole
# ------------------------------------------------------------#
# CodePipeline Deploy Create ChangeSet Action Role (IAM)
# ------------------------------------------------------------#
PipelineDeployCreateChangeSetActionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlDepCrChsetActionRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Deploy Create ChangeSet Action Role Policy (IAM)
# ------------------------------------------------------------#
PipelineDeployCreateChangeSetActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlDepCrChsetActionRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action: iam:PassRole
Effect: Allow
Resource: !GetAtt PipelineDeployCreateChangeSetRole.Arn
- Action:
- s3:GetBucket*
- s3:GetObject*
- s3:List*
Effect: Allow
Resource:
- !GetAtt PipelineArtifactBucket.Arn
- Fn::Join:
- ""
- - !GetAtt PipelineArtifactBucket.Arn
- /*
- Action:
- cloudformation:CreateChangeSet
- cloudformation:DeleteChangeSet
- cloudformation:DescribeChangeSet
- cloudformation:DescribeStacks
Condition:
StringEqualsIfExists:
cloudformation:ChangeSetName: !Sub SampleProject-Deploy-${YourID}
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":cloudformation:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- !Sub :stack/SampleProject-Stack-${YourID}/*
Version: "2012-10-17"
Roles:
- Ref: PipelineDeployCreateChangeSetActionRole
DependsOn:
- PipelineDeployCreateChangeSetRole
- PipelineArtifactBucket
- PipelineDeployCreateChangeSetActionRole
# ------------------------------------------------------------#
# CodePipeline Deploy Create ChangeSet Role (IAM)
# ------------------------------------------------------------#
PipelineDeployCreateChangeSetRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlDepCrChsetRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Deploy Create ChangeSet Role Policy (IAM)
# ------------------------------------------------------------#
PipelineDeployCreateChangeSetRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlDepCrChsetRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action:
- s3:GetBucket*
- s3:GetObject*
- s3:List*
Effect: Allow
Resource:
- !GetAtt PipelineArtifactBucket.Arn
- Fn::Join:
- ""
- - !GetAtt PipelineArtifactBucket.Arn
- /*
- Action: "*"
Effect: Allow
Resource: "*"
Version: "2012-10-17"
Roles:
- Ref: PipelineDeployCreateChangeSetRole
DependsOn:
- PipelineArtifactBucket
- PipelineDeployCreateChangeSetRole
# ------------------------------------------------------------#
# CodePipeline Deploy Execute ChangeSet Action Role (IAM)
# ------------------------------------------------------------#
PipelineDeployExecuteChangeSetActionRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub PlDepExecChsetActionRole-${YourID}
AssumeRolePolicyDocument:
Statement:
- Action: sts:AssumeRole
Effect: Allow
Principal:
AWS:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":iam::"
- Ref: AWS::AccountId
- :root
Version: "2012-10-17"
# ------------------------------------------------------------#
# CodePipeline Deploy Execute ChangeSet Action Role Policy (IAM)
# ------------------------------------------------------------#
PipelineDeployExecuteChangeSetActionRoleDefaultPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub PlDepExecChsetActionRolePolicy-${YourID}
PolicyDocument:
Statement:
- Action:
- cloudformation:DescribeChangeSet
- cloudformation:DescribeStacks
- cloudformation:ExecuteChangeSet
Condition:
StringEqualsIfExists:
cloudformation:ChangeSetName: !Sub SampleProject-Deploy-${YourID}
Effect: Allow
Resource:
Fn::Join:
- ""
- - "arn:"
- Ref: AWS::Partition
- ":cloudformation:"
- Ref: AWS::Region
- ":"
- Ref: AWS::AccountId
- !Sub :stack/SampleProject-Stack-${YourID}/*
Version: "2012-10-17"
Roles:
- Ref: PipelineDeployExecuteChangeSetActionRole
DependsOn:
- PipelineDeployExecuteChangeSetActionRole
CI/CD パイプライン使用方法
AWS Cloud9 準備
今回は、API Gateway と Lambda 関数をコードで管理します。コードは AWS CodeCommit で管理し、コードの編集は AWS Cloud9 を使用します。あらかじめ CodeCommit の該当するリポジトリ と Cloud9 を連携する必要があります。ここでは、この準備の説明は割愛します。以下の AWS 公式ドキュメントを参考に準備頂けると幸いです。
コードの準備
API Gateway と Lambda 関数をデプロイするために、以下 3 種類のコードファイルを準備します。ファイル名はこの例のまま使用頂いた方が良いです。(CI/CD パイプライン内で指定している都合でw)
- lambda_function.py
- buildspec.yml
- template.yml
以下、それぞれについて解説します。
lambda_function.py
Lambda 関数の実体です。ここでは、サンプルなので現在時刻を返すだけの Python コードになっています。
from datetime import datetime
def lambda_handler(event, context):
# Get the current date and time
now = datetime.now()
# Format the date and time in a readable format (e.g., YYYY-MM-DD HH:MM:SS)
current_time = now.strftime("%Y-%m-%d %H:%M:%S")
# Return the current date and time
return {
"statusCode": 200,
"body": current_time
}
buildspec.yml
ビルドステージで何をするか、を定義したファイルです。
実際のところ、Lambda 関数コードは上述の lambda_function.py をそのまま使用するのでコンパイルすることはありません。API Gateway や Lambda 関数リソースをこの CI/CD パイプラインでデプロイするため、sam build や sam package というコマンドを使用して AWS SAM テンプレートを AWS 側で処理しやすいフォーマットに?若干変更するようです。(変更後ファイルは packaged.yaml)
version: 0.2
phases:
install:
runtime-versions:
python: 3.11
commands:
pre_build:
commands:
- sam build
build:
commands:
- sam package --s3-bucket $S3_BUCKET --output-template-file packaged.yaml
artifacts:
files:
- packaged.yaml
template.yml
AWS SAM テンプレートファイルです。この中で、デプロイしたい API Gateway と Lambda 関数のリソースを定義しています。
AWS CloudFormation と比べるとかなり少ない行数です。標準的な設定を使用して動くリソースをデプロイしてくれます。
AWSTemplateFormatVersion: 2010-09-09
Description: >-
SampleProject
Transform:
- AWS::Serverless-2016-10-31
Parameters:
YourID:
Type: String
Default: dummy
Resources:
SampleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: lambda_function.lambda_handler
Runtime: python3.11
Policies:
- DynamoDBReadPolicy:
TableName: YourTableName
Environment:
Variables:
YourID: !Ref YourID
Events:
Api:
Type: Api
Properties:
Path: /test
Method: POST
Outputs:
ApiEndpoint:
Description: "APIG Endpoint"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
SAM (Serverless Application Model) は AWS CloudFormation よりも簡易にリソースを定義できる分、カスタマイズ性に欠けるので要件によって CloudFormation との使い分けを考える必要があります。
ここでは、全く使用しないのですが Lambda 関数に YourTableName という Amazon DynamoDB テーブルの Read Only 権限を与えています。このように AWS があらかじめ用意した権限パターンセットを使うと簡単な権限定義ができます。
最終的に、前述した通り SAM テンプレートはビルドステージで内部的に CloudFormation テンプレートに変換され、デプロイに使用されます。
実際にデプロイしてみる
CodeCommit と連携した状態の Cloud9 で、以下のようにプロジェクトのルートディレクトリに 3 つのコードを配置します。
配置後、CodeCommit にコードをプッシュします。(以下、コマンド例)
git commit -A
git commit -m "initial commit"
git push origin master
プッシュすると、自動的に CI/CD パイプライン (AWS CodePipeline) が動き出します。
Deploy ステージまで完了。
全てのステージが完了すると、API Gateway と Lambda 関数が連携された状態でデプロイされています。
Lambda 関数の IAM ロールも、デフォルトのポリシー + DynamoDB Read only 系の権限が自動的に作成されてますね。
AWS CloudFormation のコンソールを見ると、CI/CD パイプラインから実行された CloudFormation スタックがあることが確認できます。
説明は省略しますが、API Gateway や Lambda 関数を更新するときは Cloud9 のコードを更新して上記手順を繰り返します。
注意点ですが、一連の環境を削除するときには先にこの CI/CD パイプラインから呼び出された CloudFormation スタックを削除する必要があります。その後、CI/CD パイプラインをデプロイしたときのスタック削除になります。
まとめ
いかがでしたでしょうか?
API Gateway と Lambda 関数をコードでバージョン管理するときにはこのような方法を採るのが今時点のソリューションかと思います。あくまでも簡易な一例ですので、ディテールは書き換えて下さい。
本記事が皆様のお役に立てれば幸いです。