เรื่องของเรื่องก็มีอยู่ว่า … ผมมี Container Image เก็บอยู่บน Docker Hub ส่วนใหญ่ก็จะเป็นเครื่องมือในการทำโน่นนี่นั่น เช่น curl, dig, ansible หรือจำพวก application ที่เอาไว้ทดสอบในกรณีต่าง ๆ … ตัวที่มีอายุมากที่สุด ก็น่าจะประมาณ 3 ปีที่เริ่มสร้าง image เองมาทดสอบ มันก็เป็นอย่างนั้นมาตลอด ไม่เคยมีปัญหาอะไร แต่ว่า 2-3 วันนี้ก็นึกว่า จะเอาเครื่องมือหลาย ๆ ตัวมาร่วมกันไว้ใน image เดียว เวลาเรียกใช้งาน ทดสอบบางอย่างเล็ก ๆ น้อย ๆ ก็ใช้ตัวนี้ตัวเดียวพอ ก็เลยเริ่มจากเอา curl, ip, bash และ dig รวมกันไว้เป็นตัวเดียวโดยใช้ Base Image เป็น Alpine
FROM alpine
RUN apk add --update --no-cache curl iputils bash bind-tools
เริ่ม Build Container Image
ก็ปกติเลยครับ ใช้ Docker Desktop ที่ติดตั้งบน laptop ตัวเอง เรียกคำสั่ง docker build
เหมือนเดิมอย่างที่เคยทำ ตัวนี้ก็เลยตั้งชื่อ image ว่า utils และ tag เป็น r23.03 แล้วก็ push มันไปเก็บไว้บน Repository ของผมบน Docker Hub
d8k-a2m2 util > docker build -t damrongsak/utils:r23.03 --no-cache .
[+] Building 4.1s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 122B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 1.1s
=> CACHED [1/2] FROM docker.io/library/alpine@sha256:ff6bdca1701f3a8a67e 0.0s
=> [2/2] RUN apk add --update --no-cache curl iputils bash bind-tools 2.9s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:fe062658040d7049a108524ff891d3ee7ad4971d7d00a 0.0s
=> => naming to docker.io/damrongsak/utils:r23.0
d8k-a2m2 util > docker push damrongsak/utils:r23.03
The push refers to repository [docker.io/damrongsak/utils]
a8f481f3c96c: Pushed
edf70074bd40: Layer already exists
r23.03: digest: sha256:d24a5d581fb91db2e4b5f1c51f16dd263fa78024a4b542e272d86f8602062dbc size: 738
ทดสอบสร้าง container จาก image
ก่อนเอาไปใช้งานก็ทดสอบกันก่อนว่าใช้งานได้ตามปกติ ก็ใช้คำสั่ง docker container run
ลองเรียกคำใช้คำสั่ง curl และ dig ใน container ก็ใช้งานได้ปกติดี ได้ผลอย่างที่คาดไว้
d8k-a2m2 util > docker container run --rm damrongsak/utils:r23.03 curl -sI https://blog.d8k.io
HTTP/1.1 200 OK
Server: nginx/1.23.3
Date: Sat, 25 Mar 2023 02:57:13 GMT
Content-Type: text/html
Content-Length: 10822
Last-Modified: Thu, 29 Dec 2022 16:20:07 GMT
Connection: keep-alive
ETag: "63adbe37-2a46"
Accept-Ranges: bytes
d8k-a2m2 util > docker container run --rm damrongsak/utils:r23.03 dig blog.d8k.io +short
167.172.72.37
เอาไปใช้งานจริง … ใช้ไม่ได้ ???
ผมก็เริ่มเอา image damrongsak/utils:r23.03 ไปทดสอบใน Kubernetes Cluster ที่ผมสร้างไว้ที่ Digital Ocean โดยมี Kubernetes Cluster ของผม ใช้ VM เป็น Ubuntu 22.04 LTS ติดตั้ง Kubernetes v1.26.3 ด้วย kubeadm
สิ่งที่เกิดขึ้นคือ ผมสร้าง Pod จาก image damrongsak/utils:r23.03 ด้วยคำสั่ง kubectl run
ไม่ได้ มีสถานะออกมาว่า CrashLoopBackOff … ไปตามหา events ที่เกิดขึ้นกับ Pods ก็ดูเหมือนไม่เห็นอะไรผิดปกติ ก็เห็นแต่ว่ามีการ Back-off restarting เพราะว่า container ใน pod มัน fail
เกิดอะไรขึ้น !!!
ไปตามดู log ใน container ใน Pod ก็เห็นว่า exec /usr/bin/dig: exec format error
d8k-a2m2 ~ > kubectl get nodes
NAME STATUS ROLES AGE VERSION
cp0 Ready control-plane 2m47s v1.26.3
node0-0 Ready <none> 2m17s v1.26.3
node0-1 Ready <none> 2m17s v1.26.3
d8k-a2m2 ~ > kubectl run mypod --image damrongsak/utils:r23.03 -- dig blog.d8k.io +short
pod/mypod created
d8k-a2m2 ~ > kubectl get pods
NAME READY STATUS RESTARTS AGE
mypod 0/1 CrashLoopBackOff 1 (7s ago) 16s
d8k-a2m2 ~ > kubectl events --for pod/mypod
LAST SEEN TYPE REASON OBJECT MESSAGE
3m31s Normal Scheduled Pod/mypod Successfully assigned default/mypod to node0-0
3m30s Normal Pulling Pod/mypod Pulling image "damrongsak/utils:r23.03"
3m23s Normal Pulled Pod/mypod Successfully pulled image "damrongsak/utils:r23.03" in 7.047334533s (7.047346457s including waiting)
117s (x5 over 3m23s) Normal Created Pod/mypod Created container mypod
117s (x5 over 3m23s) Normal Started Pod/mypod Started container mypod
117s (x4 over 3m22s) Normal Pulled Pod/mypod Container image "damrongsak/utils:r23.03" already present on machine
116s (x9 over 3m21s) Warning BackOff Pod/mypod Back-off restarting failed container mypod in pod mypod_default(d303f666-7d7a-418a-9eb0-c1aacee8efd4)
d8k-a2m2 ~ > kubectl logs mypod
exec /usr/bin/dig: exec format error
งง !!! อยู่หลายชั่วโมง
จาก error ที่ออกพบ แต่ว่าตอนที่ทดสอบในเครื่อง laptop ตัวเองสามารถใช้งานได้ปกติ ผมก็พุ่งเป้าไปที่ความผิดพลาดของผมเองที่น่าจะทำอะไรอย่างผิดแน่นอน
- ใน Dockerfile มีอะไรผิดไหม
- Base Image ที่เลือกใช้มีอะไรหรือป่าว
- Instruction ที่ผมติดตั้ง package เพิ่ม ผมทำอะไรผิดไปไหน
- package ที่ผมติดตั้ง ผิดตัวหรือไม่
- ตอนที่ build ทำอะไรผิดไปป่าว
- ตอนที่ push ไปเกิดการเปลี่ยนแปลงอะไรหรือไม่
- Kubernetes ที่ใช้ทดสอบ มันผิดปกติอะไรหรือไม่
ผมใช้เวลาหลายชั่วโมง ทดสอบสมมุติฐานตามที่ตำแหน่งต่าง ๆ ที่คาดว่าน่าจะเกิดข้อผิดพลาดเกิดอะไรเกิดขึ้น exec /usr/bin/dig: exec format error … รูปนี้น่าจะแทนอารมณ์ผมได้ดี งงเป็นไก่ตาแตก มันเกิดอะไรขึ้นกับกรณีนี้
ผมมักจะมีความเชื่อว่า ผมไม่น่าจะเจอปัญหาคนเดียวในโลกนี้ และไม่น่าจะเป็นคนแรกที่เจอปัญหานี้ … มันต้องมีคนเคยเจอสิ ??? … อาจาย์ Google ช่วยได้ ค่อย ๆ นั่งนิ่ง ๆ พุ่งเป้ามาที่ keyword “exec format error” แทนที่จะคิดไปที่อื่น
อ๋อ … CPU Architecture นี้เอง
สิ่งที่ผมเปลี่ยนไปในรอบ 3 ปี ก็คือเปลี่ยน laptop ใหม่ที่เปลี่ยนมาใช้ Apple Silicon ทำให้เวลา build Container Image มันไปเลือก Base Image ตาม CPU ของเครื่องที่ผมใช้งานอยู่
ผมก็แค่ระบุ CPU Architecture ไปตอน build ว่าเป็น --platform linux/amd64
ก็เรียบร้อย
d8k-a2m2 util > docker build -t damrongsak/utils --platform linux/amd64 --no-cache .
[+] Building 4.3s (6/6) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 122B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 1.0s
=> CACHED [1/2] FROM docker.io/library/alpine@sha256:ff6bdca1701f3a8a67e328815ff2346b0e4067d32ec3 0.0s
=> [2/2] RUN apk add --update --no-cache curl iputils bash bind-tools 3.1s
=> exporting to image 0.1s
=> => exporting layers 0.0s
=> => writing image sha256:4d32ef67158b037b0a1f8925cc30d74eed5f1d4f1b064ad357e11fde9fca433d 0.0s
=> => naming to docker.io/damrongsak/utils
d8k-a2m2 util > docker image inspect damrongsak/utils:r23.03 | grep Architecture
"Architecture": "arm64",
d8k-a2m2 util > docker image inspect damrongsak/utils | grep Architecture
"Architecture": "amd64",