前提条件
前編で作ったALBとECS、中編で作ったデプロイの設定をもとにCodePipelineを使ってCI/CDパイプラインを作るので、それぞれ理解しておく。
前回から引き続き、記事中には、備忘のためにリファレンスに書かれていないデフォルト値を整理しておくが、2020年3月時点の情報であり、後でAWSが仕様を変えたとしても追従する予定はないので、挙動が違ったらリファレンスを見直してほしい。あと、今回の構成(ECS on FargateのBlue/Greenデプロイメント)以外の構成以外のデフォルト値まで調査はしていないのであしからず。
CI/CDパイプラインを作成する
IAMロールの作成
パイプライン中で作成しても良いのだけど、ロールが増えすぎてもなので、以下のような信頼関係のポリシで、CodePipeline, CodeCommit, CodeBuild, S3 あたりのもろもろにアクセス可能なポリシをアタッチしたIAMロールを作っておく(実際は、S3なんかはアクセス可能なバケットを絞るとかはあるのだろうけど)。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "codepipeline.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
パラメータの設定
カスタマイズ箇所を極力減らすために、プロジェクト名をParameterに指定すれば書き換える箇所が減るといった考えにしておく。S3とそれ以外で別パラメータにしているのは、S3のバケット名に大文字が使えないから。パラメータグループをメタ設定に入れた方がキレイだけど、細かいことは一旦気にしない。
ApplicationName と DeploymentGroupName は、本当ならCloudFormation中でデプロイまで定義できれば !Ref できるので不要なパラメータなのだけど、ECSのBlue/Greenデプロイメントが未対応で、前回小細工をしているために入れておく(リソース定義に直接書き込んでしまっても良いけど)。
Parameters:
Prefix:
Description: "Project name prefix"
Type: "String"
Default: "CFn-test"
PrefixS3:
Description: "Project name prefix for S3 Bucket"
Type: "String"
Default: "cfn-test"
ApplicationName:
Description: "ApplicationName on CodeDeploy"
Type: "String"
Default: "CFn-test-Application"
DeploymentGroupName:
Description: "DeploymentGroupName on CodeDeploy"
Type: "String"
Default: "CFn-test-DeploymentGroup"
S3バケットの作成
CI/CDパイプライン中でアーティファクトを格納するためのS3バケットが必要なので作る。
例によって、どのプロパティも「必須:いいえ」ではあるが、何も指定しないとエラーになるので、何かしらは必須になるようだ。
最低限は、以下のような感じでバケット名があれば良い。
Resources:
S3BUCKET:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub ${PrefixS3}-artifact-bucket
S3は他にもプロパティたくさんある。
↓にあるように、PublicAccessBlockConfiguration がデフォルトでオフになるのは危ないんじゃない?と思いつつ、今回はテストなので一旦無視。ちゃんと実運用するときは考えよう。
| プロパティ | デフォルト値 |
|---|---|
| AccelerateConfiguration | 停止 |
| AccessControl | よく分からない… |
| AnalyticsConfigurations | なし |
| BucketEncryption | 無効 |
| BucketName | AWS払い出しの名前 |
| CorsConfiguration | なし? |
| InventoryConfigurations | 無効 |
| LifecycleConfiguration | ルールなし |
| LoggingConfiguration | 無効 |
| MetricsConfigurations | なし |
| NotificationConfiguration | 通知なし |
| ObjectLockConfiguration | すべてのオブジェクトに適用 ※リファレンス記載 |
| ObjectLockEnabled | 無効 |
| PublicAccessBlockConfiguration | オフ |
| ReplicationConfiguration | ルールなし |
| Tags | aws:cloudformation:stack-id/aws:cloudformation:stack-name/aws:cloudformation:logical-id |
| VersioningConfiguration | 無効 |
| WebsiteConfiguration | 無効 |
CodeBuildのプロジェクト作成
CodeBuildもプロパティが大量にあるので設定が大変…。
CODEBUILD:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub ${Prefix}-build-project
Source:
Type: CODEPIPELINE
BuildSpec: buildspec_container.yml
Artifacts:
Type: CODEPIPELINE
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:3.0-19.11.26
PrivilegedMode: true
Cache:
Type: LOCAL
Modes:
- LOCAL_CUSTOM_CACHE
ServiceRole: !Sub arn:aws:iam::${AWS::AccountId}:role/service-role/[CodeBuildの適切なロール]
| プロパティ | デフォルト値 |
|---|---|
| Artifacts | 必須 ※↓のアーティファクトで詳述 |
| BadgeEnabled | Sourceのプロパティが Type: CODEPIPELINE の場合は指定してはいけない |
| Cache | キャッシュを使用しない |
| Description | なし |
| EncryptionKey | なし |
| Environment | 必須 ※↓の環境で詳述 |
| LogsConfig | なし |
| Name | AWS払い出しの名前 |
| QueuedTimeoutInMinutes | 480分 |
| SecondaryArtifacts | なし |
| SecondarySources | なし |
| SecondarySourceVersions | なし |
| ServiceRole | 必須 |
| Source | 必須 ※↓のソースで詳述 |
| SourceVersion | 最新のバージョン ※リファレンス記載 |
| Tags | なし |
| TimeoutInMinutes | 60分(リファレンス記載) |
| Triggers | よく分からない |
| VpcConfig | なし |
アーティファクトのプロパティについては以下。
今回は、ビルド生成物はECSに入れるものの、taskdef.json があるので、その格納先が必要。
ただし、Type: CODEPIPELINE の場合は、自動でいろいろやってくれるので、細かいことは考えなくてOK。
| プロパティ | デフォルト値 |
|---|---|
| ArtifactIdentifier | デフォルトのKMSのキー |
| EncryptionDisabled |
Type: CODEPIPELINE の場合は無視 |
| Location |
Type: CODEPIPELINE の場合は無視 |
| Name |
Type: CODEPIPELINE の場合は無視 |
| NamespaceType |
Type: CODEPIPELINE の場合は無視 |
| OverrideArtifactName | false |
| Packaging |
Type: CODEPIPELINE の場合は無視 |
| Path |
Type: CODEPIPELINE の場合は無視 |
| Type | 必須 |
ソースのプロパティについては以下。
これも、アーティファクト同様、Type: CODEPIPELINE の場合は、自動でいろいろやってくれるので、細かいことは考えなくてOK。
| プロパティ | デフォルト値 |
|---|---|
| Auth | よく分からない |
| BuildSpec | buildspec.yml |
| GitCloneDepth |
Type: CODEPIPELINE の場合は無視 |
| GitSubmodulesConfig |
Type: CODEPIPELINE の場合は無視 |
| InsecureSsl |
Type: CODEPIPELINE の場合は無視 |
| Location |
Type: CODEPIPELINE の場合は無視 |
| ReportBuildStatus |
Type: CODEPIPELINE の場合は設定してはいけない |
| SourceIdentifier | なし? |
| Type | 必須 |
環境のプロパティについては以下。
Image って何設定すりゃいいのよ?という感じだが、マネコンから作成したビルドプロジェクトの環境イメージ(↓これ)からコピペすれば良さそう。
あと、PrivilegedModeは日本語マネジメントコンソールの「特権付与」のチェックボックスに該当するもので、忘れるとDockerのビルドができないので注意。
| プロパティ | デフォルト値 |
|---|---|
| Certificate | なし |
| ComputeType | 必須 |
| EnvironmentVariables | なし |
| Image | 必須 |
| ImagePullCredentialsType | よく分からない |
| PrivilegedMode | なし |
| RegistryCredential | なし |
| Type | 必須 |
CodePipelineのパイプライン作成
CodePipelineはプロパティのサブ要素が複雑。
今回、デフォルト値はサブプロパティまで書いていく(必要な部分のみ)。
RoleArnについては↑に書いた通り、あらかじめ作成しておいたものを使用する。
| プロパティ | デフォルト値 |
|---|---|
| ArtifactStore/ArtifactStores | どちらか必須。指定なしの方は無効 |
| DisableInboundStageTransitions | なし |
| Name | AWS払い出しの名前 |
| RestartExecutionOnUpdate | |
| RoleArn | 必須 |
| Stages | 必須(↓のStageDeclaration) |
ArtifactStore のプロパティについては以下。
| プロパティ | デフォルト値 |
|---|---|
| EncryptionKey | よく分からない |
| Location | 必須 |
| Type | 必須 |
StageDeclaration のプロパティについては以下。
| プロパティ | デフォルト値 |
|---|---|
| Actions | 必須(↓のActionDeclaration) |
| Blockers | よく分からない |
| Name | 必須 |
ActionDeclaration のプロパティについては以下。
| プロパティ | デフォルト値 |
|---|---|
| ActionTypeId | 必須 |
| Configuration | 必須でないと書いてありながら、たぶん↓のConfigurationの設定をしないと動かない気がする |
| InputArtifacts | なし |
| Name | 必須 |
| OutputArtifacts | なし |
| Region | よく分からない |
| RoleArn | よく分からない。ユーザーガイドには「宣言されたアクションを実行する IAM サービスロールの ARN。これは、パイプラインの roleArn を介することが想定されています。」とあるのでパイプラインと同じARNを入れたらエラーになった。 |
| RunOrder | 必須 |
ActionTypeId のプロパティについては以下。
階層が深い……
ちなみに、日本語のドキュメントだとCategoryに指定可能な値が訳されてしまっていて設定可能な値が分からないという罠がある。英語に切り替えよう。
| プロパティ | デフォルト値 |
|---|---|
| Category | 必須 |
| Owner | 必須 |
| Provider | 必須 |
| Version | 必須 |
そして、Configuration の設定内容が超曲者で、頑張ってユーザーガイドを掘り下げていってここに辿り着かないと何を設定したら良いか分からないという……。
ActionTypeId の値によってパラメータが違うので、今回はCodeCommit、CodeBuild、CodeDeployToECS(CodeDeployと書きたいところだが、ECSのBlue/GreenデプロイメントはプロバイダをCodeDeployToECSに指定する) それぞれについて書いておく。
CodeCommit については以下。
| プロパティ | デフォルト値 |
|---|---|
| RepositoryName | 必須 |
| BranchName | 必須 |
| PollForSourceChanges | よく分からない |
CodeBuild については以下。
PrimarySource は、Type: CODEPIPELINE の場合は不要っぽい?
マネジメントコンソールの場合は、そもそもCodePipelineをソースに選択できないので、勝手がよく分からない。
| プロパティ | デフォルト値 |
|---|---|
| ProjectName | 必須 |
| PrimarySource | なし |
| EnvironmentVariables | なし |
CodeDeployToECS については以下。
| プロパティ | デフォルト値 |
|---|---|
| ApplicationName | 必須 |
| DeploymentGroupName | 必須 |
| TaskDefinitionTemplateArtifact | 必須 |
| AppSpecTemplateArtifact | 必須 |
| AppSpecTemplatePath | 必須 |
| TaskDefinitionTemplatePath | taskdef.json |
| Image1~4ArtifactName | なし |
| Image1~4ContainerName | なし |
さて、ここまでをまとめると、パイプライン制御のリソース定義は↓こうなる。RoleArnはあらかじめ作っておいたロールのARNを指定する。
appspec_container.yml は、Appspecファイルに合わせる。今回、自分が作った環境ではコンテナ用とそうでないもので定義を分けたために標準的な名前から外しているため、別名を指定した。
PIPELINE:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub ${Prefix}-pipeline
ArtifactStore:
Location: !Ref S3BUCKET
Type: S3
RoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/CodePipelineRole
Stages:
- Name: Source
Actions:
- RunOrder: 1
Name: Source
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: 1
Configuration:
RepositoryName: testProject
BranchName: master
OutputArtifacts:
- Name: SourceArtifact
- Name: Build
Actions:
- RunOrder: 2
Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
Configuration:
ProjectName: !Ref CODEBUILD
InputArtifacts:
- Name: SourceArtifact
OutputArtifacts:
- Name: BuildArtifact
- Name: Deploy
Actions:
- RunOrder: 3
Name: Deploy
ActionTypeId:
Category: Deploy
Owner: AWS
Provider: CodeDeployToECS
Version: 1
Configuration:
ApplicationName: !Sub ${ApplicationName}
DeploymentGroupName: !Sub ${DeploymentGroupName}
AppSpecTemplateArtifact: SourceArtifact
AppSpecTemplatePath: appspec_container.yml
TaskDefinitionTemplateArtifact: SourceArtifact
Image1ArtifactName: BuildArtifact
Image1ContainerName: IMAGE1_NAME
InputArtifacts:
- Name: SourceArtifact
- Name: BuildArtifact
中編までのCloudFormationテンプレートやCLIを実行するシェルスクリプトを流した後に、今回のテンプレートを流し込めば完璧だ!
ALBの設定からECSの設定からパイプライン作成までを「ほぼ」自動化できた!やったー!
