CodePipeline (Github version 2接続) とCodeDeployを利用したパイプラインをCloudFromationで作成してみた

2023.07.03

データアナリティクス事業本部のueharaです。

今回は、CodePipeline (Github version 2接続) とCodeDeployを利用したパイプラインをCloudFromationで作成してみたいと思います。

はじめに

今回作成するパイプラインは以下の通り、SourceとなるGithubへのコミットをトリガーに、EC2へのデプロイを行うようなパイプラインを想定します。

前提

本記事では、デプロイ対象のEC2が既に準備されていることを前提としています。

簡単に概要だけ説明すると、以下の作業が必要になります。

  • IAMロールの設定(AWSCodeDeployRoleポリシーのアタッチ)
  • CodeDeploy Agentのインストール(参考
  • デプロイ対象として特定するためのタグの設定

なお、CodeDeployで利用できるサンプルアプリケーションはAWS公式にて公開されており、こちらを参考にダウンロード可能です。

Githubとの接続

CodePipelineとGithubとの接続については、従来のOAuthトークンを使用したversion 1と、CodeStarSourceConnectionを使ったversion 2があります。

現在、version 1の接続方法は非推奨となっており(参考)、version 2の利用が推奨されていることから、今回はversion 2を利用したいと思います。

以下の記事を参考に、接続を作成します。

CloudFromationテンプレート

codepipeline.yml

AWSTemplateFormatVersion: "2010-09-09"
Description: My CodePipeline

Metadata:
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "Github Information"
        Parameters:
          - FullRepositoryId
          - ReleaseBranchName
          - ConnectionArn
      - Label:
          default: "Deploy Parameters"
        Parameters:
          - Env
          - ApplicationName

Parameters:
  FullRepositoryId:
    Description: "Github full repository id (ex. OwnerName/RepositoryName)"
    Type: String
  ReleaseBranchName:
    Description: "Github release branch name"
    Type: String
    Default: main
  ConnectionArn:
    # 作成したCodeStar ConnectionsのARN
    Description: "CodeStar connection arn (ex. arn:aws:codestar-connections:ap-northeast-1:xxxxx)"
    Type: String
  Env:
    Description: "Choose the environment to create: 'dev' or 'prod'"
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod
  ApplicationName:
    Description: "Application Name"
    Type: String
    Default: my-application

Resources:
  #-----------------------------------------------------------------------------
  # S3
  #-----------------------------------------------------------------------------
  S3:
    Type: AWS::S3::Bucket
    Properties: 
      BucketEncryption: 
        ServerSideEncryptionConfiguration: 
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      BucketName: !Sub ${ApplicationName}-artifact-store-${Env}
      OwnershipControls:
        Rules: 
          - ObjectOwnership: BucketOwnerEnforced
      PublicAccessBlockConfiguration:
        BlockPublicAcls: True
        BlockPublicPolicy: True
        IgnorePublicAcls: True
        RestrictPublicBuckets: True
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-artifact-store-${Env}

  #-----------------------------------------------------------------------------
  # Role
  #-----------------------------------------------------------------------------
  CodeDeployIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - codedeploy.amazonaws.com
            Action: 
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - arn:aws:iam::aws:policy/service-role/AWSCodeDeployRole
      RoleName: !Sub ${ApplicationName}-codedeploy-iam-role-${Env}
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-codedeploy-iam-role-${Env}

  CodePipelineIAMPolicy:
    Type: AWS::IAM::ManagedPolicy
    Properties: 
      PolicyDocument:
        Version: "2012-10-17"
        Statement: 
          - Effect: Allow
            Action:
              - "codestar-connections:CreateConnection"
              - "codestar-connections:DeleteConnection"
              - "codestar-connections:UseConnection"
              - "codestar-connections:GetConnection"
              - "codestar-connections:ListConnections"
              - "codestar-connections:TagResource"
              - "codestar-connections:ListTagsForResource"
              - "codestar-connections:UntagResource"
              - "codedeploy:CreateDeployment"
              - "codedeploy:GetApplication"
              - "codedeploy:GetApplicationRevision"
              - "codedeploy:GetDeployment"
              - "codedeploy:GetDeploymentConfig"
              - "codedeploy:RegisterApplicationRevision"
            Resource: 
              - "*"
          - Effect: Allow
            Action:
              - "s3:GetObject"
              - "s3:PutObject"
              - "s3:ListBucket"
            Resource: 
              - !Join 
                - ''
                - - !GetAtt S3.Arn
                  - '/*'
              - !GetAtt S3.Arn
      ManagedPolicyName: !Sub ${ApplicationName}-codepipeline-iam-policy-${Env}

  CodePipelineIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - codepipeline.amazonaws.com
            Action: 
              - 'sts:AssumeRole'
      ManagedPolicyArns: 
        - !Ref CodePipelineIAMPolicy
      RoleName: !Sub ${ApplicationName}-codepipeline-iam-role-${Env}
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-codepipeline-iam-role-${Env}

  #-----------------------------------------------------------------------------
  # CodeDeploy
  #-----------------------------------------------------------------------------
  CodeDeployApplication:
    Type: AWS::CodeDeploy::Application
    Properties:
      ApplicationName: !Sub ${ApplicationName}-deploy-${Env}
      ComputePlatform: Server
      Tags: 
        - Key: Name
          Value: !Sub ${ApplicationName}-deploy-${Env}

  CodeDeployGroup:
    Type: AWS::CodeDeploy::DeploymentGroup
    Properties:
      ApplicationName: !Ref CodeDeployApplication
      AutoRollbackConfiguration: 
        Enabled: true
        Events:
          - DEPLOYMENT_FAILURE
      DeploymentConfigName: CodeDeployDefault.AllAtOnce
      DeploymentGroupName: !Sub ${ApplicationName}-deploy-group-${Env}
      # Set tag filters
      Ec2TagFilters: 
        - Key: "deploy"
          Type: KEY_AND_VALUE
          Value: "01"
      ServiceRoleArn: !GetAtt CodeDeployIAMRole.Arn
      Tags:
        - Key: Name
          Value: !Sub ${ApplicationName}-deploy-group-${Env}
  
  #-----------------------------------------------------------------------------
  # CodePipeline
  #-----------------------------------------------------------------------------
  CodePipeline:
    Type: 'AWS::CodePipeline::Pipeline'
    Properties:
      Name: !Sub ${ApplicationName}-pipeline-${Env}
      ArtifactStore:
        Type: S3
        Location: !Ref S3
      RoleArn: !GetAtt CodePipelineIAMRole.Arn
      # パイプライン更新時に自動実行をしないようにする
      RestartExecutionOnUpdate: false
      Stages:
        - Name: Source
          Actions:
            - Name: SourceAction
              ActionTypeId:
                Category: Source
                Owner: AWS
                Version: 1
                Provider: CodeStarSourceConnection
              Configuration:
                FullRepositoryId: !Ref FullRepositoryId
                ConnectionArn: !Ref ConnectionArn
                BranchName: !Ref ReleaseBranchName
                # ソースコード変更時にパイプラインを自動的に開始する
                DetectChanges: "true"
              OutputArtifacts:
                - Name: SourceOutput
              RunOrder: 1
        - Name: Deploy
          Actions:
            - Name: DeployAction
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Version: 1
                Provider: CodeDeploy
              Configuration:
                ApplicationName: !Ref CodeDeployApplication
                DeploymentGroupName: !Ref CodeDeployGroup
              InputArtifacts:
                - Name: SourceOutput
              RunOrder: 2

Outputs:
  CodeDeployApplicationName:
    Value: !Ref CodeDeployApplication
    Export: 
      Name: !Sub ${ApplicationName}-codedeploy-application-name-${Env}

  CodeDeployGroupName:
    Value: !Ref CodeDeployGroup
    Export: 
      Name: !Sub ${ApplicationName}-codedeploy-group-${Env}

  CodePipelineName:
    Value: !Ref CodePipeline
    Export: 
      Name: !Sub ${ApplicationName}-codepipeline-name-${Env}

パラメータについて

パラメータとして、以下を設定しています。

パラメータ名 設定値
FullRepositoryId GithubのレポジトリIDを設定する
ReleaseBranchName リリース対象のブランチ名を設定する
ConnectionArn 作成したCodeStar ConnectionsのARNを設定する
Env 環境名を設定する(dev or prod)
ApplicationName 任意のアプリケーション名を設定する

デプロイ対象のタグの設定

以下の部分で、デプロイ対象のEC2に設定しているタグを設定しています。

      Ec2TagFilters: 
        - Key: "deploy"
          Type: KEY_AND_VALUE
          Value: "01"

この例では、"deploy"というタグ名に、値として"01"を設定しているEC2を対象としています。

最後に

今回は、CodePipeline (Github version 2接続) とCodeDeployを利用したパイプラインをCloudFromationで作成してみました。

参考になりましたら幸いです。

参考文献