こんにちは、ロジカル・アーツの井川です。
CodeBuild でのビルドがうまくいかない際に、逐一 buildspec ファイルを修正して再ビルドして結果を確認して...というのは面倒ですよね?実は、CodeBuild では実行中のビルドを一時停止してビルドコンテナに接続できる方法があります。
はじめに
Session Manager を使用することで、実行中のビルドコンテナに接続し操作することができます。これにより、エラーが発生する直前でビルドを中断し、接続してその時の状況を確認したりできます。
この記事では CodePipeline に組み込まれた既存の CodeBuild プロジェクトを扱います。また、パイプラインのソースアクションプロバイダとして CodeCommit を使用しています*1。
デバッグにあたって必要な設定は主に以下の二つです。
ただし、カスタムイメージを使用している場合は SSM Agent のインストールや設定が必要だったりしますので、詳しくは以下のリンクを参照してください。
-
CodeBuild のサービスロールに以下のポリシーを追加する
{ "Effect": "Allow", "Action": [ "ssmmessages:CreateControlChannel", "ssmmessages:CreateDataChannel", "ssmmessages:OpenControlChannel", "ssmmessages:OpenDataChannel" ], "Resource": "*" }
- buildspec ファイルのビルドを一時停止したい箇所に
codebuild-breakpointコマンドを追加する
準備
CodeBuild のマネジメントコンソールからデバッグしたいビルドプロジェクトの詳細画面に行き、「上書きでビルドを開始する」をクリックします。

「高度なビルドの上書き」をクリックします。

「ソースプロバイダ」が CodePipeline だと実行できないようなので、パイプラインのソースアクションプロバイダを直接指定します。

「セッション接続の有効化」にチェックを入れます。
サービスロールに「はじめに」で述べたポリシーがアタッチされていない場合は別途追加しておきます。もしくは画像の青枠の「AWS CodeBuild にこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にする」にチェックを入れると当該ポリシーを含むポリシーがアタッチされます。(ただし、不要な権限もアタッチされる可能性があります。)

「ビルドコマンドの挿入」を選択し、「エディタに切り替え」をクリックします。(以下の画像はクリック後のものです。)
ビルドコマンドに buildspec ファイルの中身を貼り付け、ビルドを一時停止したい箇所に codebuild-breakpoint を追加します。

その後、一番下までスクロールし「ビルドを開始」をクリックします。
ビルドが開始してしばらく待つとビルドログに以下のようなメッセージが表示されます。

ビルドステータスに Session Manager のリンクが表示されています。このリンクをクリックするとビルドコンテナに接続できます。

デバッグ
この記事の設定だとビルドが失敗し、ビルドログに以下のメッセージが記録されていました。
Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: sam build --use-container --template ${SAM_TEMPLATE}. Reason: exit status 1
もう少し上のログを確認すると
Error: We do not support building .NET Core Lambda functions within a container. Try building without the container. Most .NET Core functions will build successfully.
と書いてあるので、sam build --use-container --template ${SAM_TEMPLATE} から --use-container を除いてうまくいくか試してみます。
上述したように、Session Manager へのリンクをクリックしてビルドコンテナに接続したら、sam build --template ${SAM_TEMPLATE} を実行してみます。

ビルドに失敗しました。
.NET のバージョンが古い(3.1.426)ようなので、.NET 6 をインストールします。ビルドイメージは aws/codebuild/amazonlinux2-x86_64-standard:3.0 を使用していますが、既に .NET のインストーラーが存在しているのでこれを利用します。
/usr/local/bin/dotnet-install.sh --channel lts を実行し、.NET のバージョンが 6 になったことが確認できました。

再度 sam build --template ${SAM_TEMPLATE} を実行してみます。

今度は成功しました!
ビルドを再開したいときは、コンテナシェル(上記の Session Manager で接続した画面)で codebuild-resume を実行します。もうビルドを続行する必要が無い場合は、「ビルドの停止」をクリックします(以下の画像参照)。

さて、sam build の --use-container オプションを削除し、.NET のバージョンを更新すればよいことが分かったので、ソースコードを編集し、CodeCommit にプッシュしてみます。
最後までパイプラインが実行されました!

おわりに
上で見たように、ログから確認できること以外にもビルドが失敗する原因が潜んでいたりするので、デバッグすることで修正を繰り返す手間を小さくできます。なお、注意点として、ビルドを一時停止している間も課金されるので、デバッグが終わったら codebuild-resume でビルドを再開するか、ビルドを停止してしまいましょう。