マニュアル見ろよ、という話しではあるんだが。
私はなんか突っかかるまでマニュアル読まないタイプの人なので。
やりたかったこと
- マネージドイメージ内でカスタムイメージをビルド。ビルドしたイメージを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に権限足りてない。
- デフォルトではECRのポリシーは設定されていない。
- 自分で設定を追加する必要がある
- IAMでロールに
AmazonEC2ContainerRegistryPowerUser
(ECRの操作を許可する)ポリシーをアタッチ
https://qiita.com/icck/items/bcf118a38c2a691a837d#2%E3%83%93%E3%83%AB%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%83%AD%E3%83%BC%E3%83%AB%E3%81%ABecr%E3%82%92%E6%93%8D%E4%BD%9C%E3%81%99%E3%82%8B%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E5%BF%85%E8%A6%81%E3%81%8C%E3%81%82%E3%82%8B
今度は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をどこぞから流用して作ったんだけど、
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
このパッケージがもうないんだよね。他にもこういうのに悩まされた。
#!/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シーケンス内はリテラルになるため変数展開できないことが判明。
マニュアルに書いとけよ。読んでも分かんないよ。
つまり、
env:
variables:
PATH: ${GOPATH}/bin:${PATH}
は駄目で、↓のようにする必要がある。
pre_build:
commands:
- export PATH=${GOPATH}/bin:${PATH} && echo ${PATH}
これで完了!やったね!
ってS3アップロードまで出来てない気がする。もう疲れた。
結論
FAQに入れとけよと思うよマジで。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/troubleshooting.html