绝了,真的绝了,昨天刚解决完磁盘空间的问题,还以为能消停一段时间了,结果并没有。
今天上午同事在执行完CI/CD之后发现流程走完了,但pod没起来,提示报错信息:
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox image "[registry.k8s.io/pause:3.7](http://registry.k8s.io/pause:3.7)": failed to pull image "[registry.k8s.io/pause:3.7](http://registry.k8s.io/pause:3.7)": failed to pull and unpack image "[registry.k8s.io/pause:3.7](http://registry.k8s.io/pause:3.7)": failed to resolve reference "[registry.k8s.io/pause:3.7](http://registry.k8s.io/pause:3.7)": failed to do request: Head "<https://asia-east1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.7>": dial tcp [64.233.188.82:443](http://64.233.188.82:443): i/o timeout
一眼就看出了,这玩意铁定是和我昨天删镜像有关系。本着虽然很难受,但该解决还是得解决的态度,开始分析问题。
分析
从报错信息的语义来看,这个问题出在无法获取镜像上,也就是说k8s在本地找不到这个镜像,即kind里没有这个镜像导致的报错,那么只要将这个镜像以某种方式放进去这个问题就解决了。
但是当我开始动手做的时候才发现事情没那么简单。
过程
要想获取镜像,首先第一反应自然是docker search,但很快,docker search报错:Error response from daemon: Unexpected status code 404
无法找到这个镜像,docker pull也报错,也就是说这个镜像无法直接下载。
这就用到了docker打包的方法了。
首先找到镜像的替代品:dyrnq/pause:3.7
,docker pull到本地,这个是官方的registry.k8s.io/pause
包,但是因为名字不是叫registry.k8s.io/pause,所以直接search是搜不到的。
然后执行:docker image tag dyrnq/pause:3.7 registry.k8s.io/pause:3.7
,将这个包重命名为registry.k8s.io/pause。
再执行:docker save -o pause37.tar registry.k8s.io/pause
,将这个镜像打包到当前文件夹,命名为"registry.k8s.io/pause"。
将打好的包放入docker:docker cp pause37.tar (你kind所在的docker container名字):/images/pause37.tar
,这个images文件夹是进入docker内部创建的,进入命令:docker exec -it (container 名字) bash
。
放好之后进入docker内部,执行:ctr -n k8s.io image import /images/pause37.tar
,这里需要解释一下,这个命令有看过上一篇文章的同学应该是有所了解的,它和crictl命令是k8s对docker API的封装,避免用户直接操作docker,这里的操作相当于docker import,将本地镜像包导入到本地镜像仓库,-n命令是由于ctr命令是要判断命名空间的,crictl命令能够查询到的命名空间默认是k8s.io。
以上的步骤执行完成后,就是重启当前启动失败的Pod,但是由于k8s本身没有重启pod的命令,需要将pod停止之后重新生成一个:kubectl get pod (podid) -n (pod命名空间,默认是default) -o yaml | kubectl replace --force -f -
。
就完成了。
总结
说着说着又加班了,淦,我要下班!!!