• 首页 > 
  • 容器服务ACK应用故障排查

容器服务ACK应用故障排查

KB: 211618

 · 

更新时间:2021-04-12 17:18

概述

在容器服务ACK部署应用程序后,出现异常问题,您可以参考本文内容,排查应用问题。

详细信息

ACK应用故障主要是由Pod、Deployment(StatefulSet/DaemonSet)控制器和Service的问题导致,您需要检查以下几类问题:

检查Pod

登录容器服务管理控制台,单击目标集群名称,然后单击容器组(Pod),查看容器组的状态,根据状态选择不同的方法定位问题:

Pod状态为Pending

  1. 如果Pod一直停留在Pending状态,意味着该Pod不能被调度到某一个节点上,通常是因为集群中缺乏需要的资源导致。
  2. 在目标集群的容器组页面,单击目标容器组名称,然后单击事件,查看事件描述,定位Pod不能调度到节点的原因,主要的原因有以下几类:

    • 资源依赖:
      创建Pod时,有时候需要依赖于集群中ConfigMap(配置字典)、PVC(存储卷声明)等资源。例如,Pod添加存储卷声明前,存储卷声明需要先与存储卷绑定。
    • 资源不足:
      1. 在集群信息页面,依次单击节点管理>节点,查看集群的资源使用率。
        说明:某个节点实际使用的CPU、内存资源非常低,此时新加入一个Pod,如果会导致实际使用的资源超过该节点最大可供使用的资源,则调度程序不会将该Pod分配到该节点。这样可以避免在日常的流量高峰时段,节点上出现资源短缺的情况。
      2. 如果集群中的CPU或内存都已经耗尽,此时,您可以尝试以下方法处理:
    • 该Pod使用了hostPort:
      如果您使用了hostPort,那么Deployment或ReplicationController中replicas值不能超过集群中的节点数,因为每个实例的任意端口只有一个。如果该端口被其他应用占用了,将导致Pod调度不成功,因此不建议您使用hostPort,建议您可以使用Service访问您的Pod,详情请参见Service
    • 污点和容忍:
      当您在Pod的事件中看到Taints或Tolerations这两个单词时,说明是由于污点导致,您可以参见管理污点,删除污点,或者给Pod设置设置容忍,详情请参见设置容忍
      说明:污点和容忍的相关信息请参见污点和容忍

Pod状态为Wating

如果Pod停留在Waiting状态,说明此Pod已经被调度到某个节点,但是却不能运行。您可以查看该Pod的事件描述,最常见的Pod状态为Wating的原因是使用YAML创建应用时,抓取容器镜像失败。因此请参见以下步骤进行排查:

  • 容器镜像名字是否正确。
  • 容器镜像是否已经推送到镜像仓库。
    在对应的节点上,执行docker pull [$Image]命令,查看是否能正常抓取容器镜像。
    说明:[$Image]为容器镜像的名字。
  • 如果您使用的是私有镜像仓库,请参见使用私有镜像仓库创建应用

Pod状态为Crash或者Unhealthy

此时通常是容器中应用程序的问题,您可以查看容器的日志,以诊断容器中应用程序出现的问题。在容器组页面,单击日志,选择目标容器,通过日志内容排查问题。或者参见K8S官方文档,调试异常的Pod。

Pod状态为Running但是没正常工作

出现该问题很有可能是您部署使用的YAML文件有问题,有些问题在创建时,集群会忽略该错误。例如环境变量中某一个Key写错了,即如果command拼写成了commnd,您仍然能够使用该YAML文件创建资源,但是容器在运行时,不会使用您原本期望的命令,而是执行镜像中的默认命令:

  1. 首先,在使用kubectl apply -f命令之前,可以尝试为其添加--validate选项,如下所示。
    kubectl apply --validate -f XXX.yaml
    如果您将command拼写成commnd,将看到如下错误信息。
    XXX] unknown field: commnd
    XXX] this may be a false alarm, see https://gXXXb.XXX/6842
    pods/test
  2. 其次,请检查您已经创建的Pod和您预期是否一致。执行以下命令,将输出结果的XXX.yaml文件与您创建Pod时所使用的文件进行对比。通常通过此命令从服务器端获取到的信息比创建Pod时所使用的文件要多几行,这是正常情况。然而,如果您创建Pod时所使用的文件,存在XXX.yaml文件中没有的代码行,这可能就是出现问题的原因。
    kubectl get pods/[$Pod] -o yaml > XXX.yaml
    说明:[$Pod]为异常Pod的名称,您可以通过kubectl get pods命令查看。

