カスタムイメージを使ってCodebuildでbuildするまで。


マニュアル見ろよ、という話しではあるんだが。
私はなんか突っかかるまでマニュアル読まないタイプの人なので。

やりたかったこと

  • マネージドイメージ内でカスタムイメージをビルド。ビルドしたイメージをECRにPush
  • カスタムイメージ内で、golangのpackeageをビルド。ビルドした生成物をS3にアップロード

カスタムイメージの作成まで

DOWNLOAD_SOURCEでi/o timeout for primary source

GitHubへのoAuth設定をCodeBuildから行うと、こんなエラーが出る。GitHub側で問題おきていることは考えにくいので、CodeBuild側の問題。

CLIENT_ERROR: Get https://github.com/XXXXXXXXXXX/sample.git/info/refs?service=git-upload-pack:
 dial tcp 13.114.40.48:443: i/o timeout for primary source

CodeBuildはVPC内に設定してあり、NAT-Gateway経由でGitHubに接続しているのだが、そこが問題だろう。13.114.40.48はGithub.comのIPv4アドレスなので、DNS変換は出来ているが、git cloneで問題が起きているようだ。

対応

SecurityGroupの指定に問題あったようで、SGに何らかのインバウンド許可をつけることでNATを通過し通信が届くようになった。
※以下codebuidに付与したSGのインバウントに3389ポートを許可し、ビルドした際のcodebuildのログ
YAML_FILE_ERROR: YAML file does not exist
この時点でカスタムイメージを作成するためのbuildspec.yamlはまだ作成してなかったので想定通りなのだが、接続部分で既にエラーが起きるというのは先が思いやられる…。

余談

CodeBuildのDOWNLOAD_SOURCEフェーズではログが出ないため、原因を切り分けるのに大変分かりにくい。せめてbashが使えればもっと早く解決できるのに…。

INSTALLでCOMMAND_EXECUTION_ERROR

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-docker-custom-image.html
を参考にしながら流用しつつそれっぽくyaml作って再実行してみるとまたエラー

COMMAND_EXECUTION_ERROR: Error while executing command: timeout 15 sh -c "until docker info; do echo .; sleep 1; done". Reason: exit status 124

ログを見るとこんなエラーが出てるなあ。Dockerが動いてない。

Server:
ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
errors pretty printing info
.
time="2020-06-05T05:53:33.864814126Z" level=info msg="Starting up"
time="2020-06-05T05:53:33.903326219Z" level=warning msg="could not change group /var/run/docker.sock to docker: group docker not found"
time="2020-06-05T05:53:33.903422360Z" level=warning msg="[!] DON'T BIND ON ANY IP ADDRESS WITHOUT setting --tlsverify IF YOU DON'T KNOW WHAT YOU'RE DOING [!]"

対応

「特権付与」が必要。

このビルドプロジェクトを使用して Docker イメージをビルドするため、[Privileged] を選択します
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-docker.html

よく読めば書いてはあるんだよ。あるんだけど、わかりにくいよねえ。

「環境」の箇所から上記をチェック

PRE_BUILDでCOMMAND_EXECUTION_ERROR

一歩進んで二歩下がる?

COMMAND_EXECUTION_ERROR: Error while executing command: $(aws ecr get-login --no-include-email). Reason: exit status 255

対応

CodeBuildに権限足りてない。

今度はIAMかよ。

BUILD/POST BUILDでCOMMAND_EXECUTION_ERROR

ECRにリポジトリも作成し、さてそろそろ完成かな、と思ったらやっぱりエラー。
本当に一歩ずつだな!

COMMAND_EXECUTION_ERROR: Error while executing command: docker build -t XXX-build .. Reason: exit status 1
COMMAND_EXECUTION_ERROR: Error while executing command: docker push ${REPOSITORY_URI}:latest. Reason: exit status 1

対応

buildspec.ymlをどこぞから流用して作ったんだけど、

buildspec.yml
  build:
    commands:
      - docker build -t XXX-build .
      - docker tag XXX-build:latest ${REPOSITORY_URI}:latest

XXX-buildの部分ってECRのリポジトリの部分と一致していないとダメなのか。そうなのかー。あんまり気づいておらず、適当に修正してしまっていた。

ECRの当該リポジトリのプッシュコマンドをちゃんと見て、それとbuildspec.ymlを合わせないとうまく動作しないね!

BUILDでCOMMAND_EXECUTION_ERROR - take2

ちょっと進んだけどやっぱりエラー。しかもExitStatusは一緒…。わけわからん。

