工作负载异常:实例拉取镜像失败
问题定位
当工作负载状态显示“实例未就绪:Back-off pulling image "xxxxx"”,该状态下工作负载实例K8s事件名称为“实例拉取镜像失败”或“重新拉取镜像失败”。查看K8s事件的方法请参见Pod事件查看方法。
排查思路
根据具体事件信息确定具体问题原因,如表1所示。
事件信息 |
问题原因与解决方案 |
---|---|
Failed to pull image "xxx": rpc error: code = Unknown desc = Error response from daemon: Get xxx: denied: You may not login yet |
没有登录镜像仓库,无法拉取镜像。 |
Failed to pull image "nginx:v1.1": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host |
镜像地址配置有误找不到镜像导致失败。 |
Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "nginx-6dc48bf8b6-l8xrw": Error response from daemon: mkdir xxxxx: no space left on device |
磁盘空间不足。 |
Failed to pull image "xxx": rpc error: code = Unknown desc = error pulling image configuration: xxx x509: certificate signed by unknown authority |
从第三方仓库下载镜像时,第三方仓库使用了非知名或者不安全的证书. |
Failed to pull image "XXX": rpc error: code = Unknown desc = context canceled |
镜像体积过大。 |
Failed to pull image "docker.io/bitnami/nginx:1.22.0-debian-11-r3": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) |
|
ERROR: toomanyrequests: Too Many Requests. 或 you have reached your pull rate limit, you may increase the limit by authenticating an upgrading |
由于拉取镜像次数达到上限而被限速。 |
排查项一:kubectl创建工作负载时未指定imagePullSecret
当工作负载状态异常并显示“实例拉取镜像失败”的K8s事件时,请排查yaml文件中是否存在imagePullSecrets字段。
排查事项:
- 当Pull SWR容器镜像仓库的镜像时,name参数值需固定为default-secret。
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx spec: replicas: 1 selector: matchLabels: app: nginx strategy: type: RollingUpdate template: metadata: labels: app: nginx spec: containers: - image: nginx imagePullPolicy: Always name: nginx imagePullSecrets: - name: default-secret
- Pull第三方镜像仓库的镜像时,需设置为创建的secret名称。
kubectl创建工作负载拉取第三方镜像时,需指定的imagePullSecret字段,name表示pull镜像时的secret名称。
排查项二:填写的镜像地址错误(使用第三方镜像时)
CCE支持拉取第三方镜像仓库中的镜像来创建工作负载。
在填写第三方镜像的地址时,请参照要求的格式来填写。镜像地址格式为:ip:port/path/name:version或name:version,若没标注版本号则默认版本号为latest。
- 若是私有仓库,请填写ip:port/path/name:version。
- 若是docker开源仓库,请填写name:version,例如nginx:latest。
镜像地址配置有误找不到镜像导致失败,Kubernetes Event中提示如下信息:
Failed to pull image "nginx:v1.1": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: no such host
解决方案:
可编辑yaml修改镜像地址,也可在工作负载详情页面更新升级页签单击更换镜像。
排查项三:使用错误的密钥(使用第三方镜像时)
通常第三方镜像仓库都必须经过认证(账号密码)才可以访问,而CCE中容器拉取镜像是使用密钥认证方式,这就要求在拉取镜像前必须先创建镜像仓库的密钥。
解决方案:
若您的密钥错误将会导致镜像拉取失败,请重新获取密钥。
排查项四:节点磁盘空间不足
当k8s事件中包含以下信息,表明节点上用于存储镜像的磁盘空间已满,会导致重新拉取镜像失败。您可以通过清理镜像或扩容磁盘解决该问题。
Failed create pod sandbox: rpc error: code = Unknown desc = failed to create a sandbox for pod "nginx-6dc48bf8b6-l8xrw": Error response from daemon: mkdir xxxxx: no space left on device
您可以执行以下命令,确认节点上存储镜像的磁盘空间:
lvs
方案一:清理镜像
- 使用containerd容器引擎的节点:
- 查看节点上的本地镜像。
crictl images -v
- 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
crictl rmi {镜像ID}
- 查看节点上的本地镜像。
- 使用docker容器引擎的节点:
- 查看节点上的本地镜像。
docker images
- 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
docker rmi {镜像ID}
- 查看节点上的本地镜像。
请勿删除cce-pause等系统镜像,否则可能导致无法正常创建容器。
方案二:扩容磁盘
扩容磁盘的操作步骤如下:
- 在EVS界面扩容数据盘。
- 登录CCE控制台,进入集群,在左侧选择“节点管理”,单击节点后的“同步云服务器”。
- 登录目标节点。
- 使用lsblk命令查看节点块设备信息。
这里存在两种情况,根据容器存储Rootfs而不同。
- Overlayfs,没有单独划分thinpool,在dockersys空间下统一存储镜像相关数据。
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 50G 0 disk └─sda1 8:1 0 50G 0 part / sdb 8:16 0 200G 0 disk ├─vgpaas-dockersys 253:0 0 90G 0 lvm /var/lib/docker # 容器引擎使用的空间 └─vgpaas-kubernetes 253:1 0 10G 0 lvm /mnt/paas/kubernetes/kubelet # kubernetes使用的空间
在节点上执行如下命令, 将新增的磁盘容量加到dockersys盘上。
pvresize /dev/sdb lvextend -l+100%FREE -n vgpaas/dockersys resize2fs /dev/vgpaas/dockersys
- Devicemapper,单独划分了thinpool存储镜像相关数据。
# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 50G 0 disk └─sda1 8:1 0 50G 0 part / sdb 8:16 0 200G 0 disk ├─vgpaas-dockersys 253:0 0 18G 0 lvm /var/lib/docker ├─vgpaas-thinpool_tmeta 253:1 0 3G 0 lvm │ └─vgpaas-thinpool 253:3 0 67G 0 lvm # thinpool空间 │ ... ├─vgpaas-thinpool_tdata 253:2 0 67G 0 lvm │ └─vgpaas-thinpool 253:3 0 67G 0 lvm │ ... └─vgpaas-kubernetes 253:4 0 10G 0 lvm /mnt/paas/kubernetes/kubelet
- 在节点上执行如下命令, 将新增的磁盘容量加到thinpool盘上。
pvresize /dev/sdb lvextend -l+100%FREE -n vgpaas/thinpool
- 在节点上执行如下命令, 将新增的磁盘容量加到dockersys盘上。
pvresize /dev/sdb lvextend -l+100%FREE -n vgpaas/dockersys resize2fs /dev/vgpaas/dockersys
- 在节点上执行如下命令, 将新增的磁盘容量加到thinpool盘上。
- Overlayfs,没有单独划分thinpool,在dockersys空间下统一存储镜像相关数据。
排查项五: 远程镜像仓库使用非知名或不安全的证书
从第三方仓库下载镜像时,若第三方仓库使用了非知名或者不安全的证书,节点上会拉取镜像失败,Pod事件列表中有“实例拉取镜像失败”事件,报错原因为"x509: certificate signed by unknown authority"。
当前EulerOS 2.9镜像中有进行安全增强,移除系统中部分非安全或过期知名证书配置,部分第三方镜像在其他类型节点上未报错,在EulerOS 2.9系统报此错误属正常现象,也可通过下述解决方案进行处理。
解决方案:
- 确认报错unknown authority的第三方镜像服务器地址和端口。
从"实例拉取镜像失败"事件信息中能够直接看到报错的第三方镜像服务器地址和端口,如上图中错误信息为:
Failed to pull image "bitnami/redis-cluster:latest": rpc error: code = Unknown desc = error pulling image configuration: Get https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/e8/e83853f03a2e792614e7c1e6de75d63e2d6d633b4e7c39b9d700792ee50f7b56/data?verify=1636972064-AQbl5RActnudDZV%2F3EShZwnqOe8%3D: x509: certificate signed by unknown authority
对应的第三方镜像服务器地址为 production.cloudflare.docker.com,端口为https默认端口443。
- 在需要下载第三方镜像的节点上加载第三方镜像服务器的根证书。
EulerOS, CentOS节点执行如下命令,{server_url}:{server_port}需替换成步骤1中地址和端口,如 production.cloudflare.docker.com:443。
若节点的容器引擎为containerd,最后一步“systemctl restart docker”命令替换为"systemctl restart containerd"。openssl s_client -showcerts -connect {server_url}:{server_port} < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /etc/pki/ca-trust/source/anchors/tmp_ca.crt update-ca-trust systemctl restart docker
ubuntu节点执行如下命令。openssl s_client -showcerts -connect {server_url}:{server_port} < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /usr/local/share/ca-certificates/tmp_ca.crt update-ca-trust systemctl restart docker
排查项六: 镜像过大导致失败
Pod事件列表中有“实例拉取镜像失败”事件,报错原因如下。这可能是镜像较大导致的情况。
Failed to pull image "XXX": rpc error: code = Unknown desc = context canceled
登录节点使用docker pull命令手动下拉镜像,镜像下拉成功。
问题根因:
kubernetes默认的image-pull-progress-deadline是1分钟, 如果1分钟内镜像下载没有任何进度更新, 下载动作就会取消。在节点性能较差或镜像较大时,可能出现镜像无法成功下载,负载启动失败的现象。
解决方案:
- (推荐)方法一:登录节点使用docker pull命令手动下拉镜像,确认负载的镜像拉取策略imagePullPolicy为IfNotPresent(默认策略配置)。此时创建负载会使用已拉取到本地的镜像。
- 方法二:修改kubelet配置参数。
vi /opt/cloud/cce/kubernetes/kubelet/kubelet
1.15以下集群使用如下命令:
vi /var/paas/kubernetes/kubelet/kubelet
在DAEMON_ARGS参数末尾追加配置 --image-pull-progress-deadline=30m ,30m为30分钟,可根据需求修改为合适时间。追加配置和前项配置之间由空格分开。
重启kubelet:
systemctl restart kubelet
等待片刻,确定kubelet状态为running
systemctl status kubelet
负载正常启动,镜像下拉成功。
排查项七:无法连接镜像仓库
问题现象
创建工作负载时报如下错误。
Failed to pull image "docker.io/bitnami/nginx:1.22.0-debian-11-r3": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
问题原因
无法连接镜像仓库,网络不通。SWR仅支持直接拉取Docker官方的镜像,其他仓库的镜像需要连接公网。
解决方案:
- 方案一:给需要下载镜像的节点绑定公网IP。
- 方案二:先将镜像上传到SWR,然后从SWR拉取镜像。
排查项八:拉取公共镜像达上限
问题现象
创建工作负载时报如下错误。
ERROR: toomanyrequests: Too Many Requests.
或
you have reached your pull rate limit, you may increase the limit by authenticating an upgrading: https://www.docker.com/increase-rate-limits.
问题原因
DockerHub对用户拉取容器镜像请求设定了上限,详情请参见Understanding Docker Hub Rate Limiting。
解决方案:
将常用的镜像上传到SWR,然后从SWR拉取镜像。