检查Deployment

参见以下步骤,检查Deployment的问题:

  • 创建Deployment、DaemonSet、StatefulSet或Job等资源时,主要可能是Pod的问题。此时,可以参见检查Pod步骤,检查Pod的问题。
  • 您也可以通过查看和Deployment相关的事件及日志来定位问题:
    说明:本文以Deployment为例进行介绍,DaemonSet、StatefulSet或Job等资源查看事件及日志的步骤类似。
    1. 在目标集群的集群信息页面,单击无状态(Deployment),单击目标Deployment名称。
    2. 然后单击事件日志,通过异常信息定位问题。
  • 如果创建的是StatefulSet,您有可能会碰到一些特殊的问题,详情请参见Forced Rollback

检查Service

服务(Service)可以为一组Pod提供负载均衡的功能。与Service相关,存在几类常见问题。请参见本小节了解如何定位Service的问题:

  1. 首先,需要您检查Service的Endpoints。
  2. 登录Kubernetes集群的Master节点,详情请参见通过kubectl连接Kubernetes集群
  3. 执行以下命令,查看Service的Endpoints。
    kubectl get endpoints [$Service_Name]
    说明:[$Service_Name]为目标Service的名称。
    请确保ENDPOINTS值的地址个数和您期望与该Service匹配的Pod个数相同。例如,您使用Deployment部署了应用,其副本数为3,那么ENDPOINTS值的地址个数一定是3个,如下图所示。

Service中缺少Endpoints地址

 如果您的Service中缺少Endpoints地址,可以通过Service的selector查询Service与Pod是否相关联,示例如下:

  1. 若您服务的YAML文件信息如下所示时。
  2. 执行以下命令,核对返回的Pod是否是您关联的Pod。
    kubectl get pods --selector=app=[$App] -n [$Namespace]
    说明
    • [$App]为关联的Pod名称。
    • [$Namespace]为服务所在的命名空间,如果服务在默认空间,可以不需要指定。
  3. 如果返回的Pod是您关联的Pod,但是没有Endpoints地址,很可能是您没有为Service指定正确的端口。如果Service中指定的端口实际上在Pod中没有被监听,那么该Pod不会被添加到ENDPOINTS列表中,因此,请确保Service指定的容器端口在Pod中可以访问,命令如下。
    curl [$IP]:[$Port]
    说明
    • [$IP]为第1步YAML文件中的clusterIP。
    • [$Port]为第1步YAML文件中的port值。
    • 具体测试方法以实际环境为准。

网络转发问题

如果您的客户端可以连接Service,并且Endpoints中地址正确,但是连接很快就断开,那么可能是流量不能转发到您的Pod上,通常需要做下列检查:

  • Pod是否正常工作:
    定位Pod问题,详情请参见检查Pod
  • Pod地址是否正常连通:
    1. 执行以下命令,获取Pod的IP地址。
      kubectl get pods -o wide
    2. 登录任意节点,使用ping命令测试Pod的IP地址,确认网络连接正常。
  • 应用程序是否正常监听端口:
    如果您的应用程序监听80端口,那么您需要在Service中应该指定容器端口为80。在任意节点上执行curl [$IP]:[$Port]命令,查看Pod中容器的端口是否正常。

参考文档

本文的排查方案参考了以下文档:

适用于

  • 容器服务Kubernetes版