CICDハンズオン (CodeBuild, CodeDeploy)

CICD

本記事のCICDハンズオンは[AWS Hands-on for Beginners AWS Code サービス群を活用して、CI/CDのための構成を構築しよう]を参考にハンズオンを進めつつ、ハンズオンの中では深く説明がない部分を深堀しています。

CI/CDの構築を初めて実施する、という方に向けての初学者向けの内容となっております。

AWS Hands-on for Beginners AWS Code サービス群を活用して、CI/CD のための構成を構築しよう! | AWS Webinar

“AWS Hands-on for Beginners – AWS Code サービス群を活用して、CI/CD のための構成を構築しよう!” 編では、ハンズオン形式で継続的インテグレーション/継続的デプロイメント(CI/CD)構成を作成していただきます。具体的な AWS サービスとしては、AWS CodeCommit, AWS CodeBuild, AWS CodeDeploy, AWS CodePipeline を利用し、ソースコードの更新をトリガし、自動的にビルド、デプロイするパイプラインを作成いただきます。※本ウェビナーは2020年にレコーディングされたものです。

CICDとは

アプリケーションをデプロイするまでの流れは

デプロイまでの流れ
  • コードを書く
  • 書いたコードを動かせる状態にする (これをビルドするという)
  • ードを動かせる状態にしたプログラムをテストする
  • テストが終わるとプログラムをデプロイする
  • 上記の流れでアプリケーションはデプロイされますが、この流れを自動で実行することをCICD (Continuous Integration, Continuous Delivery) 継続的インテグレーション, 継続的デリバリーと呼ばれています。

    CodeBuildとは

    CodeBuildとは書いたコードを動かせる状態にし、テストを実行し、デプロイできる状態に持っていくことを指します。

    CodeDeployとは

    CodeDeployとはCodeBuildでデプロイできる状態にしたプログラムをAmazon EC2やオンプレサーバ、Amazon ECSなどのデプロイ対象に対してデプロイを実行します。

    構成図

    今回はEC2インスタンスをデプロイ対象としてCodeCommit -> CodeBuild -> CodeDeployCodePipelineでつないで、git pushを実行すると自動でCodeCommitからCodeDeployまでが実行され、最終的にEC2インスタンスにデプロイがされるというハンズオンを行っていきます。

    前提

    前提条件
  • すでにCodeCommitでindex.htmlをリポジトリを作成済み
  • アーティファクト保存用のS3が作成されていること -> 作成されていない場合は[アーティファクト保存用のS3バケットの情報]を参考に作成してください
  • 事前準備

    EC2にアタッチするIAMロールを作成

    AmazonS3FullAccess権限のポリシーおよびAmazonSSMManagedInstanceCoreをアタッチしたロールを作成します。

    上記2つのポリシーが必要な理由

    AmazonS3FullAccess -> CodeCommitにPushしたソースコードはCodeBuildを介してソースコードから実際に動かすプログラムに変換させたものを (アーティファクト)S3へアップロードします -> その後CodeDeployがbuildspec.yml, appspec.ymlというファイル (後述します)をトリガーして、S3からアプロードしたプログラムをEC2からS3へダウンロードする際にS3へアクセスするため、S3へのアクセス権限が必要となります。

    上記をわかりやすく図にすると以下のイメージです。

    今回は基本的な動きを確認するためにAmazonS3FullAccessを使用していますが、最小権限に絞る場合には、S3へGet, Listの権限が付いていればアーティファクトのダウンロードは可能かと思います。

    {
        "Effect": "Allow",
        "Action": [
            "s3:GetObject",
            "s3:ListBucket"
        ],
        "Resource": [
            "arn:aws:s3:::your-code-deploy-bucket",
            "arn:aws:s3:::your-code-deploy-bucket/*"
        ]
    }

    AmazonSSMManagedInstanceCore -> 今回のハンズオンではSSH接続ではなくSessionManagerを使用してインスタンスに接続を行うため必要となります。

    EC2インスタンスにApacheを設定

    EC2インスタンス起動の際にユーザーデータに以下を流し込みます。

    Apacheを起動して、単純なindex.htmlを配置し、ソースコードを編集してgit pushして自動デプロイができるところまでを想定しています。

    echo "=======yum update -y======="
    yum update -y
    echo "=======yum install httpd -y======="
    yum install httpd -y
    echo "=======systemctl start httpd======="
    systemctl start httpd
    echo "=======systemctl enable httpd======="
    systemctl enable httpd

    CodeDeployエージェントインストール

    Amazon Linux または RHEL CodeDeploy 用のエージェントをインストールします。

    インスタンスにサインインし、次のコマンドを一度に 1 つずつ実行します。コマンド sudo yum update を最初に実行するのが、 yum を使用してパッケージをインストールするときのベストプラクティスと考えられていますが、すべてのパッケージを更新しない場合はこのコマンドをスキップできます。

    yum install ruby -y
    yum install wget -y
    cd
    wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
    chmod +x ./install
    ./install auto
    service codedeploy-agent start
    service codedeploy-agent status

    CICDハンズオン

    アーティファクト保存用のS3バケットの情報

    S3バケット名cicd-bucket-artifact-ユーザーID
    オブジェクト所有者ACL無効
    このバケットのパブリックアクセス設定パブリックアクセスをすべてブロック
    バケットのバージョニング無効
    デフォルトの暗号化Amazon S3 マネージドキーを使用したサーバー側の暗号化 (SSE-S3)

    ビルドプロジェクトを作成

    プロジェクト名dev-cicd-handson
    ソースプロバイダAWS CodeCommit
    リポジトリdev-cicd-handson
    ブランチmaster
    オペレーティングシステムAmazon Linux
    ランタイムStandard
    イメージaws/codebuild/amazonlinux2-x86_64-standard:5.0
    イメージのバージョンaws/codebuild/amazonlinux2-x86_64-standard:5.0-23.12.14
    ロール名codebuild-dev-cicd-handson-service-role (デフォルト名)
    アーティファクトS3
    バケット名cicd-bucket-artifact-AWSユーザーID

    CodeBuild画面から[ビルドプロジェクトを作成する]をクリックします。

    [プロジェクト名]を入力します。

    ソースプロバイダ、リポジトリ、ブランチを設定します。

    ソースプロバイダについては今回は[AWS CodeCommit]を使用します。

    リポジトリはCodeCommitで作成したリポジトリを選択します。

    ブランチについてはmasterしかブランチを用意していないため、[master]を選択します。

    環境についてですが、ソースコードをBuildを行うための環境を[どのOS][どのイメージ][どのイメージのバージョン]を使用するかを決める項目となっています。

    ここで選択する[イメージ]についてですが、ビルド作業を行う際のDockerイメージであり、Amazon Linux2ベースのビルド環境となっています。

    Build実行時に必要なツールをまとめたイメージをどれにしますか?を選択する項目になっていて、イメージとは色々なツールがまとまって入っている記憶媒体だと思ってもらえれば良いです。

    もう少し簡単に言ってしまうと、DVDやCDと思ってもらえると理解し易いかと思います。

    ここで選択するイメージには例えば以下のようなものが含まれていて、Buildする際に必要なものが盛り込まれています。

    イメージ
  • 一般的なプログラミング言語(Python、Node.js、Java、Ruby など)のランタイムとツール
  • コンパイラとビルドツール(gcc、make など)
  • Git クライアント
  • Docker クライアント
  • AWS CLI(Amazon Web Services のコマンドラインツール)
  • イメージについてなんとなく理解ができたところで、各項目は下図を選択していきます。

    オペレーティングシステム: [Amazon Linux]

    ランタイム: [Standard]

    イメージ: [aws/codebuild/amazonlinux2-x86_64-standard:5.0] 最新のものを選択

    イメージのバージョン: [このランタイムバージョンには常に最新のイメージを使用してください]

    サービスロールは既存のものが存在しなければ新たなものを作成します。

    サービスロール名はデフォルトで入力されます。

    buildspecファイルは使用します。

    buildspecとはBuild実行時にコマンドを記述するファイルです。

    アーティファクトはタイプ[Amazon S3]

    バケット名は作成したバケット名を入力

    これでビルドプロジェクトを作成します。

    CodeBuildのロールにポリシーをアタッチ

    ビルドプロジェクト作成時に作成されたIAMロールに追加で[AWSCodeDeployDeployerAccess]のポリシーをアタッチする必要があります。

    結論から話すと、このポリシーがアタッチされていないと、CodeBuild実行後、CodeDeployのフェーズで失敗します。

    詳細は後述します。

    [AWSCodeDeployDeployerAccess]のポリシーの詳細は以下の通りです。

    CodeDeploy関連のアクション
  • codedeploy:Batch*: CodeDeployのバッチ操作を実行できる権限
  • codedeploy:CreateDeployment: デプロイを作成できる権限
  • codedeploy:Get*: CodeDeployに関する情報を取得できる権限
  • codedeploy:List*: リスト操作を実行できる権限
  • codedeploy:RegisterApplicationRevision: アプリケーションのリビジョンを登録できる権限
  • CodeStar Notificationsに関連するアクション
  • codestar-notifications:CreateNotificationRule: 通知ルールを作成できる権限
  • codestar-notifications:DescribeNotificationRule: 通知ルールに関する情報を取得できる権限
  • codestar-notifications:UpdateNotificationRule: 通知ルールを更新できる権限
  • codestar-notifications:Subscribe: 通知にサブスクライブできる権限
  • codestar-notifications:Unsubscribe: サブスクライブを解除できる権限
  • CodeStar Notificationsのリスト操作に関するアクション
  • codestar-notifications:ListNotificationRules: 通知ルールのリストを取得できる権限
  • codestar-notifications:ListTargets: 通知の対象のリストを取得できる権限
  • codestar-notifications:ListTagsforResource: リソースに関連するタグのリストを取得できる権限
  • codestar-notifications:ListEventTypes: イベントタイプのリストを取得できる権限
  • Chatbotに関連するアクション
  • chatbot:DescribeSlackChannelConfigurations: Slackチャンネルの構成に関する情報を取得できる権限
  • SNSトピックのリスト操作に関するアクション
  • sns:ListTopics: SNSトピックのリストを取得できる権限
  • buildspec.ymlの作成

    buildspec.ymlファイルをローカルリポジトリのルート配下に作成します。

    touch buildspec.yml

    作成したファイルに以下のようにコードを記述します。

    version: 0.2
    phases:
      build:
        commands:
          - aws deploy push --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-xxxxxxxxxx/artifact.zip --source src
    artifacts:
      files:
        - '**/*'
      base-directory: src

    このbuildspec.ymlファイルが何をしているのかを一つ一つ見ていこうと思います。

    phases : 以下に各処理のフェーズを記述します。

    build : ビルドフェーズ

    aws deploy push コマンドを使用して--application-name dev-cicd-app (後述する手順で作成します)ではdev-cicd-appというアプリケーションをデプロイします。

    --s3-location s3://cicd-bucket-artifact-xxxxxxxxx/artifact.zip srcディレクトリから取得したソースコードをarttifact.zipに圧縮してcicd-bucket-artifact-xxxxxxxxxのS3バケットへアップロードします。

    --source src srcディレクトリに存在するソースコードを取得します。

    artfifacts : アーティファクト → ビルドして生成されるファイルを定義します。

    files アーティファクトに含めるファイルのリストを定義します。

    - '**/*'ですべてのファイルを指定

    base-directory: src アーティファクトに含めるビルド対象のディレクトリを定義しています。

    CodeDeploy用ロールの作成

    CodeBuild -> CodeDeployを行う際に、CodeBuildがCodeDeployするために必要な権限を定義します。

    IAMロールの作成からAWSCodeDeployRoleのポリシーをアタッチしてロールを作成します。

    AssumeRoleする対象のサービスはcodedeploy.amazonaws.comとなります。

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "",
                "Effect": "Allow",
                "Principal": {
                    "Service": "codedeploy.amazonaws.com"
                },
                "Action": "sts:AssumeRole"
            }
        ]
    }

    CodeDeployアプリケーション作成

    CodeDeployの画面の左ペイン[アプリケーション] -> [アプリケーションの作成]ボタンをクリックします。

    アプリケーション名: [dev-cicd-app]と入力

    コンピューティングプラットフォーム: [EC2/オンプレミス]を選択

    [アプリケーションの作成]ボタンをクリックします。

    ここで作成したアプリケーション名をbuildspec.ymlの--application-name に指定してやる必要があります。

    再掲

    version: 0.2
    phases:
      build:
        commands:
          - aws deploy push --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-674078804300/artifact.zip --source src
    artifacts:
      files:
        - '**/*'
      base-directory: src

    デプロイグループの作成

    [デプロイグループの作成]ボタンをクリックします。

    デプロイグループ名: [Web] (デプロイグループ名は何でも良いです、どんなアプリケーションをデプロイするのかがわかる名称をつけます)

    サービスロール: [arn:aws:iam::xxxxxxx/CodeDeployRole] (CodeDeploy用に作成したロールを選択します)

    アプリケーションのデプロイ方法: [インプレース]

    インプレースとBlue/Greenデプロイの違いについては以下

    インプレース: 既存インスタンスにデプロイします。

    Blue/Green: 既存環境と同じ構成を持つEC2インスタンスが作成され (新しい環境が作成される: Green)、そのインスタンスにアプリケーションのデプロイを行います。

    デプロイ成功後、トラフィックを既存環境から新しい環境に切り替え移行を行います。

    リリースの手段として

    - Canary: トラフィックの一部を最初に新しいバージョンに移行し、その後一定時間を置いて残りのトラフィックを移行します。 
    例: 最初にトラフィックの10%を新しいバージョンに移行し、30分後に残りのトラフィックを新しいバージョンに移行するなど
    - Canary: トラフィックの一部を最初に新しいバージョンに移行し、その後一定時間を置いて残りのトラフィックを移行します。 
    例: 最初にトラフィックの10%を新しいバージョンに移行し、30分後に残りのトラフィックを新しいバージョンに移行するなど
    - Linear: 一定間隔で新しいバージョンに移行します。
    例: 10分ごとにトラフィックの10%を新しいバージョンに移行するなど
    - AllAtOnce: すべてのトラフィックを一度に新しいバージョンに移行します。

    でのデプロイ設定の操作 CodeDeploy

    CodeDeploy でデプロイ設定を使用する方法を説明します。

    環境設定: [Amazon EC2インスタンス]にチェック

    タググループ: キーおよび値を作成したEC2インスタンスを選択

    AWS CodeDeploy エージェントのインストール: [なし] (すでに手動でCodeDeployエージェントはインストール済みのため)

    デプロイ設定: [CodeDeployDefault.AllAtOnce]を選択

    [ロードバランシングを有効にする]のチェックをはずし、[デプロイグループの作成]ボタンをクリックします。

    appspec.ymlの作成

    appspec.ymlとは

    前提として、appspec.ymlはアプリケーションのソースコードが存在するディレクトリのルート配下に配置する必要があります。

    CodeDeployを実行する際に、動作するOSはなにで、どこに、どんなファイルを配置するのか?を定義するファイルです。

    srcディレクトリ配下にappspec.ymlファイルを作成します。

    touch appspec.yml

    ファイルの中身を以下のように記述します。

    version: 0.0
    os: linux
    files:
      - source: index.html
        destination: /var/www/html/

    詳細:

    OS: 動作するOSを指定

    files: デプロイするファイルを指定

    source: デプロイする対象のソースコードを指定 → この場合ローカルリポジトリに存在するindex.htmlというファイルがデプロイ対象のファイルであることを示しています

    destination: デプロイ先のディレクトリを指定 -> Linuxの/var/www/html/ のディレクトリに対してデプロイを行う指定をしています。

    CodeDeploy AppSpec ファイルリファレンス

    AppSpec で使用されるファイルの構造とセクションについて説明します CodeDeploy。

    appspec.ymlファイルの作成が完了したら、$ git commit -> $ git pushを行います。

    git add .
    git commit -m 'commit message'
    git push origin master

    CodeBuildの実行

    CodeBuildを実行します。

    CodeBuildの画面から[ビルドを開始]ボタンをクリックします。

    ステータスが[成功]していれば、Buildは成功しています。

    ビルド成功ログ

    [Container] 2023/12/26 21:10:04.311125 Waiting for agent ping
    [Container] 2023/12/26 21:10:05.312000 Waiting for DOWNLOAD_SOURCE
    [Container] 2023/12/26 21:10:14.041450 Phase is DOWNLOAD_SOURCE
    [Container] 2023/12/26 21:10:14.051365 CODEBUILD_SRC_DIR=/codebuild/output/src1742860277/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dev-cicd-handson
    [Container] 2023/12/26 21:10:14.051917 YAML location is /codebuild/output/src1742860277/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dev-cicd-handson/buildspec.yml
    [Container] 2023/12/26 21:10:14.053993 Not setting HTTP client timeout for source type codecommit
    [Container] 2023/12/26 21:10:14.054155 Processing environment variables
    [Container] 2023/12/26 21:10:14.310903 No runtime version selected in buildspec.
    [Container] 2023/12/26 21:10:14.336142 Moving to directory /codebuild/output/src1742860277/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dev-cicd-handson
    [Container] 2023/12/26 21:10:14.339131 Unable to initialize cache download: no paths specified to be cached
    [Container] 2023/12/26 21:10:14.509142 Configuring ssm agent with target id: codebuild:52903477-1d32-40cd-9b95-ee5cf6c6754c
    [Container] 2023/12/26 21:10:14.538345 Successfully updated ssm agent configuration
    [Container] 2023/12/26 21:10:14.538905 Registering with agent
    [Container] 2023/12/26 21:10:14.538919 Phases found in YAML: 1
    [Container] 2023/12/26 21:10:14.538925  BUILD: 1 commands
    [Container] 2023/12/26 21:10:14.539266 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
    [Container] 2023/12/26 21:10:14.539278 Phase context status code:  Message: 
    [Container] 2023/12/26 21:10:14.635021 Entering phase INSTALL
    [Container] 2023/12/26 21:10:14.675746 Phase complete: INSTALL State: SUCCEEDED
    [Container] 2023/12/26 21:10:14.675763 Phase context status code:  Message: 
    [Container] 2023/12/26 21:10:14.713851 Entering phase PRE_BUILD
    [Container] 2023/12/26 21:10:14.715310 Phase complete: PRE_BUILD State: SUCCEEDED
    [Container] 2023/12/26 21:10:14.715322 Phase context status code:  Message: 
    [Container] 2023/12/26 21:10:14.747416 Entering phase BUILD
    [Container] 2023/12/26 21:10:14.747933 Running command aws deploy push --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-xxxxxxxxxx/artifact.zip --source src
    To deploy with this revision, run:
    aws deploy create-deployment --application-name dev-cicd-app --s3-location bucket=cicd-bucket-artifact-xxxxxxxxxx,key=artifact.zip,bundleType=zip,eTag=991ac8c456664a87293e6d326808b85a --deployment-group-name <deployment-group-name> --deployment-config-name <deployment-config-name> --description <description>
    
    [Container] 2023/12/26 21:10:28.836196 Phase complete: BUILD State: SUCCEEDED
    [Container] 2023/12/26 21:10:28.836213 Phase context status code:  Message: 
    [Container] 2023/12/26 21:10:28.880681 Entering phase POST_BUILD
    [Container] 2023/12/26 21:10:28.882522 Phase complete: POST_BUILD State: SUCCEEDED
    [Container] 2023/12/26 21:10:28.882537 Phase context status code:  Message: 
    [Container] 2023/12/26 21:10:28.987380 Expanding base directory path: src
    [Container] 2023/12/26 21:10:28.991115 Assembling file list
    [Container] 2023/12/26 21:10:28.991130 Expanding src
    [Container] 2023/12/26 21:10:28.994281 Expanding file paths for base directory src
    [Container] 2023/12/26 21:10:28.994295 Assembling file list
    [Container] 2023/12/26 21:10:28.994329 Expanding **/*
    [Container] 2023/12/26 21:10:28.997373 Found 2 file(s)
    [Container] 2023/12/26 21:10:28.998456 Phase complete: UPLOAD_ARTIFACTS State: SUCCEEDED
    [Container] 2023/12/26 21:10:28.998468 Phase context status code:  Message:
    [CodeBuildのロールにポリシーをアタッチする]の項でもご説明しましたが、適切なロールがアタッチされていない場合はBuildがに失敗します。

    ビルド失敗ログ

    [Container] 2023/12/26 11:50:53.956042 Waiting for agent ping
    [Container] 2023/12/26 11:50:54.957011 Waiting for DOWNLOAD_SOURCE
    [Container] 2023/12/26 11:51:03.912894 Phase is DOWNLOAD_SOURCE
    [Container] 2023/12/26 11:51:03.924724 CODEBUILD_SRC_DIR=/codebuild/output/src1029631/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dev-cicd-handson
    [Container] 2023/12/26 11:51:03.925338 YAML location is /codebuild/output/src1029631/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dev-cicd-handson/buildspec.yml
    [Container] 2023/12/26 11:51:03.927646 Not setting HTTP client timeout for source type codecommit
    [Container] 2023/12/26 11:51:03.927764 Processing environment variables
    [Container] 2023/12/26 11:51:04.291765 No runtime version selected in buildspec.
    [Container] 2023/12/26 11:51:04.317152 Moving to directory /codebuild/output/src1029631/src/git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/dev-cicd-handson
    [Container] 2023/12/26 11:51:04.320233 Unable to initialize cache download: no paths specified to be cached
    [Container] 2023/12/26 11:51:04.502623 Configuring ssm agent with target id: codebuild:12b9467f-cfc1-4528-957e-4ac0b3dc9116
    [Container] 2023/12/26 11:51:04.537354 Successfully updated ssm agent configuration
    [Container] 2023/12/26 11:51:04.537990 Registering with agent
    [Container] 2023/12/26 11:51:04.538007 Phases found in YAML: 1
    [Container] 2023/12/26 11:51:04.538013  BUILD: 1 commands
    [Container] 2023/12/26 11:51:04.538380 Phase complete: DOWNLOAD_SOURCE State: SUCCEEDED
    [Container] 2023/12/26 11:51:04.538401 Phase context status code:  Message: 
    [Container] 2023/12/26 11:51:04.622329 Entering phase INSTALL
    [Container] 2023/12/26 11:51:04.667515 Phase complete: INSTALL State: SUCCEEDED
    [Container] 2023/12/26 11:51:04.667539 Phase context status code:  Message: 
    [Container] 2023/12/26 11:51:04.717923 Entering phase PRE_BUILD
    [Container] 2023/12/26 11:51:04.719959 Phase complete: PRE_BUILD State: SUCCEEDED
    [Container] 2023/12/26 11:51:04.719973 Phase context status code:  Message: 
    [Container] 2023/12/26 11:51:04.757667 Entering phase BUILD
    [Container] 2023/12/26 11:51:04.758443 Running command aws deploy push --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-xxxxxxxxxx/artifact.zip --source src
    
    An error occurred (AccessDeniedException) when calling the RegisterApplicationRevision operation: User: arn:aws:sts::674078804300:assumed-role/codebuild-dev-cicd-handon-service-role/AWSCodeBuild-12b9467f-cfc1-4528-957e-4ac0b3dc9116 is not authorized to perform: codedeploy:RegisterApplicationRevision on resource: arn:aws:codedeploy:ap-northeast-1:xxxxxxxxxx:application:dev-cicd-app because no identity-based policy allows the codedeploy:RegisterApplicationRevision action
    
    [Container] 2023/12/26 11:51:27.480436 Command did not exit successfully aws deploy push --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-674078804300/artifact.zip --source src exit status 254
    [Container] 2023/12/26 11:51:27.485809 Phase complete: BUILD State: FAILED
    [Container] 2023/12/26 11:51:27.485825 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: aws deploy push --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-xxxxxxxxxx/artifact.zip --source src. Reason: exit status 254
    [Container] 2023/12/26 11:51:27.529171 Entering phase POST_BUILD
    [Container] 2023/12/26 11:51:27.531222 Phase complete: POST_BUILD State: SUCCEEDED
    [Container] 2023/12/26 11:51:27.531235 Phase context status code:  Message: 
    [Container] 2023/12/26 11:51:27.620361 Expanding base directory path: src
    [Container] 2023/12/26 11:51:27.624352 Assembling file list
    [Container] 2023/12/26 11:51:27.624368 Expanding src
    [Container] 2023/12/26 11:51:27.628592 Expanding file paths for base directory src
    [Container] 2023/12/26 11:51:27.628607 Assembling file list
    [Container] 2023/12/26 11:51:27.628611 Expanding **/*
    [Container] 2023/12/26 11:51:27.631910 Found 2 file(s)
    [Container] 2023/12/26 11:51:27.633062 Phase complete: UPLOAD_ARTIFACTS State: SUCCEEDED
    [Container] 2023/12/26 11:51:27.633074 Phase context status code:  Message:

    ビルドが失敗している箇所

    [Container] 2023/12/26 11:51:04.758443 Running command aws deploy push 
    --application-name dev-cicd-app --s3-location s3://cicd-bucket-artifact-xxxxxxxxxx/artifact.zip --source src
    
    
    An error occurred (AccessDeniedException) when calling the RegisterApplicationRevision operation: 
    User: arn:aws:sts::xxxxxxxxxx:assumed-role/codebuild-dev-cicd-handon-service-role/AWSCodeBuild-12b9467f-cfc1-4528-957e-4ac0b3dc9116 is not authorized to perform: 
    codedeploy:RegisterApplicationRevision on resource: 
    arn:aws:codedeploy:ap-northeast-1:xxxxxxxxxx:application:dev-cicd-app because no identity-based policy allows the codedeploy:RegisterApplicationRevision action

    aws deploy pushコマンドを実行しようとしたところ、CodeDeployへの必要な権限が付与されていないためエラーを吐いている。

    CodeDeployのRegisterApplicationRevision actionというAPIを投げているが、dev-cicd-handonのビルドプロジェクトには、その権限がない、と言われいてる。

    codedeploy:RegisterApplicationRevision on resource: 
    arn:aws:codedeploy:ap-northeast-1:674078804300:application:dev-cicd-app because no identity-based policy allows the codedeploy:RegisterApplicationRevision action

    ビルドプロジェクト作成時に作成されるロールに対してAWSCodeDeployDeployerAccessというポリシーを追加でアタッチしていなかったことが原因だったため、codebuild-ビルドプロジェクト名-service-roleに対して、ポリシーを追加する必要があります。

    ポリシー: AWSCodeDeployDeployerAccess
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "codedeploy:Batch*",
                    "codedeploy:CreateDeployment",
                    "codedeploy:Get*",
                    "codedeploy:List*",
                    "codedeploy:RegisterApplicationRevision"
                ],
                "Effect": "Allow",
                "Resource": "*"
            },
            {
                "Sid": "CodeStarNotificationsReadWriteAccess",
                "Effect": "Allow",
                "Action": [
                    "codestar-notifications:CreateNotificationRule",
                    "codestar-notifications:DescribeNotificationRule",
                    "codestar-notifications:UpdateNotificationRule",
                    "codestar-notifications:Subscribe",
                    "codestar-notifications:Unsubscribe"
                ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "codestar-notifications:NotificationsForResource": "arn:aws:codedeploy:*"
                    }
                }
            },
            {
                "Sid": "CodeStarNotificationsListAccess",
                "Effect": "Allow",
                "Action": [
                    "codestar-notifications:ListNotificationRules",
                    "codestar-notifications:ListTargets",
                    "codestar-notifications:ListTagsforResource",
                    "codestar-notifications:ListEventTypes"
                ],
                "Resource": "*"
            },
            {
                "Sid": "CodeStarNotificationsChatbotAccess",
                "Effect": "Allow",
                "Action": [
                    "chatbot:DescribeSlackChannelConfigurations"
                ],
                "Resource": "*"
            },
            {
                "Sid": "SNSTopicListAccess",
                "Effect": "Allow",
                "Action": [
                    "sns:ListTopics"
                ],
                "Resource": "*"
            }
        ]
    }

    上記のポリシーをアタッチすることで、エラーは解消されます。

    CodeDeployを実行する

    CodeDeploy画面の左ペインから[CodeDeploy] -> [ アプリケーション]を選択し、デプロイグループで作成した名前をクリックします。

    [デプロイの作成]ボタンをクリックします。

    デプロイグループ: [Web]

    リビジョンタイプ: [アプリケーションはAmazon S3に格納されています]を選択

    リビジョンタイプ: 選択できるS3バケットを選択

    [デプロイの作成]ボタンをクリックします。

    これで無事にデプロイが完了し、EC2インスタンスのパブリックIPアドレスでブラウザにアクセスし、デプロイしたindex.htmlの内容が表示されればOKです。

    本記事ではCodeBuild -> CodeDeployの作業を手動で行いました。

    これをCodeCommit -> CodeBuild -> CodeDeployまでの一連の工程をCodePipelineでつないで$ git push時に自動で行ってくれるまでが本来のCICDの動きになるかと思いますが、今回は手動でCodeBuild, CodeDeployの操作を行っております。

    一つ一つの動きを一つずつ動かしていくことでどういう仕組みで動ているのか、という理解を深めるための良いハンズオンとなりました。

    参考記事

    Codeシリーズで始めるはじめてのCI/CD (#higobashiaws で登壇しました) | DevelopersIO

    CI/CDわからない、難しそうと感じてらっしゃる方、Codeシリーズなんとなく知ってるけど使ったことない方に向けて、Codeシリーズの概要を理解していただき、便利やん!やってみよ!と思っていただく、というところ目指した登壇を行ないました。こちらはそれをブログにアレンジしたものです。

    コメントを残す

    メールアドレスが公開されることはありません。 * が付いている欄は必須項目です