public memo

エンジニア向け小ネタ書き溜め用。公開日記だけど親切な文章とは程遠いかもしれない。

CodeBuildのビルド実行時間を短縮する方法まとめ

2020-09-24 by MasakiMisawa
Tweet
このエントリーをはてなブックマークに追加
Pocket
LINEで送る

前回に引き続き、CodeBuildのビルド実行時間を短縮ネタです。
前回は急にビルド実行時間が長くなってしまった場合のトラブルシューティング的な内容でしたが、今回はビルド実行時間を短縮する手段としてどんな方法が存在するかがメインです。
真新しい内容は特になく自分用まとめ的な内容ですが、毎回のビルドプロジェクト作成時に忘れないようにする為にメモとして残しておきます。

目的

CodeBuildのビルド実行時間を短くすることが目的と言えばそれまでですが、ビルド時間短縮には以下二つの嬉しさがあります。

1. (主にCIなどでの)ビルド実行結果の待ち時間が短くなる

以前の記事でも書きましたが、Pull Request作成時に自動でビルドやテストを回して全てが正常終了したのを確認後にマージ可能にするようなCIでCodeBuildを使っている環境では、ビルドが完了するまでマージを待たなければなりません。
テストが落ちて修正を行う場合にもビルド実行結果を見てから修正作業を開始する必要があり、一回のビルド時間が短くなればストレスも軽減されます。

2. CodeBuild利用料金の節約

CodeBuildの利用料金は、ビルドを実行した時間分の料金になっています。
ビルド時間が短くなれば利用料金も安くなるので一石二鳥です。

ビルド実行時間短縮方法

という事で、ビルド実行時間を短縮できる方法をまとめてみます。

1. BuildKitの有効化

  • 概要
  • Dockerのイメージビルドを行う場合の実行時間短縮方法で、Dockerfileに定義した依存関係のないレイヤを並列実行させたり、キャッシュを有効利用できるようにしたりと大幅な実行時間短縮が期待できます。
    Dockerのイメージビルドは主にBuildフェーズなどで行う内容の為、実行時間が短縮されるフェーズも同様です。

  • 使用条件
  • Dockerのランタイムバージョンが18.09以上である必要がありますが、CodeBuildの環境イメージに使用できるAWSが用意するマネージド型イメージでも昨年対応されて使用可能になっています。

  • 使用方法
  • 環境変数のDOCKER_BUILDKITに1を設定しておくだけです。
    CodeBuildで環境変数を設定する方法は幾つかありますが、他の設定と同じくbuildspec.ymlに記述しておくのが管理的にも楽でしょうか。

    buildspec.yml
    YAML
    1
    2
    3
    env:
      variables:
        DOCKER_BUILDKIT: "1"

  • その他
  • ビルド高速化ではないですが、BuildKitには鍵ファイルなどを削除する前のレイヤが残ってしまう問題を解消するSecret/SSH Mountの導入など、セキュアビルド観点でも嬉しい変更が多々入っているのでデフォルトで有効化しておいても良いと思います。
    詳しくは同プロジェクトのメンテナでもいらっしゃる方のスライドをご参照ください。


コンテナ全盛のご時世、定義したDockerfileとGitリポジトリにpushした最新のソースコードを元にCodeBuildからDocker buildを実行して結果をECRに保存、そのままECSタスクとしてプロダクション環境にデプロイなんて使い方をしている環境も多いと思うので、非常に多くの場面で使える方法と言えそうです。

2. ローカルキャッシュの利用

  • 概要
  • DockerイメージのレイヤやGitのメタデータをCodeBuildの実行ホスト環境内にキャッシュする事で実行時間短縮が期待できます。
    CodeBuildのローカルキャッシュには以下3つの種類が存在します。

    1. DockerLayerCache
    2. Buildフェーズなどで実行するDockerイメージのbuild/pull時の各レイヤをキャッシュしてイメージのビルドやDLを高速化します。
      Dockerイメージのbuildやpullは主にBuildフェーズなどで行う内容の為、実行時間が短縮されるフェーズも同様です。

    3. SourceCache
    4. ビルドに使用するソースコードを保存してあるGitリポジトリからDLしたメタデータをキャッシュして、次回以降のDLに前回DL時からの差分のみをDLできるようになります。
      GitリポジトリからDLしたメタデータをキャッシュするので、DOWNLOAD_SOURCEフェーズの実行時間が短縮されます。

    5. CustomCache
    6. buidspec.ymlのcache/pathsで指定したディレクトリ配下のパスに存在するファイル群がキャッシュされるようになります。

      buildspec.yml
      YAML
      1
      2
      3
      cache:
        paths:
          - './node_modules/**/*'

  • 使用条件
  • キャッシュの保存先がCodeBuildの実行ホスト環境内ということで、ビルドを実行するホスト環境が変わると当然キャッシュも消えてしまいます。
    ビルドを実行するホスト環境は指定できないので確実にキャッシュをヒットさせる事は難しいですが、一般的に前回のビルド実行時から時間を空けずに再度ビルドを実行すると同じホスト環境を使い回すと言われているので、短い時間内で複数回ビルドを実行するような使い方をしている場合にキャッシュのヒット率が高くなりそうです。
    同時に複数ビルド実行時にホスト環境がスケールアウトしたりもあるので、あくまでも参考程度です。

  • 使用方法
  • ビルドのアーティファクトから追加設定を選び、キャッシュタイプにローカルを選択、使用したいキャッシュを選択するだけです。

  • その他
  • CodeBuildのキャッシュにはローカルキャッシュ以外にS3を使用したキャッシュを利用する事もできますが、S3とのネットワーク転送時間分ローカルキャッシュを利用した方が高速な実行が可能です。
    ただし、使用条件にも記載した通り間隔を空けてビルドを実行する場合などにキャッシュのヒット率が低いデメリットもあるので、使用用途に応じてどちらのキャッシュタイプを使用するか選択する必要があります。
    キャッシュタイプがS3の場合には、Dockerのレイヤキャッシュが使用できない制約もあります。

