はじめに
CodePipelineをなんとなく使っていたのですが、いろいろな間違いに気づいたので正しい理解をメモしておきます。
AWSとGithubを連携させるやりかた
特定のブランチ(例えばdevelop)にマージすると自動的にECSサービスが更新されるようにします。
version1とversion2の2つのやり方があり、現在はVersion2が推奨されています。
【version1】 GithubのPersonal Access Tokenを使う
ググるとこの方法がよく出てきますが、今は非推奨とのことです。
後述するCodeStarSourceConnectionを使いましょう。
Not recommended: The GitHub version 1 action uses OAuth tokens to authenticate with GitHub and uses a separate webhook to detect changes. This is no longer the recommended method.
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
GitHubRepositoryName:
Type: String
Default: <inut-your-github-repo>
GitHubAccountName:
Type: String
Default: <inut-your-github-account>
GitHubPipelineWebhookName:
Type: String
Default: <inut-your-unique-webhook-name> # レポジトリ内の他のwebhookと被らないようにする
CodeBuildVpcId:
Type: String
Default: <input-your-vpc-id-for-codebuild>
CodeBuildPrivateSubnet1:
Type: String
Default: <input-your-subnet-id-for-codebuild>
CodeBuildPrivateSubnet2:
Type: String
Default: <input-your-subnet-id-for-codebuild>
CodeBuildPrivateSubnet3:
Type: String
Default: <input-your-subnet-id-for-codebuild>
CodeBuildVpcDefaultSG:
Type: String
Default: <input-your-default-security-group-for-codebuild>
EcrRepository:
Type: String
Default: <input-your-ECR-repo>
Branch:
Type: String
Default: <input-your-Github-branch-for-CodePipeline>
ClusterName:
Type: String
Default: <inout-your-ECS-cluster-name>
ServiceName:
Type: String
Default: <input-your-ECS-service-name>
ArtifactFileName:
Type: String
Default: artifact.json
CodeBuildName:
Type: String
Default: <input-your-codebuild-name> #なんでもOK
CodeBuildServiceRoleArn:
Type: String
Default: <input-your-service-role-arn>
CodePipelineRoleArn:
Type: String
Default: <input-your-service-role-arn>
S3ArficactStoreBucketName:
Type: String
Default: <input-your-s3-bucket-name>
Resources:
CodeBuild:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref CodeBuildName
ServiceRole: !Ref CodeBuildServiceRoleArn
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Type: LINUX_CONTAINER
Image: aws/codebuild/standard:5.0
PrivilegedMode: true
EnvironmentVariables:
- Name: AWS_DEFAULT_REGION
Value: !Sub ${AWS::Region}
- Name: AWS_ACCOUNT_ID
Value: !Sub ${AWS::AccountId}
- Name: REPOSITORY_URI
Value: !Sub
- ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${Repository}
- Repository: !Ref EcrRepository
- Name: CONTAINER_NAME
Value: !Ref ServiceName
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
BuildSpec: buildspec.yml
VpcConfig:
VpcId: !Ref CodeBuildVpcId
Subnets:
- !Ref CodeBuildPrivateSubnet1
- !Ref CodeBuildPrivateSubnet2
- !Ref CodeBuildPrivateSubnet3
SecurityGroupIds:
- !Ref CodeBuildVpcDefaultSG
# 今回はCodeBuildを実行するための特定のVPC/Subnet/SGを設定する。これを設定しないと他のAWSユーザと共通IPからdockerイメージをpullすることとなり、pullリミットに引っかかる。
# Private Subnetの必要があり、NatGWも必要。
# 詳細 => https://docs.aws.amazon.com/codebuild/latest/userguide/vpc-support.html
PipelineWebhook:
Type: 'AWS::CodePipeline::Webhook'
Properties:
Authentication: GITHUB_HMAC
AuthenticationConfiguration:
SecretToken: '{{resolve:secretsmanager:<your-secret-name>:SecretString:<your-secret-key>}}'
# Parametersを使って機密情報を入れるのは推奨されない。今回はSecretManagerを使う。
# 詳細 => https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-secretsmanager
Filters:
- JsonPath: '$.ref'
MatchEquals: !Sub
- refs/heads/${Branch}
- Branch: !Ref Branch
- JsonPath: '$.created'
MatchEquals: false
- JsonPath: '$.deleted'
MatchEquals: false
# 特定のBranchの変更(push)を検知してwebhookを実行。このときBranchの作成と消去は無視する。
# 詳しくは、Githubの Settings => Webhooks => Recent Deliveries => Payload を見ればわかる。
TargetPipeline: !Ref Pipeline
TargetAction: SourceAction
Name: !Ref GitHubPipelineWebhookName
TargetPipelineVersion: !GetAtt Pipeline.Version
RegisterWithThirdParty: 'true'
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
RoleArn: !Ref CodePipelineRoleArn
Name: !Ref ServiceName
ArtifactStore:
Type: S3
Location: !Ref S3ArficactStoreBucketName
# 事前にS3バケットを作っておく
Stages:
- Name: Source
Actions:
- Name: SourceAction
ActionTypeId:
Category: Source
Owner: ThirdParty
Version: 1
Provider: GitHub
Configuration:
Owner: !Ref GitHubAccountName
Repo: !Ref GitHubRepositoryName
PollForSourceChanges: false
# Webhhokを登録してGithub→AWSに変更を教えてもらうのではなく、AWS側がポーリングすることでGithubの変更をキャッチするための設定。昔はこれが主流だったらしい。今回は使わない。
# 詳細 => https://aws.amazon.com/jp/premiumsupport/knowledge-center/codepipeline-running-twice/
Branch: !Ref Branch
OAuthToken: '{{resolve:secretsmanager:<your-secret-name>:SecretString:<your-secret-key>}}'
RunOrder: 1
OutputArtifacts:
- Name: SourceCode
- Name: Build
Actions:
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref CodeBuild
RunOrder: 1
InputArtifacts:
- Name: SourceCode
OutputArtifacts:
- Name: BuildOutput
- Name: Deploy
Actions:
- Name: Deploy
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: ECS
Configuration:
ClusterName: !Ref ClusterName
ServiceName: !Ref ServiceName
FileName: !Ref ArtifactFileName
InputArtifacts:
- Name: BuildOutput
RunOrder: 1
version: 0.2
phases:
pre_build:
commands:
- IMAGE_URI="${REPOSITORY_URI}:$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | head -c 7)"
- aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
build:
commands:
- echo Build started on $(date)
- docker build --tag ${IMAGE_URI} .
- docker push ${IMAGE_URI}
post_build:
commands:
- echo Build completed on $(date)
- printf '[{"name":"%s","imageUri":"%s"}]' "${CONTAINER_NAME}" "$IMAGE_URI" > artifact.json
artifacts:
files: artifact.json
# 適当につくってください。
【version2】 CodeStarSourceConnectionを使う
今はこちらが推奨されているみたいです。
CodeStarSourceConnectionはコンソール( Developer Tools => Settings => Connnections )から作るのが早いです。
https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html#connections-create-github-console
下図から、接続先のGithubアカウントまたはレポジトリを選びます。
下記のようにymlを書き直します。Webhookの設定も不要となります。
Recommended: The GitHub version 2 action uses Github app-based auth backed by a CodeStarSourceConnection for Bitbucket, GitHub, and GitHub Enterprise Server actions resource. It installs an AWS CodeStar Connections application into your GitHub organization so that you can manage access in GitHub.
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
GitHubRepositoryName:
Type: String
Default: <inut-your-github-repo>
GitHubAccountName:
Type: String
Default: <inut-your-github-account>
CodeBuildVpcId:
Type: String
Default: <input-your-vpc-id-for-codebuild>
CodeBuildPrivateSubnet1:
Type: String
Default: <input-your-subnet-id-for-codebuild>
CodeBuildPrivateSubnet2:
Type: String
Default: <input-your-subnet-id-for-codebuild>
CodeBuildPrivateSubnet3:
Type: String
Default: <input-your-subnet-id-for-codebuild>
CodeBuildVpcDefaultSG:
Type: String
Default: <input-your-default-security-group-for-codebuild>
EcrRepository:
Type: String
Default: <input-your-ECR-repo>
Branch:
Type: String
Default: <input-your-Github-branch-for-CodePipeline>
ClusterName:
Type: String
Default: <inout-your-ECS-cluster-name>
ServiceName:
Type: String
Default: <input-your-ECS-service-name>
ArtifactFileName:
Type: String
Default: artifact.json
CodeBuildName:
Type: String
Default: <input-your-codebuild-name>
CodeBuildServiceRoleArn:
Type: String
Default: <input-your-service-role-arn>
CodePipelineRoleArn:
Type: String
Default: <input-your-service-role-arn>
S3ArficactStoreBucketName:
Type: String
Default: <input-your-s3-bucket-name>
GithubConnectionArn: # ここに作ったCodeStarSourceConnectionのARNを記入
Type: String
Default: <input-your-connection-arn>
Resources:
CodeBuild:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref CodeBuildName
ServiceRole: !Ref CodeBuildServiceRoleArn
Environment:
ComputeType: BUILD_GENERAL1_SMALL
Type: LINUX_CONTAINER
Image: aws/codebuild/standard:5.0
PrivilegedMode: true
EnvironmentVariables:
- Name: AWS_DEFAULT_REGION
Value: !Sub ${AWS::Region}
- Name: AWS_ACCOUNT_ID
Value: !Sub ${AWS::AccountId}
- Name: REPOSITORY_URI
Value: !Sub
- ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/${Repository}
- Repository: !Ref EcrRepository
- Name: CONTAINER_NAME
Value: !Ref ServiceName
Artifacts:
Type: CODEPIPELINE
Source:
Type: CODEPIPELINE
BuildSpec: buildspec.yml
VpcConfig:
VpcId: !Ref CodeBuildVpcId
Subnets:
- !Ref CodeBuildPrivateSubnet1
- !Ref CodeBuildPrivateSubnet2
- !Ref CodeBuildPrivateSubnet3
SecurityGroupIds:
- !Ref CodeBuildVpcDefaultSG
Pipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
RoleArn: !Ref CodePipelineRoleArn
# 上記RoleにConnectionへのアクセス権限を追加する必要あり。
#{
# "Version": "2012-10-17",
# "Statement": [
# {
# "Sid": "ConnectionsAccess",
# "Effect": "Allow",
# "Action": [
# "codestar-connections:UseConnection",
# "codestar-connections:GetConnection",
# "codestar-connections:ListConnections"
# ],
# "Resource": "<input-your-connection-arn>"
# }
# ]
#}
Name: !Ref ServiceName
ArtifactStore:
Type: S3
Location: !Ref S3ArficactStoreBucketName
Stages:
- Name: Source # updated
Actions:
- Name: SourceAction
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeStarSourceConnection
OutputArtifacts:
- Name: SourceCode
Configuration:
FullRepositoryId: !Sub
- ${OrganizationName}/${RepositoryName}
- OrganizationName: !Ref GitHubAccountName
RepositoryName: !Ref GitHubRepositoryName
ConnectionArn: !Ref GithubConnectionArn
BranchName: !Ref Branch
OutputArtifactFormat: CODEBUILD_CLONE_REF
RunOrder: 1
- Name: Build
Actions:
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
Configuration:
ProjectName: !Ref CodeBuild
RunOrder: 1
InputArtifacts:
- Name: SourceCode
OutputArtifacts:
- Name: BuildOutput
- Name: Deploy
Actions:
- Name: Deploy
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: ECS
Configuration:
ClusterName: !Ref ClusterName
ServiceName: !Ref ServiceName
FileName: !Ref ArtifactFileName
InputArtifacts:
- Name: BuildOutput
RunOrder: 1
↓こちらの記事を参考にさせていただきました。