https://github.com/dybooksIT/k8s-aws-book
클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트를 공부하던 중 docker image build에 실패해 관련 오류를 해결하다 다른 분들께 도움이 될 수 있도록 해결 과정을 공유하고자 합니다.
p.78 전까지 잘 따라오셨다면 spring boot 프로젝트를 .jar 파일로 빌드하셨을겁니다.
그러면 이 jar 파일을 이용해서 docker image build를 할 차례입니다.
sudo docker build -t k8sbook/backend-app:1.0.0 --build-arg \
JAR_FILE=build/libs/backend-app-1.0.0.jar .
그래서 docker image build하면, 문제가 생깁니다.
[+] Building 0.8s (2/3)
[+] Building 0.8s (3/3) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 37B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> ERROR [internal] load metadata for docker.io/library/amazoncorretto:1 0.7st
------
> [internal] load metadata for docker.io/library/amazoncorretto:11:
------
failed to solve with frontend dockerfile.v0: failed to create LLB definition: rpc error: code = Unknown desc = error getting credentials - err: exit status 1, out: ``
이러한 오류 메시지를 보게 될 확률이 높습니다.
제 실행 환경은 다음과 같습니다.
OS: Apple M1 Pro, MacOS Ventura 13.2.1
Docker Engine: v20.10.22
이러한 오류는 buildkit과 관련된 오류입니다.
buildkit은 docker에서 legacy builder를 대체하는 발전된 백엔드 빌더입니다.
오류 메시지를 보시면 frontend, LLB와 같은 단어를 볼 수 있는데요.
LLB(Low-Level-Build): LLB는 개발자가 BuildKit을 확장할 수 있는 중간 바이너리 형식이다. LLB는 매우 복잡한 빌드 정의를 구성하는 데 사용할 수 있는 콘텐츠 주소 지정 가능한 종속성 그래프를 정의합니다.
Frontend: 프론트엔드는 사람이 읽을 수 있는 빌드 형식을 사용하여 LLB로 변환하여 BuildKit이 실행할 수 있는 구성 요소입니다. 프론트엔드는 이미지로 배포될 수 있으며, 사용자는 정의에 의해 사용되는 기능에 대해 작동하도록 보장된 특정 버전의 프론트엔드를 타겟팅할 수 있습니다.
이 오류는 buildkit을 이용하는 과정에서 생긴 오류입니다.
따라서 단기적으로는 buildkit을 사용하지 않고 legacy builder를 사용함으로써 해결될 수 있습니다.
buildkit 대신 legacy builder를 사용하는 방법은 다음과 같습니다.
docker engine 설정에 가셔서 buildkit : true 에서 false로 바꿔주시면 됩니다.
그 후 다시 빌드를 시도하면 성공하게 됩니다.
2023/03/01 13:11:49 must use ASL logging (which requires CGO) if running as root
Sending build context to Docker daemon 54.3MB
Step 1/9 : FROM amazoncorretto:11
11: Pulling from library/amazoncorretto
71343c279119: Pull complete
4e2f94ae4821: Pull complete
Digest: sha256:855f474f4247018ce1461bab1619b5147c01e436e542a6ab16176bf50661b8ff
Status: Downloaded newer image for amazoncorretto:11
---> dd7aaf50ad7a
Step 2/9 : RUN yum install -y glibc-langpack-ko
---> Running in 37c9fecfaf56
Loaded plugins: ovl, priorities
8 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package glibc-langpack-ko.aarch64 0:2.26-62.amzn2 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
glibc-langpack-ko aarch64 2.26-62.amzn2 amzn2-core 329 k
Transaction Summary
================================================================================
Install 1 Package
Total download size: 329 k
Installed size: 2.5 M
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : glibc-langpack-ko-2.26-62.amzn2.aarch64 1/1
Verifying : glibc-langpack-ko-2.26-62.amzn2.aarch64 1/1
Installed:
glibc-langpack-ko.aarch64 0:2.26-62.amzn2
Complete!
Removing intermediate container 37c9fecfaf56
---> 14cdb923b03b
Step 3/9 : ENV LANG ko_KR.UTF8
---> Running in 0bb43effdbc1
Removing intermediate container 0bb43effdbc1
---> 8d999a3b4c7c
Step 4/9 : ENV LC_ALL ko_KR.UTF8
---> Running in 763d2471ffde
Removing intermediate container 763d2471ffde
---> b9d3c14e2f9b
Step 5/9 : RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
---> Running in d3ff218c0d2f
Removing intermediate container d3ff218c0d2f
---> 60b8c1881f6b
Step 6/9 : VOLUME /tmp
---> Running in ee128a14d435
Removing intermediate container ee128a14d435
---> f002c6e5c2cc
Step 7/9 : ARG JAR_FILE
---> Running in 9e9b76911d59
Removing intermediate container 9e9b76911d59
---> 96a79fafd220
Step 8/9 : COPY ${JAR_FILE} app.jar
---> a75ebf35dd9d
Step 9/9 : ENTRYPOINT ["java", "-verbose:gc", "-Xlog:gc*:stdout:time,uptime,level,tags", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
---> Running in dff2edf347b8
Removing intermediate container dff2edf347b8
---> cf537138ea5b
Successfully built cf537138ea5b
Successfully tagged k8sbook/backend-app:1.0.0
다만 이는 완전한 해결책은 아니며 결국 앞으로 buildkit이 더 널리 쓰일 것이므로 buildkit의 추후 업데이트로 오류가 해결되거나 buildkit에 맞춰 Dockerfile을 수정하는 등의 대책이 필요합니다.
저희는 책을 보고 예제를 따라하는 것이 중요하므로 legacy builder를 이용하여 빌드하고 넘어가도 충분할 것 같습니다.
해결하는데 생각보다 오래 걸려서 다른 분들은 이슈를 보고 빨리 넘어가길 바라는 마음에서 이슈를 올려봅니다.
(저를 포함한) 쿠버네티스 초심자 분들에게 컨테이너의 가호가 함께하길 빌겠습니다.
좋은 하루 되세요!
깃헙 이슈
https://github.com/dybooksIT/k8s-aws-book/issues/8
추가 내용
이대로 빌드하면 pod에서 이미지를 기반으로 컨테이너를 생성하는 데 실패하게 됩니다.
pod 상태는 다양할 수 있는데, 에러가 난 상태일 수도 있고, 계속 재시도하는 상태일 수도 있습니다.
예제에서는 imagePullPolicy가 always로 설정되어 있기 때문에 계속 재시도하게 됩니다.
다만 쿠버네티스 기본 설정상 연속 실패할수록 재시도 시간은 점점 늦춰지게 됩니다.
이 때 컨테이너의 로그를 찍어보면 다음과 같이 출력됩니다.
kimjinyeon@kimjinyeonui-MacBookPro backend-app % kubectl logs -f backend-app-9cd598bc6-ht5h2
exec /usr/bin/java: exec format error
java를 실행하지 못해서 생기는 오류인데요.
[
{
"Id": "",
"RepoTags": [
"usernumber.dkr.ecr.ap-northeast-2.amazonaws.com/k8sbook/backend-app:1.0.0",
"k8sbook/backend-app:1.0.0"
],
"RepoDigests": [
"usernumber.dkr.ecr.ap-northeast-2.amazonaws.com/k8sbook/backend-app@sha256:898cbcd65344de57003228fb76761f1ef133a7be0c0c146fd6f770e42703bd38"
],
"Parent": "",
"Comment": "",
"Created": "2023-03-02T04:38:04.15837418Z",
"Container": "f08546ff4e1d9fdea9d87c77ecf45c91fad136d35e0396a375e4ca8cea193c32",
"ContainerConfig": {
"Hostname": "f08546ff4e1d",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=ko_KR.UTF8",
"JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto",
"LC_ALL=ko_KR.UTF8"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"ENTRYPOINT [\"java\" \"-verbose:gc\" \"-Xlog:gc*:stdout:time,uptime,level,tags\" \"-Djava.security.egd=file:/dev/./urandom\" \"-jar\" \"/app.jar\"]"
],
"Image": "",
"Volumes": {
"/tmp": {}
},
"WorkingDir": "",
"Entrypoint": [
"java",
"-verbose:gc",
"-Xlog:gc*:stdout:time,uptime,level,tags",
"-Djava.security.egd=file:/dev/./urandom",
"-jar",
"/app.jar"
],
"OnBuild": null,
"Labels": {
"maintainer": "k8sbook"
}
},
"DockerVersion": "20.10.22",
"Author": "",
"Config": {
"Hostname": "",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=ko_KR.UTF8",
"JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto",
"LC_ALL=ko_KR.UTF8"
],
"Cmd": null,
"Image": "",
"Volumes": {
"/tmp": {}
},
"WorkingDir": "",
"Entrypoint": [
"java",
"-verbose:gc",
"-Xlog:gc*:stdout:time,uptime,level,tags",
"-Djava.security.egd=file:/dev/./urandom",
"-jar",
"/app.jar"
],
"OnBuild": null,
"Labels": {
"maintainer": "k8sbook"
}
},
"Architecture": "arm64",
"Variant": "v8",
"Os": "linux",
"Size": 765460261,
"VirtualSize": 765460261,
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/74f19483af4e73508cf941fbe39c84a183fd2103d1f76cbb398074b0ada3ea77/diff:/var/lib/docker/overlay2/324e4f0bf5dc83f842d97054b1a4af23d79255275f594a49240b30d1ac79e3cf/diff:/var/lib/docker/overlay2/c4961a7e3c86505a1195f59685fd3bb306e30470baf5d8721af66bc43a9c7795/diff:/var/lib/docker/overlay2/00cac4fe769a58b90618c3f2e2170ba89d163f707dda6649504df50b314f60c0/diff",
"MergedDir": "/var/lib/docker/overlay2/0d30bf7afaad884ece15bc1848c2a1b4384299b341573c0f5fae23da2007c113/merged",
"UpperDir": "/var/lib/docker/overlay2/0d30bf7afaad884ece15bc1848c2a1b4384299b341573c0f5fae23da2007c113/diff",
"WorkDir": "/var/lib/docker/overlay2/0d30bf7afaad884ece15bc1848c2a1b4384299b341573c0f5fae23da2007c113/work"
},
"Name": "overlay2"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:1d636628b9ab697e1aad4b6343eae0df5bdd2cf19341d798737dfc7384a038f0",
"sha256:b99f8756b00f04efbbad0488fa71e0b85933bb1a1e115fcd26f18a570d5f677f",
"sha256:3702e145894424cd52e6e97b8b959b70ab0a6059dc215d306e39a8c784a90577",
"sha256:0c6a5701062654b19fc83995a4905a4c64c83ed3633c5d2a109ae7bf1a55578e",
"sha256:e714ba4b47e2b2a51c9e365613b5c9b78b6df77cb76035fe6f98c254206cfb0d"
]
},
"Metadata": {
"LastTagTime": "2023-03-02T04:43:51.877340508Z"
}
}
]
image를 검사해보면 다음과 같은 내용을 볼 수 있고, 중요한 건 "Architecture": "arm64" 부분입니다.
apple sillicon의 경우에는 arm architecture를 채택하고 있는데, EC2에서 리눅스 기반 OS를 선택하면 amd architecture가 선택되게 됩니다.
두 가지는 기본적으로는 호환되지 않기 때문에, 오류가 나게 됩니다.
이 경우에는 로컬(macOS)에서 컨테이너 이미지를 생성할 때, 이를 맞춰서 빌드해주면 됩니다.
기존 코드
docker build -t k8sbook/backend-app:1.0.0 --build-arg \
JAR_FILE=build/libs/backend-app-1.0.0.jar .
변경된 코드
docker buildx build --platform=linux/amd64 -t k8sbook/backend-app:1.0.0 --build-arg \
JAR_FILE=build/libs/backend-app-1.0.0.jar .
buildx의 경우 buildkit 기반으로 docker에서 제공하는 크로스 플랫폼 이미지 빌드 툴입니다.
buildx를 이용하면 arm64에서도 amd64에서 동작하는 이미지를 만들 수 있습니다.
buildx에 대해서는 도커 문서를 참고하시길 바랍니다.
https://docs.docker.com/engine/reference/commandline/buildx/
추가로, 문제를 해결하는 데 있어서 아래의 블로그가 도움이 되었습니다.
https://appleg1226.tistory.com/35
평소에 자주 보던 블로그인데, 이번에는 검색해서 찾게 되어 반가웠습니다.
EKS 배포 오류 뿐만 아니라 다른 글도 좋은 내용이 많으니 혹시라도 제 글을 보셨다면 이 분의 블로그도 참고해주시면 좋을 것 같습니다.
'개발 - Coding > Infra' 카테고리의 다른 글
네트워크 영역에서의 NAT와 AWS NAT Gateway: 1편 (0) | 2023.06.16 |
---|---|
클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트 p.92 오류 해결 (0) | 2023.03.03 |
도커 컨테이너의 생애주기와 조작 실습 (4) | 2023.01.12 |
도커 이미지와 컨테이너 (0) | 2022.12.11 |
도커(Docker) 개요 (1) | 2022.12.11 |