CodeBuildのキャッシュ利用時はハマりポイントも多いので、使用する際はAWSの公式サイトの説明を読んで挙動を理解してから使うようにしましょう。

3. カスタムイメージを使用して、必要な各種ライブラリなどを予め使用可能にしておく

  • 概要
  • CodeBuildのINSTALLフェーズなどで毎回インストールしているビルド実行時に必要な各種ライブラリなどを環境イメージで予め用意しておく方法です。
    ビルド実行毎に毎回インストールし直す手間が省けるようになるので、INSTALL(ものによってはPRE_BUILD)フェーズ実行時間が短縮できます。

  • 使用条件
  • 環境イメージに使用する環境内に予め必要な内容を用意しておく必要があるので、必然的にカスタムイメージを使用している必要があります。

  • 使用方法
  • 長くなるので詳細は省略しますが、以下4ステップで使用可能にできます。

    1. 使用するカスタムイメージの用意
    2. まずは、CodeBuildで毎回インストールしていた必要なライブラリなどをインストール済のDockerイメージを作成します。

    3. 用意したカスタムイメージをECRにアップロード
    4. 作成したイメージをCodeBuildから使用する為にアップロードします。
      アップロード先はDockerHubなどでも可能ですが、アクセス時の権限制御やネットワーク速度などからECRにアップロードするのが便利です。

    5. ECRにCodeBuildからのアクセスを許可するポリシー追加
    6. ECRはリポジトリに対してポリシーを設定してアクセス制御を行うので、以下のようなポリシーを追加します。

      ZSH
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Effect": "Allow",
            "Principal":{
              "Service":"codebuild.amazonaws.com"
            },
            "Action":[
              "ecr:GetDownloadUrlForLayer",
              "ecr:BatchGetImage",
              "ecr:BatchCheckLayerAvailability"
            ]
          }
        ]
      }

    7. CodeBuildの環境イメージをカスタムイメージに上書き
    8. 作成したイメージを使用する為に、CodeBuildのビルドの環境からイメージの上書きを選び、イメージレジストリにECRを選択、ECRレポジトリ/イメージにアップロードしたECRイメージのレポジトリとイメージ名を選択します。

  • その他
  • マネージド型イメージからでもインストール可能なものが対象になるのでpipやwgetで用意するライブラリなどが対象になる事が多いですが、docker run(compose)で起動させているコンテナの実行イメージも予めカスタムイメージ内にpullしておくと実行時間の短縮ができそうです。
    管理がかなり面倒になるのでお勧めはできませんが…

ビルド実行時に使用する環境イメージの管理も自分でやらなければならなくなるので、そこはビルド実行時間の短縮幅と比較してのトレードオフでしょうか。
事前準備で大きく時間がかかっていてしまっているようであれば実行時間重視でカスタムイメージにするべきでしょうし、数秒程度しか短縮されないのであれば運用コストを重視してマネージド型イメージを使用しておくのが無難かと思います。

4. 環境イメージの最新化

  • 概要
  • ビルド実行時間短縮方法というよりは、急にビルド実行時間が大幅に長くなってしまった場合のトラブルシューティング的な短縮です。
    PROVISIONINGフェーズの実行時間が急激に増えてしまった場合の対応になる為、実行時間が短縮されるフェーズもPROVISIONINGフェーズです。

  • 使用条件
  • 自分で用意したカスタムイメージを使用している場合は該当しない為、環境イメージにAWSが用意したマネージド型のイメージを使用しているケースが該当します。

  • 使用方法
  • ビルドの環境からイメージの上書きを選び、マネージド型イメージで選択可能な最新バージョンのイメージを選択するだけです。

  • その他
  • 急にビルド実行時間のPROVISIONINGフェーズが長くなってしまった場合への対処法の一つという扱いになり、全ての場面で実行時間短縮になる訳ではないですが、短縮幅は大きいので一度試してみる価値はあると思います。

