AWS-CodeBuild

CodeBuildでECRのカスタムイメージを利用する

はじめに

こんにちは、omkです。
だんだん涼しくなってきましたが風邪などひかれないようにご注意ください。

さて、前回はCodeBuildでawspecのテストを実行しましたが、そのときはデフォルトのコンテナイメージを利用し、必要なパッケージをすべて「buildspec.yml」に記載してBuild実行時にコンテナにインストールしていました。
このやりかたでは毎度テストするたびにパッケージインストールが発生し、時間を取られてしまいます。特にawspecは環境の準備に時間がかかりますのでこれを短縮したいと思います。

CodeBuildでは使用するコンテナイメージを「マネージド型イメージ」と「カスタムイメージ」の2種類から選択できます。
前者はAWSが管理するAmazonLinux2やubuntuのイメージで、後者はユーザーで管理するECRやその他のリポジトリに登録しているイメージです。
今回は後者のカスタムイメージで、予め必要なパッケージのインストールを済ませたイメージをECRに登録してCodeBuildで使用します。

やってみた

ビルドの内容は何でもいいので、前回同様awspecを実行してもらいます。
本記事ではawspecの動作環境を作ることをベースにして進めますが、awspecの記事ではないということで関連する内容の詳細は省きます。

ECRリポジトリ作成

コンパネからECRリポジトリを作成します。
画面に従ってプライベートなリポジトリを作成しました。

Dockerイメージ作成~ECRにプッシュ

次にEC2上にDocker環境を作成してイメージをECRにプッシュします。

作成したDockerfileは以下です。

FROM amazonlinux:latest
RUN amazon-linux-extras install ruby3.0
RUN yum install -y ruby-devel
RUN yum install -y awscli
RUN yum install -y jq
RUN gem install awspec
RUN gem install rexml
RUN gem install rspec

AmazonLinux2の公式イメージをプルしたものをベースにawspecの実行に必要なパッケージを導入しています。
これをビルドしてECRにプッシュします。プッシュはECRリポジトリに表示される「プッシュコマンドの表示」の内容に従います。

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {ECRのURI}

$ docker build -t {イメージ名}:latest ./

$ docker tag {イメージ名}:latest {ECRのURI}/{リポジトリ名}:latest

$ docker push {ECRのURI}/{リポジトリ名}:latest

ECRにプッシュするためにEC2のIAMロールにはAWS管理ポリシー「EC2InstanceProfileForImageBuilderECRContainerBuilds」を割り当てています。

プッシュできました。

EC2上のDockerでこのコンテナイメージを利用する場合はこの段階でECRからイメージをプルして利用することができます。
以下の権限があればEC2からプルできます。

"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:GetAuthorizationToken"

やってみます。

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {ECRのURI}

$ docker pull {ECRのURI}/{リポジトリ名}:latest

$ docker images
-------------------------------
REPOSITORY       TAG       (ry
{ECRのURI}/{リポジトリ名}   latest  (ry
-------------------------------

プルできました。

しかし、CodeBuildからコンテナを利用する場合にはECRリポジトリに別途権限の設定が必要となります。

ECR権限設定

若干分かりづらいですが、ECRで対象のリポジトリを選択したらナビゲーションペインに選択前にはなかった項目が表示されます。

before


after

そのうちの「Permissions」を選択して権限を設定します。
権限はコンパネの案内に従って設定することも可能ですしポリシーJSONを直接編集することもできます。
今回は前者で進めます。

「編集」→「アクセス許可ステートメントを追加」を選択することで以下の画面が表示されます。

CodeBuildで利用する際に必要な設定として

  • サービスプリンシパルに「codebuild.amazonaws.com」を設定
  • 許可するアクションに「ecr:GetDownloadUrlForLayer」「ecr:BatchGetImage」「ecr:BatchCheckLayerAvailability」を設定

が必要です。
他は必要に合わせて条件を絞るなどしてください。

EC2でイメージをプルする際にはdockerログインのために「ecr:GetAuthorizationToken」が必要でしたが、CodeBuildで利用する際には不要です。

以下のポリシーができました。

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "CodeBuildAccess",
      "Effect": "Allow",
      "Principal": {
        "Service": "codebuild.amazonaws.com"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ]
    }
  ]
}

これでCodeBuildでECRリポジトリにアクセスできるようになります。

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

では、最後にビルドプロジェクトを作成します。

AWSマネージド型イメージを利用しない場合と変わってくるのは「環境」の設定です。
それ以外はケースによって異なるので省略します。

「環境イメージ」に「カスタムイメージ」を設定し、環境のタイプはDockerイメージに合わせて選択し(今回はLinux)、「イメージレジストリ」を「Amazon ECR」として、「ECRアカウント」で「自分のECR」を選択します。そしてレポジトリ、イメージを先程作成したものを設定します。
認証情報プルイメージに「AWS CodeBuild 認証情報」を選択します。
最後にサービスロールに適切な権限を設定したものを選択します(前述した3つの権限が必要)。なければ作ってください。

最終的にこんな感じになります。

これでビルドプロジェクトの設定が完了です。
以上の設定を通してCodeBuildでECRのイメージを利用することが可能となります。

ビルド実行

試しに前回同様の設定でawspecを実行してみます。
前回作成したbuildspec.ymlからパッケージインストール部分を除外し、以下の状態にしました。
awspecの初期化を行い、テストに必要なロールの取得、テスト実行、結果出力というような内容になっています。

version: 0.2
phases:
  pre_build:
    commands:
      - awspec init
      - mv ./*_spec.rb ./spec/
      # Get IAMRole
      - curl -qL -o aws_credentials.json 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI > aws_credentials.json
      - aws configure set region $AWS_REGION
      - aws configure set aws_access_key_id `jq -r '.AccessKeyId' aws_credentials.json`
      - aws configure set aws_secret_access_key `jq -r '.SecretAccessKey' aws_credentials.json`
      - aws configure set aws_session_token `jq -r '.Token' aws_credentials.json`
  build:
    commands:
      - echo "test start"
      - rake spec > ./result.txt || true
  post_build:
    commands:
      - echo "Nothing to do"

artifacts:
  files:
      - './result.txt'

ではビルドを実行します。

完了しました。
ECRイメージが読めない場合はここでエラーがでますが、awspecの実行まで行えているので正常にイメージが利用できたことが分かります。

まとめ

元々パッケージインストールに5分かかっていたところ1分でテストが終わるようになりました。
よく使うビルドは極力かかる時間を短くしていきたいですね。

以上お付き合いありがとうございました。

参考

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-ecr.html

返信を残す

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

CAPTCHA