更新时间:2024-01-26 GMT+08:00

工作负载异常:实例拉取镜像失败

问题定位

当工作负载状态显示“实例未就绪:Back-off pulling image "xxxxx"”,该状态下工作负载实例K8s事件名称为实例拉取镜像失败重新拉取镜像失败。查看K8s事件的方法请参见Pod事件查看方法

排查思路

根据具体事件信息确定具体问题原因,如表1所示。

表1 实例拉取镜像失败

事件信息

问题原因与解决方案

Failed to pull image "xxx": rpc error: code = Unknown desc = Error response from daemon: Get xxx: denied: You may not login yet

没有登录镜像仓库,无法拉取镜像。

排查项一:kubectl创建工作负载时未指定imagePullSecret

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容器引擎的节点:
    1. 查看节点上的本地镜像。
      crictl images -v
    2. 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
      crictl rmi {镜像ID}
  • 使用docker容器引擎的节点:
    1. 查看节点上的本地镜像。
      docker images
    2. 确认镜像无需使用,并通过镜像ID删除无需使用的镜像。
      docker rmi {镜像ID}

请勿删除cce-pause等系统镜像,否则可能导致无法正常创建容器。

方案二:扩容磁盘

扩容磁盘的操作步骤如下:

  1. 在EVS界面扩容数据盘。
  2. 登录CCE控制台,进入集群,在左侧选择“节点管理”,单击节点后的“同步云服务器”
  3. 登录目标节点。
  4. 使用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

排查项五: 远程镜像仓库使用非知名或不安全的证书

从第三方仓库下载镜像时,若第三方仓库使用了非知名或者不安全的证书,节点上会拉取镜像失败,Pod事件列表中有“实例拉取镜像失败”事件,报错原因为"x509: certificate signed by unknown authority"。

当前EulerOS 2.9镜像中有进行安全增强,移除系统中部分非安全或过期知名证书配置,部分第三方镜像在其他类型节点上未报错,在EulerOS 2.9系统报此错误属正常现象,也可通过下述解决方案进行处理。

解决方案

  1. 确认报错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

  2. 在需要下载第三方镜像的节点上加载第三方镜像服务器的根证书。

    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配置参数。

    1.15及以上集群使用如下命令:

    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拉取镜像。