前回の記事にも書いた内容なので、詳細はそちらをご参照ください。

5. 使用するコンピューティングリソースの増強

  • 概要
  • 最もシンプルな方法で、CodeBuildのホスト環境のコンピューティングリソースをスケールアップして増強します。
    特定フェーズの短縮ではなく全フェーズに跨った実行時間短縮になりますが、コンピューティングリソースへの依存が大きいBUILDフェーズ周りが短縮幅が大きそうです。

  • 使用条件
  • どの環境でも使用可能です。

  • 使用方法
  • ビルドの環境から追加設定を選び、コンピューティングから使用したいリソース量を選択するだけです。

  • その他
  • お金で解決する方法なので、当然ですが利用料金は高くなってしまいます。
    CodeBuildにはコンピューティングインスタンスタイプがgeneral1.small(3 GB メモリ、2 vCPU)を選択時のみ無料枠の100分が付与されますが、コンピューティングリソースを増強するのはインスタンスタイプを変更する事でもあるので、変えた時点で無料枠が効かなくなる点にも注意が必要です。

    利用可能なコンピューティングインスタンスタイプの一覧とそれぞれの利用料金は、AWSの公式サイトからご確認ください。

身も蓋もないですが、お金で解決するのが一番ROIが高い場面はやはり多いですw

参考文献

  • docker buildを高速化!CodeBuildのローカルキャッシュ機能を試してみる
  • 【ビルド高速化!】AWS CodeBuildが次世代高速コンテナビルドのBuildKitをサポートしました

今回は以上です。

Tweet
このエントリーをはてなブックマークに追加
Pocket
LINEで送る

カテゴリー: AWS, CodeBuild タグ: AWS, CodeBuild, Docker

profile

profile_img Web系のソフトウェアエンジニアです。
野球観戦(横浜DeNAベイスターズ)、格闘ゲーム、カメラ、ランニング、愛犬、インテリア、美味しいものの食べ歩き、などなどが好き。

  • twitter MasakiMisawa
  • facebook MisawaMasaki
  • github MasakiMisawa
  • instagram masakimisawa
  • follow us in feedly

search

recent entry

  • M1 MacでAppleシリコンとIntelプロセッサのバイナリ管理を分離して共存させる
  • M1 MacでtfenvからTerraform1.0.2未満のダウンロードに失敗する問題を無理矢理解決する
  • GitHub ActionsからAWS利用時に永続的クレデンシャル情報を渡さないようにする
  • TerraformでAuroraのエンジンバージョンアップグレードをする時は、対象リソースをクラスターだけに絞る
  • CloudWatch Logsに出力されたエラーログ本文のSlackへの転送

category

  • AWS (17)
    • ACM (1)
    • AWS CLI (1)
    • Chatbot (2)
    • CloudWatchAlarm (1)
    • CloudWatchLogs (1)
    • CodeBuild (3)
    • DynamoDB (1)
    • IAM (1)
    • Kinesis (2)
    • Lambda (5)
    • OpenId Connect (1)
    • RDS (1)
    • S3 (2)
    • SNS (2)
    • SSM (2)
    • STS (1)
  • CI (2)
  • GCP (1)
    • PageSpeedInsights (1)
  • Git (3)
    • GitHub (2)
      • GitHub Actions (1)
  • M1 Mac (2)
  • Python (2)
  • Redis (1)
  • selenium (1)
  • Slack (3)
  • Terraform (3)
  • その他 (1)

archive

  • 2022年2月 (3)
  • 2021年1月 (1)
  • 2020年12月 (1)
  • 2020年11月 (1)
  • 2020年9月 (2)
  • 2020年8月 (1)
  • 2020年7月 (1)
  • 2020年6月 (1)
  • 2020年5月 (2)
  • 2020年4月 (1)
  • 2020年3月 (1)
  • 2020年1月 (1)
  • 2019年1月 (1)
  • 2017年12月 (1)
  • 2017年9月 (1)
  • 2017年8月 (1)
  • 2017年7月 (1)
  • 2017年2月 (1)
  • 2016年10月 (1)

tag cloud

ACM Aurora AWS AWS CLI Billing CI CloudWatchAlarm CloudWatch Logs CodeBuild Code Format Docker DynamoDB EC2 env find firehose Git GitHub GitHub Actions Homebrew husky IAM Role Java kinesis KinesisFirehose Lambda lint-staged M1 Mac Node.js OpenId Connect PHP Python RDS Redis RI S3 Selenium Slack SNS SSM Terraform tfenv セッションマネジャー リモートワーク 生産性

Copyright © 2023 public memo.