4
0

More than 3 years have passed since last update.

CloudFormationテンプレートを1からしっかり理解しながらECS on Fargateなアプリを自動構築する(後編)

Last updated at Posted at 2020-03-29

前提条件

前編で作った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 って何設定すりゃいいのよ?という感じだが、マネコンから作成したビルドプロジェクトの環境イメージ(↓これ)からコピペすれば良さそう。

キャプチャ5.PNG

あと、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の設定からパイプライン作成までを「ほぼ」自動化できた!やったー!

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0