POD异常状态排查

CrashLoopBackOff

Pod生命周期状态有四个:

  • Pending
  • Running
  • Failed
  • Success
    CrashLoopBackOff是Pod生命状态的Failed状态,他是Pod Running状态之后,容器粒粒面的应用进程运行异常造成的Pod状态的转换,容器里的应用进程的运行异常一般由如下两方面引起:
  1. 应用关联资源调用失败,应用启动失败,应用进程消失,包括调用Service Name的解析失败或者Service Name 的Service Port 调用失败,redis,zk等公共服务的调用失败等
  2. 应用配置有问题,应用进程用到的是不正确的配置参数造成应用进程直接退出

解决思路

查看Pod启动日志
kubectl logs Podname

  • 关键字: service name unkonw host 提示,需要登录主机,查看容器网络组件 kube-proxy 服务和 flanneld 或者calico 是否存在,再验证 到172.254.0.2 53 端口是否通,检查解析失败是否由于网络带来的问题
  • 关键字:time out exception ,一般是被调用资源的服务不存在或者服务端口的防火墙策略问题,还有一种是连错了被调用方的服务端口,都有可能造成连接超时
  • 关键字: unknow parameter 这些一般是应用的配置参数错误造成,检查打镜像时配置文件是否正确

Pending 挂起

POD 挂起状态通常会出现在应用重新部署,重启,或者scale up之后
POD挂起状态标识集群中没有工作节点有足够的资源能够满足运行该POD,kube-scheduler无法完成调度,只能一致等待,直到
集群中有节点能满足POD的资源要求
通常有如下原因

  • 集群工作节点状态异常
  • 集群工作节点资源无法同时满足POD的cpu和 memory requst。我们需要评估并设置合理的CPU 和Memory Request 值,并确认集群中工作节点能满足集群中所有应用的需求;如果应用的CPU,memory request 很高,就很可能集群中有足够的CPU和memory 但是因为碎片化而没有节点能满足需求:如下例子
Limits:
  cpu: 6
  memory: 20Gi
Requests:
  cpu: 6
  memory: 20Gi  
  • 集群工作节点的kubenetes文件系统磁盘空间使用率高,我们需要关注主机节点磁盘空间使用率,清除不必要的日志或Docke容器,Docker镜像,最好能设置磁盘空间使用率的告警并及时处理
  • 应用挂载了外部资源,如configmap但是资源不存在,这种情况下需要先创建好资源
Volumes:
  config-volume:
    Type: ConfigMap(a volume populated by a ConfigMap)
    Name: nginx-conf
    Optionnal: false
  • 添加了特殊的Node-Selector标签,但是没有节点满足该标签,这种情况下需要删除该Node-Selector 或者添加对应的标签
Node-SelectorsL labelexxx=valuexxx
  • 应用配置了节点亲和性,这种情况下需要分析是否有节点满足应用的亲和性策略;
spec:
   affinity:
     nodeAffinity:
       requiredDuringSchedulingIngnoredDuringExecution:
         nodeSelectorTerms:
         -  matchExpressions:
            -  key: failure-domain.beta.kubernetes.io/zone
               operator: in
               values:
               -  sha-az1
               -  sha-az2

ImagePullBakckOff 镜像拉取失败

这个错误是因为Kubernetes 无法拉取容器镜像所导致的。有四种常见原因

  • 镜像名称不正确,如拼写错误、镜像不存在
  • 所定义的镜像的tag 不存在;
  • 镜像属于一个私有仓库且Kubernetes没有权限拉取,可以通过授权并且在Kubernetes 中配置相应的credentials解决。
  • 镜像是一个公网镜像,内网无法拉取

NotReady 未就绪

Pod not in ready state
这个状态表示POD里面的应用已经启动了,但是Readiness探针探测到POD还未就绪(前提是POD配置了Readiness 探针,否则只要程序运行着,POD就是Ready状态)。如果Readiness 探针失败,POD就不会被添加到Service中,也不会有访问流量被转发到该Pod。Pod的Readiness 探针失败通常是因为探针配置不正确或者应用错误导致,需要通过 kubectl describe pod podname 查看分析原因。
常见原因如下

  • 应用完全启动时间大于就绪探针等待时间,此情况下需要调整initialDelaySeconds;
readyniessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds:30 
  persiodSeconds:10
  • 如果就绪探针设置为httpGet,可能http url 指向的页面不存在。有可能是应用没有创建该页面,此种情况应该修改探针配置或者创建相应页面;应用还没有启动完成,还没来得及创建该页面,此种情况应参考第一种原因。
readinessProbe:
 httpGet:
  path:/healthz
 port: liveness-port
 failureThreshold:1
 periodSeconds: 10 
  • 应用程序错误,无法相应就绪探针,需要查看应用日志排查。

Evicted --驱逐

当工作节点的磁盘,内存资源使用率达到阈值时会出发POD驱逐
默认的驱逐阈值如下:

--eviction-hard default 
imagefs.available<15%,memory.available<100Mi,nodefs.available<10%,nodefs.inodesFress<5%

一般常见的驱逐都是因为磁盘空间使用率太高,报错信息为Pod The node was low on resource: [DiskPressure]
此时需要检查主机上的磁盘空间使用率,清理不必要的文件或者扩容磁盘,有时可能因为某些Pod写了太大的日志或dump文件,导致单个Pod占用空间太大,而这个Pod被驱逐后,磁盘空间恢复正常,这种情况需要些日志、dump文件到外部挂载的磁盘(如nas等)

Unknow --未知

