前回に引き続き、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に記述しておくのが管理的にも楽でしょうか。
1 2 3 |
env: variables: DOCKER_BUILDKIT: "1" |
ビルド高速化ではないですが、BuildKitには鍵ファイルなどを削除する前のレイヤが残ってしまう問題を解消するSecret/SSH Mountの導入など、セキュアビルド観点でも嬉しい変更が多々入っているのでデフォルトで有効化しておいても良いと思います。
詳しくは同プロジェクトのメンテナでもいらっしゃる方のスライドをご参照ください。
コンテナ全盛のご時世、定義したDockerfileとGitリポジトリにpushした最新のソースコードを元にCodeBuildからDocker buildを実行して結果をECRに保存、そのままECSタスクとしてプロダクション環境にデプロイなんて使い方をしている環境も多いと思うので、非常に多くの場面で使える方法と言えそうです。
2. ローカルキャッシュの利用
- 概要
- DockerLayerCache
- SourceCache
- CustomCache
- 使用条件
- 使用方法
- その他
DockerイメージのレイヤやGitのメタデータをCodeBuildの実行ホスト環境内にキャッシュする事で実行時間短縮が期待できます。
CodeBuildのローカルキャッシュには以下3つの種類が存在します。
Buildフェーズなどで実行するDockerイメージのbuild/pull時の各レイヤをキャッシュしてイメージのビルドやDLを高速化します。
Dockerイメージのbuildやpullは主にBuildフェーズなどで行う内容の為、実行時間が短縮されるフェーズも同様です。
ビルドに使用するソースコードを保存してあるGitリポジトリからDLしたメタデータをキャッシュして、次回以降のDLに前回DL時からの差分のみをDLできるようになります。
GitリポジトリからDLしたメタデータをキャッシュするので、DOWNLOAD_SOURCEフェーズの実行時間が短縮されます。
buidspec.ymlのcache/pathsで指定したディレクトリ配下のパスに存在するファイル群がキャッシュされるようになります。
1 2 3 |
cache: paths: - './node_modules/**/*' |
キャッシュの保存先がCodeBuildの実行ホスト環境内ということで、ビルドを実行するホスト環境が変わると当然キャッシュも消えてしまいます。
ビルドを実行するホスト環境は指定できないので確実にキャッシュをヒットさせる事は難しいですが、一般的に前回のビルド実行時から時間を空けずに再度ビルドを実行すると同じホスト環境を使い回すと言われているので、短い時間内で複数回ビルドを実行するような使い方をしている場合にキャッシュのヒット率が高くなりそうです。
同時に複数ビルド実行時にホスト環境がスケールアウトしたりもあるので、あくまでも参考程度です。
ビルドのアーティファクトから追加設定を選び、キャッシュタイプにローカルを選択、使用したいキャッシュを選択するだけです。
CodeBuildのキャッシュにはローカルキャッシュ以外にS3を使用したキャッシュを利用する事もできますが、S3とのネットワーク転送時間分ローカルキャッシュを利用した方が高速な実行が可能です。
ただし、使用条件にも記載した通り間隔を空けてビルドを実行する場合などにキャッシュのヒット率が低いデメリットもあるので、使用用途に応じてどちらのキャッシュタイプを使用するか選択する必要があります。
キャッシュタイプがS3の場合には、Dockerのレイヤキャッシュが使用できない制約もあります。
CodeBuildのキャッシュ利用時はハマりポイントも多いので、使用する際はAWSの公式サイトの説明を読んで挙動を理解してから使うようにしましょう。
3. カスタムイメージを使用して、必要な各種ライブラリなどを予め使用可能にしておく
- 概要
- 使用条件
- 使用方法
- 使用するカスタムイメージの用意
- 用意したカスタムイメージをECRにアップロード
- ECRにCodeBuildからのアクセスを許可するポリシー追加
- CodeBuildの環境イメージをカスタムイメージに上書き
- その他
CodeBuildのINSTALLフェーズなどで毎回インストールしているビルド実行時に必要な各種ライブラリなどを環境イメージで予め用意しておく方法です。
ビルド実行毎に毎回インストールし直す手間が省けるようになるので、INSTALL(ものによってはPRE_BUILD)フェーズ実行時間が短縮できます。
環境イメージに使用する環境内に予め必要な内容を用意しておく必要があるので、必然的にカスタムイメージを使用している必要があります。
長くなるので詳細は省略しますが、以下4ステップで使用可能にできます。
まずは、CodeBuildで毎回インストールしていた必要なライブラリなどをインストール済のDockerイメージを作成します。
作成したイメージをCodeBuildから使用する為にアップロードします。
アップロード先はDockerHubなどでも可能ですが、アクセス時の権限制御やネットワーク速度などからECRにアップロードするのが便利です。
ECRはリポジトリに対してポリシーを設定してアクセス制御を行うので、以下のようなポリシーを追加します。
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" ] } ] } |
作成したイメージを使用する為に、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
参考文献
今回は以上です。