问题发生
一个 http 应用, 监听在 8080 端口, 编译命令:
go build -o app
Dockerfile
FROM alpine:3.16
WORKDIR /app
COPY app .
CMD ["./app"]
打包镜像的命令:
docker build -t daydaylw3/k8s-node:v1 .
问题1: 找不到该镜像
然后使用 minikube 部署该镜像, 部署名称为 k8s-bootcamp:
kubectl create deployment k8s-bootcamp --image=daydaylw3/k8s-node:v1
发现一直没有 READY, 查看发现状态是
NAME READY STATUS RESTARTS AGE
k8s-bootcamp-68566978d4-x2t2m 0/1 ImagePullBackOff 0 20s
然后 describe pod 的事件如下:
~ kubectl describe pod k8s-bootcamp-68566978d4-6x4xb
... 省略其他内容 ...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4m54s default-scheduler Successfully assigned default/k8s-bootcamp-68566978d4-6x4xb to minikube
Normal Pulling 3m8s (x4 over 4m54s) kubelet Pulling image "daydaylw3/k8s-node:v1"
Warning Failed 3m2s (x4 over 4m48s) kubelet Failed to pull image "daydaylw3/k8s-node:v1": Error response from daemon: Head "https://registry-1.docker.io/v2/daydaylw3/k8s-node/manifests/v1": Get "https://auth.docker.io/token?scope=repository%3Adaydaylw3%2Fk8s-node%3Apull&service=registry.docker.io": EOF
Warning Failed 3m2s (x4 over 4m48s) kubelet Error: ErrImagePull
Warning Failed 2m47s (x6 over 4m47s) kubelet Error: ImagePullBackOff
Normal BackOff 2m34s (x7 over 4m47s) kubelet Back-off pulling image "daydaylw3/k8s-node:v1"
一开始以为默认行为是一定要从远程拉取, 因此打算编辑部署 yaml 文件
kubectl edit deployment k8s-bootcamp
但是发现配置如下:
# ... 省略其他配置
spec:
containers:
- image: daydaylw3/k8s-node:v1
imagePullPolicy: IfNotPresent
name: k8s-node
resources: {}
# ... 省略其他配置
IfNotPresent: 说明是会优先寻找本地仓库的
解决
Minikube 默认使用的 runtime 可能跟 Docker 本地环境不是同一个,所以没法识别本地的镜像。
在 Minikube 内部导入你的本地镜像:
minikube image load daydaylw3/k8s-node:v1
或者在构建镜像时直接使用 minikube 的 docker 来构建
eval $(minikube docker-env)
docker build -t daydaylw3/k8s-node:v1 .
问题2: 镜像里的可执行文件不是当前系统架构支持的格式
导入了镜像之后重新部署, 这时候 pod 直接 crashed
(base) ➜ ~ kubectl get pods
NAME READY STATUS RESTARTS AGE
k8s-bootcamp-68566978d4-cnbl4 0/1 CrashLoopBackOff 2 (27s ago) 42s
查看事件:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 61s default-scheduler Successfully assigned default/k8s-bootcamp-68566978d4-cnbl4 to minikube
Normal Pulled 19s (x4 over 60s) kubelet Container image "daydaylw3/k8s-node:v1" already present on machine
Normal Created 19s (x4 over 60s) kubelet Created container k8s-node
Normal Started 19s (x4 over 60s) kubelet Started container k8s-node
Warning BackOff 4s (x5 over 59s) kubelet Back-off restarting failed container k8s-node in pod k8s-bootcamp-68566978d4-cnbl4_default(eb0bdc82-c1a4-40e8-aa2d-172274b39d70)
以及日志:
~ kubectl logs -p k8s-bootcamp-68566978d4-cnbl4
exec ./app: exec format error
这个错误通常就代表镜像里的可执行文件 ./app 不是当前系统架构支持的格式, 于是登录 minikube 控制台确认 minikube 的架构
~ minikube ssh
docker@minikube:~$ uname -m
aarch64
确认了 minikube 的架构为 arm64, 然后同样确认下 minikube 中的镜像架构:
docker inspect daydaylw3/k8s-node:v1
...
"Architecture": "arm64"
...
说明镜像也是 arm64 的
在 minikube 控制台上直接运行该镜像也是报相同的错
退出 minikube 控制台, 直接在物理机上(mac)运行该镜像又一切正常
解决
编译 app 可执行文件时使用交叉编译的选项:
GOOS=linux GOARCH=arm64 go build -o app
docker build -t daydaylw3/k8s-node:v1 .
然后在 minikube 控制台中删除原镜像, 重新导入, 再次部署, pod 就成功启动!