k8s集群中,每个工作节点上的kubelet会定时轮询Pod的状态并更新到apiserver。kubelet本身也会定时发送心跳信心给apiserver,如果apiserver没有收到kubelet的心跳信息超过一定阈值,该工作节点会变成NotReady,节点上的Pod会变成Unknown。如果节点转台在pod-eviction-timeout时间之内恢复正常,pod的状态也会恢复正常。如果节点状态无法再pod-eviction-timeout时间内恢复正常,控制器会在其他节点上拉起新的POD,旧的POD状态依旧是Unknown,等待节点恢复后,旧的POD会被删除。
工作节点NotReady的可能原因有:

  • Kubelet服务异常
  • 节点高负载导致无法上报
  • 节点宕机
  • 网络不通
    如发现POD状态为Unknown,请登录工作节点,查看Kubelet状态及日志。systemctl status kubelet -l 或者查看主机状态,网络通信是否正常。

故障基本排查步骤

Pod故障排查

  1. 查看Pod状态
  2. 查看Pod事件
  3. 查看Pod日志
  4. 测试网络连通性
    • 网络插件检查 ping podip 通说明正常
    • 端口连通性检测 telnet podip 不通,则有可能是无响应或者是没有监听
    • curl检查: curl podip:port 如果没有返回可能是应用无响应
    • 域名解析检查: nslookup domain 172.254.0.3 可测试k8s dns是否能够正常解析
    • 查看端口监听状态 netstat -anp 如果无监听,或者只监听127.0.0.1则访问会connection refused。ss -Int 如果Rcev -Q 满或者太高,则说明应用无响应了

Service故障排查

  1. 查看Service :kubelet get svc
  2. 查看service端口配置 : kubectl describe svc
  3. 查看service Endpoints
  4. 测试service 端口连通性 service ip ping不通
    telnet svcip port如果所有IP正常,但是端口不通,可能是 iptables/ipvx/kube-proxy 异常
    curl svcip:port 如果http不通,可能是应用无响应

NodePort 故障排查

nodePort是通过iptables规则对报文的源目的地址做如下转换

源IP:源Port
转换前 客户端IP:随机端口 Node IP:node port
转换后 NodeIP :随机端口 Pod IP:服务端口
  • 查看nodePort是否监听
    netstat -anp | grep nodeport 若无监听,则可能是没部署nodePort svc
  • 测试连通性
    telnet nodeIp nodePort
    curl node Ip:nodePort

ingress 故障排查

  • 查看ingress
    同一个host可能存在多条ingress规则
  • 查看ingress host 后端svc 端口配置
    匹配 host + path -> 成功则转发到 service + port
  • 测试 ingress端口连通性
    curl url -x ingress-controller-ip :80
    curl ingress-controller-ip:80/path -H “host:域名”

其他常见问题

CPU 内存资源配置

Request 值是保证POD一定能分配到的资源,Pod实际使用资源可能比这个值小,Limit值是Pod 能够使用的资源上线(前提是工作节点未饱和)。Pod在调度时只看 request值,跟limits值无关,只要工作节点能满足CPU和Memory request值,Pod就可能部署到这些节点。初始配置 request 和limit可按照 1:1.5 配置,后续可根据监控信息调整

磁盘空间监控

/var/lib/docker 目录告警阈值建议配置为 75%
单独挂载卷到 /var/lib/docker

1. 给节点打上NoExecute 污点,驱逐 Pod
2. 停止kubelet 服务, systemctl stop kubelet
3. 停止所有docker容器  docker stop $(docker ps -q)
4. 停止docker 服务 systemctl stop docker
5. 确认相关进程均已停止  ps -ef|grep docker
6. 重命名 docker 目录 cd /var/lib mv docker docker_bak ; mkdir docker
7. 挂载新卷到 /var/lib/docker目录,问价格式为xfs ,ftpye=1
8. 启动docker服务 systemctl start docker
9. 重新加载基础镜像 docker load -i /opt/k8s/node/inmage/pause.tar (视具体情况而定)
10.启动 kubelet 服务,systemctl start kubelet
11 删除工作节点上的污点标签 

清理docker目录空间

Docker文件所在目录为/var/lib/docker 通常会被挂载为/var 分区或者直接被挂载到 根分区(/),不建议把Docker目录直接挂载到根分区。
Docker 所在的磁盘分区如果使用率太高会导致pod无法调度或者被驱逐,建议对docker所在磁盘分区设置监控并把阈值调整为70%
清理步骤:

  1. 查看/var/lib/docker 所在磁盘分区使用率
    df -h /var/lib/docker
  2. 查看docker文件系统资源占用信息
    docker system df
    docker system df -v
    docker system prun -a
    将删除如下内容
    删除已经停止的容器;
    没有被任何容器使用的卷(不包括外部挂载的数据)
    没有被任何容器使用的网络配置
    没有被任何容器使用的镜像
  3. 如果运行的容器磁盘使用率高,则需要进入容器查看并清理文件
    docker exec -it container bash

主机内存监控

主机oom容易导致docker 服务异常

Java 应用没有配置堆内存参数

java1.8_131以下版本无法感知容器内存,131-191 可以使用-XX:UnlockExperimentalVMOptions ,-XX:+UseCGroupMemoryLimitForHeap,191+可以使用-XX:+UserContainerSupport,-XX:MaxRAMPercent

POD 内存与JVM堆内存关系 ≈ 虚拟机与JVM 堆内存关系

生产环境使用NodePort访问

Pod访问不通常见原因

net.ipv4.ip_forward=1
flannel 8472 UDP 不通
calico IP 协议不通
路由表未更新
iptables或者ipvs规则未更新

你可能感兴趣的:(POD异常状态排查)