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

工作负载异常:启动容器失败

问题定位

工作负载详情中,若事件中提示启动容器失败,请按照如下方式来初步排查原因:

  1. 登录异常工作负载所在的节点。
  2. 查看工作负载实例非正常退出的容器ID。

    docker ps -a | grep $podName

  3. 查看退出容器的错误日志。

    docker logs $containerID

    根据日志提示修复工作负载本身的问题。

  4. 查看操作系统的错误日志。

    cat /var/log/messages | grep $containerID  | grep oom

    根据日志判断是否触发了系统OOM。

排查思路

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

表1 容器启动失败

日志或事件信息

问题原因与解决方案

日志中存在exit(0)

容器中无进程。

请调试容器是否能正常运行。

排查项一:(退出码:0)容器中无持续运行的进程

事件信息:Liveness probe failed: Get http…

日志中存在exit(137)

健康检查执行失败。

排查项二:(退出码:137)健康检查执行失败

事件信息:

Thin Pool has 15991 free data blocks which is less than minimum required 16383 free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior

磁盘空间不足,需要清理磁盘空间。

排查项三:容器所在磁盘空间不足

日志中存在OOM字眼

内存不足。

排查项四:达到容器资源上限

排查项五:工作负载的容器规格设置较小导致

Address already in use

Pod中容器端口冲突

排查项六:同一pod中container端口冲突导致

除上述可能原因外,还可能存在如下原因,请根据顺序排查。

图1 重新启动容器失败排查思路

排查项一:(退出码:0)容器中无持续运行的进程

  1. 登录异常工作负载所在的节点。
  2. 查看容器状态。

    docker ps -a | grep $podName

    如下图所示:

    当容器中无持续运行的进程时,会出现exit(0)的状态码,此时说明容器中无进程。

排查项二:(退出码:137)健康检查执行失败

工作负载配置的健康检查会定时检查业务,异常情况下pod会报实例不健康的事件且pod一直重启失败。

工作负载若配置liveness型(工作负载存活探针)健康检查,当健康检查失败次数超过阈值时,会重启实例中的容器。在工作负载详情页面查看事件,若K8s事件中出现“Liveness probe failed: Get http…”时,表示健康检查失败。

解决方案:

请在工作负载详情页中,切换至“容器管理”页签,核查容器的“健康检查”配置信息,排查健康检查策略是否合理或业务是否已异常。

排查项三:容器所在磁盘空间不足

如下磁盘为创建节点时选择的docker专用盘分出来的thinpool盘,以root用户执行lvs命令可以查看当前磁盘的使用量。

Thin Pool has 15991 free data blocks which is less than minimum required 16383 free data blocks. Create more free space in thin pool or use dm.min_free_space option to change behavior

解决方案:

方案一:清理镜像

您可以执行以下步骤清理未使用的镜像:
  • 使用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
      vda                   8:0    0   50G  0 disk 
      └─vda1                8:1    0   50G  0 part /
      vdb                   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/vdb 
      lvextend -l+100%FREE -n vgpaas/dockersys
      resize2fs /dev/vgpaas/dockersys
    • Devicemapper,单独划分了thinpool存储镜像相关数据。
      # lsblk
      NAME                                MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
      vda                                   8:0    0   50G  0 disk 
      └─vda1                                8:1    0   50G  0 part /
      vdb                                   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/vdb 
        lvextend -l+100%FREE -n vgpaas/thinpool
      • 在节点上执行如下命令, 将新增的磁盘容量加到dockersys盘上。
        pvresize /dev/vdb 
        lvextend -l+100%FREE -n vgpaas/dockersys
        resize2fs /dev/vgpaas/dockersys

排查项四:达到容器资源上限

事件详情中有OOM字样。并且,在日志中也会有记录:

cat /var/log/messages | grep 96feb0a425d6 | grep oom

创建工作负载时,设置的限制资源若小于实际所需资源,会触发系统OOM,并导致容器异常退出。

排查项五:工作负载的容器规格设置较小导致

工作负载的容器规格设置较小导致,若创建工作负载时,设置的限制资源少于实际所需资源,会导致启动容器失败。

排查项六:同一pod中container端口冲突导致

  1. 登录异常工作负载所在的节点。
  2. 查看工作负载实例非正常退出的容器ID。

    docker ps -a | grep $podName

  3. 查看退出容器的错误日志。

    docker logs $containerID

    根据日志提示修复工作负载本身的问题。如下图所示,即同一Pod中的container端口冲突导致容器启动失败。

    图2 container冲突导致容器启动失败

解决方案:

重新创建工作负载,并配置正确的端口,确保端口不冲突。

排查项七:容器启动命令配置有误导致

错误信息如下图所示:

解决方案:

请在工作负载详情页中,切换至“容器管理”页签,核查容器的“生命周期 > 启动命令”配置信息,确保启动命令配置正确。

排查项八:用户自身业务BUG

请检查工作负载启动命令是否正确执行,或工作负载本身bug导致容器不断重启。

  1. 登录异常工作负载所在的节点。
  2. 查看工作负载实例非正常退出的容器ID。

    docker ps -a | grep $podName

  3. 查看退出容器的错误日志。

    docker logs $containerID

    注意:这里的containerID为已退出的容器的ID

    图3 容器启动命令配置不正确

    如上图所示,容器配置的启动命令不正确导致容器启动失败。其他错误请根据日志提示修复工作负载本身的BUG问题。

解决方案:

重新创建工作负载,并配置正确的启动命令。