COMMAND_EXECUTION_ERROR: Error while executing command: docker build -t custom-image-build .. Reason: exit status 1

対応

これ元々こんな感じのシェルをDockerfileから呼び出してRedisをインストールするようにしていたのだけど(これもどこぞから流用した)、redis-5.0.4-1.el7このパッケージがもうないんだよね。他にもこういうのに悩まされた。

install.sh
#!/bin/sh

# 必要なリポジトリの有効化
yum -y install epel-release
yum -y install wget
wget http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
rpm -Uvh remi-release-7.rpm
yum-config-manager --enable epel epel-release remi remi-release

# Redisのインストール
yum -y install --enablerepo=epel,remi redis-5.0.4-1.el7.remi.x86_64

CodeBuildにこんなログ出てはいるんだけど、完全に見落としてて、ずっと他の部分を調査してた。

Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: d36uatko69830t.cloudfront.net
 * epel: d2lzkl7pfhq30w.cloudfront.net
 * extras: d36uatko69830t.cloudfront.net
 * remi: ftp.riken.jp
 * remi-safe: ftp.riken.jp
 * updates: d36uatko69830t.cloudfront.net
No package redis-5.0.4-1.el7.remi.x86_64 available.

No packageとかNot Foundとかを見逃さないこと。ErrorとかWarning表記になってないので、ちゃんとログを見ないとわからない。

余談

CodebuildのExit status一覧どこにあるのよマジで。ちらっと探しただけだと見つからないし。

カスタムイメージを用いたビルドまで。

pull access denied

buildspec.ymlを適当にかいてCodebuildで動作させてみると、PROVISIONINGでエラーが出る。

BUILD_CONTAINER_UNABLE_TO_PULL_IMAGE: Unable to pull customer's container image. 
CannotPullContainerError: Error response from daemon: pull access denied for 
XXXXXXXXXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/custom-docker-image, repository does not exist or may require 'docker login'

docker login?特権権限がないから?、と思って再度やってみてもやっぱりエラーが出る。そこまで安易じゃなかった。

対応

[アクション] で、プル専用アクションとして [ecr:GetDownloadUrlForLayer]、[ecr:BatchGetImage]、および [ecr:BatchCheckLayerAvailability] を選択します。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/sample-ecr.html

ECRにCodebuildからpullできる権限付与が必要なのである。CodeBuildからECRにアクセスする権限も必要だし、なんか色々めんどいな。

PRE_BUILDでCOMMAND_EXECUTION_ERROR

まあ上記を修正しても当然のようにエラー。

COMMAND_EXECUTION_ERROR: Error while executing command: make setup. Reason: exit status 127

ログは…(流石にログの見方も段々慣れてきた。)

[Container] 2020/06/09 02:43:58 Running command make setup
/codebuild/output/tmp/script.sh: line 4: make: command not found

はあ。make入ってないですか。そうですか。そうですね。インストールしなきゃね。

対応

カスタムイメージ側に以下の対処。BuildしてECRに再PUSH

yum -y install gcc
yum -y install make

PRE_BUILDでCOMMAND_EXECUTION_ERROR - take2

またかよ!Status変わってるし。

COMMAND_EXECUTION_ERROR: Error while executing command: make setup. Reason: exit status 2

ログを見ると

golint -set_exit_status ./...
make: golint: Command not found
make: *** [lint] Error 127

あーもう。PATHが通ってない。
というわけでhttps://github.com/golang/lint を参考にどこにインストールされているか調べてみると、

go list -f {{.Target}} golang.org/x/lint/golint
/codebuild/output/src813842990/bin/golint

ここである。$GOPATHが/codebuild/output/src813842990を指していたので、その下にPATHを通せばよいことが判明。

対応

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/build-spec-ref.html
じゃあ上記を参考にbuildspec.ymlのenvシーケンスに書けばいいのね?と思ったら、envシーケンス内はリテラルになるため変数展開できないことが判明。
マニュアルに書いとけよ。読んでも分かんないよ。

つまり、

buildspec.yml
env:
  variables:
    PATH: ${GOPATH}/bin:${PATH}

は駄目で、↓のようにする必要がある。

buildspec.yml
  pre_build:
    commands:
      - export PATH=${GOPATH}/bin:${PATH} && echo ${PATH}

これで完了!やったね!
ってS3アップロードまで出来てない気がする。もう疲れた。

結論

FAQに入れとけよと思うよマジで。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/troubleshooting.html