この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
目標
CodeCommitにホストされたserverless frameworkのコードをCodePipelineでデプロイするためのCloudFormationを作成します。
serverless frameworkのデプロイコマンドにはstage
オプションがあり、ステージ(環境)ごとにデプロイされるようになっています。それにあわせてCodePipelineもステージ別に作成するように実装してみます。今回はdev
とprd
という2環境むけに作成します。
環境
今回は下記の環境で確認しています。
- serverless framework: 1.67.0
- Codepipeline runtime: Node.js 12.x
serverless framework側 ソースコードの変更
CloudFormationテンプレート作成の前にまずserverless framework側(CodeCommitでホストするソースコード側)で必要な変更を行います。
serverless.yml
serverless.yml
の内容です。service
とregion
は後述するCloudFormationと同じものにします。
service: serverless-deploy-example
provider:
name: aws
runtime: nodejs12.x
region: ap-northeast-1
stage: ${opt:stage, self:custom.defaultStage}
custom:
defaultStage: dev
functions:
hello:
handler: handler.hello
package.json
ここには、デプロイ時に実行するnpm script
コマンドを記述します。ここに環境別向けのデプロイコマンドを記述します。
{
"name": "serverless-deploy-example",
"version": "1.0.0",
"dependencies": {
"serverless": "^1.67.0"
},
"devDependencies": {},
"scripts": {
"deploy:dev": "sls deploy --stage dev",
"deploy:prd": "sls deploy --stage prd"
}
}
buildspec.yml
CodeBuildで使用するbuildspec.yml
を作成します。${DEPLOY_ENV}
には後述するCloudFormationテンプレートでCodeBuildの環境変数を埋め込むようにします。
version: 0.2
phases:
install:
runtime-versions:
nodejs: 12
commands:
- npm install
build:
commands:
- npm run deploy:${DEPLOY_ENV}
CloudFormationテンプレート
次にCloudFormationテンプレートを作成します。
基本となるCloudFormationテンプレートは先日書いたフロントエンド環境をS3にデプロイするCodePipelineをCloudFormationで作成するのものと同じです。
Parameters.Env
でスタック作成時にdev
かprd
を選択するようにします。
AWSTemplateFormatVersion: 2010-09-09
Description: serverless framework deploy pipeline example
Parameters:
ServiceName:
Description: serverless framework deploy pipeline example
Type: String
Default: serverless-deploy-example
Env:
Type: String
Default: dev
AllowedValues:
- dev
- prd
Resources:
# ビルド成果物を格納するS3バケット
ArtifactsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${ServiceName}-artifacts-${Env}
LifecycleConfiguration:
Rules:
- Id: DeleteRule
Status: Enabled
ExpirationInDays: 7
# CodeBuild
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${ServiceName}-${Env}
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:3.0
PrivilegedMode: true
Type: LINUX_CONTAINER
EnvironmentVariables:
- Name: DEPLOY_ENV
Value: !Sub ${Env}
ServiceRole: !GetAtt CodeBuildServiceRole.Arn
# CodeBuildのIAMロール
CodeBuildServiceRole:
Type: AWS::IAM::Role
Properties:
RoleName:
!Sub ${ServiceName}-CodeBuildServiceRole-${Env}
Policies:
- PolicyName: !Sub ${ServiceName}-CodeBuild-ServiceRolePolicy-${Env}
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
- logs:DeleteLogGroup
- logs:DescribeLogGroups
Resource:
- !Sub arn:aws:logs:ap-northeast-1:${AWS::AccountId}:log-group:/aws/codebuild/${ServiceName}-${Env}:*
- !Sub arn:aws:logs:ap-northeast-1:${AWS::AccountId}:log-group:/aws/lambda/*
- !Sub arn:aws:logs:ap-northeast-1:${AWS::AccountId}:log-group::log-stream:*
Effect: Allow
- Action:
- codebuild:CreateReportGroup
- codebuild:CreateReport
- codebuild:UpdateReport
- codebuild:BatchPutTestCases
Resource:
- !Sub arn:aws:codebuild:ap-northeast-1:${AWS::AccountId}:project/${ServiceName}-${Env}
Effect: Allow
- Action:
- s3:CreateBucket
- s3:DeleteBucket
- s3:PutBucket
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketAcl
- s3:GetBucketLocation
- s3:PutObject
- s3:ListBucket
- s3:SetBucketEncryption
- s3:GetEncryptionConfiguration
- s3:PutEncryptionConfiguration
- s3:PutBucketPolicy
Resource:
- '*'
Effect: Allow
- Action:
- cloudformation:DescribeStackEvents
- cloudformation:DescribeStackResources
- cloudformation:DescribeStackResource
- cloudformation:DescribeStacks
- cloudformation:ValidateTemplate
- cloudformation:CreateStack
- cloudformation:UpdateStack
- cloudformation:DeleteStack
- cloudformation:ListStackResources
Resource:
- '*'
Effect: Allow
- Action:
- iam:CreateRole
- iam:DeleteRole
- iam:DeleteRolePolicy
- iam:PutRolePolicy
- iam:GetRole
- iam:PassRole
Resource:
- '*'
Effect: Allow
- Action:
- lambda:UpdateFunctionCode
- lambda:GetFunction
- lambda:GetFunctionConfiguration
- lambda:CreateFunction
- lambda:DeleteFunction
- lambda:ListVersionsByFunction
- lambda:PublishVersion
Resource:
- !Sub arn:aws:lambda:ap-northeast-1:${AWS::AccountId}:function:${ServiceName}-${Env}*
Effect: Allow
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: ''
Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
# CodePipeline
CodePipelineProject:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${ServiceName}-${Env}
RoleArn: !GetAtt CodePipelineServiceRole.Arn
Stages:
- Name: Source
Actions:
- Name: SourceAction
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
OutputArtifacts:
- Name: SourceArtifact
# デプロイもとのCodeCommitのリポジトリとブランチ
Configuration:
RepositoryName: serverless-example-repository
BranchName: master
# push時に自動でデプロイされないようにする
PollForSourceChanges: false
RunOrder: 1
- Name: Build
Actions:
- Name: BuildAction
InputArtifacts:
- Name: SourceArtifact
OutputArtifacts:
- Name: BuildArtifact
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName:
!Ref CodeBuildProject
RunOrder: 2
ArtifactStore:
Type: S3
Location:
!Ref ArtifactsBucket
# CodePipelineのIAMロール
CodePipelineServiceRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub ${ServiceName}-CodePipelineServiceRole-${Env}
Policies:
- PolicyName: !Sub ${ServiceName}-CodePipelineServiceRolePolicy-${Env}
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- s3:GetObject
- s3:GetObjectVersion
- s3:GetBucketVersioning
- s3:PutObject
Resource:
- arn:aws:s3:::codepipeline*
Effect: Allow
- Action:
- codecommit:CancelUploadArchive
- codecommit:GetBranch
- codecommit:GetCommit
- codecommit:GetUploadArchiveStatus
- codecommit:UploadArchive
Resource:
- '*'
Effect: Allow
- Action:
- codebuild:BatchGetBuilds
- codebuild:StartBuild
Resource:
- '*'
Effect: Allow
- Action:
- codedeploy:CreateDeployment
- codedeploy:GetApplication
- codedeploy:GetApplicationRevision
- codedeploy:GetDeployment
- codedeploy:GetDeploymentConfig
- codedeploy:RegisterApplicationRevision
Resource:
- '*'
Effect: Allow
- Action:
- codestar-connections:UseConnection
Resource:
- '*'
Effect: Allow
- Action:
- s3:*
Resource:
- '*'
Effect: Allow
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
-
Effect: Allow
Principal:
Service:
- codepipeline.amazonaws.com
Action:
- sts:AssumeRole
スタックを作成する
先程のEnvを指定してそれぞれdev
とprd
のスタックを作成します。
デプロイする
スタック作成後に作成されたCodePipelineからデプロイできるかどうか確認します。
dev
とprd
でそれぞれのパイプラインが作成されているので選択して「変更をリリースする」を選択します。
デプロイが成功すればserverless frameworkが作成したスタックを確認することができます。
Lambda関数もdev
とprd
でそれぞれ別に出来上がっています。
おわりに
今回のCloudFormationテンプレートだとデプロイが全てmaster
ブランチからとなっていますが、環境ごとにデプロイもととなるブランチを変えたいといった場合などにはデプロイもとのブランチ名もEnv
などを含めたものにあわせて変更するなど、もうひと工夫必要になります。