一、pod状态异常查看方法

1.查看Pod状态
#使用--all-namespaces查看所有命名空间下的pod
kubectl get pod -n <namespace> -o wide

在这里插入图片描述

2.常见Pod状态
状态 解释
Running 运行中
Pending 等待被调度
Waiting 等待启动
CrashLoopBackOff 容器退出,kubelet 正在将它重启
Error 启动过程中发生错误
Unknown 所在节点失联或其它未知异常
Evicted 容器被驱逐
Terminating 正在被销毁
ContainerCreating 容器正在被创建
ImageInspectError 无法校验镜像
InvalidImageName 无法解析镜像名称
ErrImageNeverPull 策略禁止拉取镜像
ErrImagePull 通用的拉取镜像出错
CreateContainerConfigError 不能创建 kubelet 使用的容器配置
CreateContainerError 创建容器失败
RunContainerError 启动容器失败
3.输出Pod的yaml文件
# -o可以指定文件输出格式如yaml、josn等
kubectl get pod <pod-name> -n <namespace> -o yam
#修改yaml文件可用edit
kubectl edit <控制器类型> pod <pod-name> -n <namespace> -o yaml

在这里插入图片描述

4.查看Pod详细信息
kubectl describe  pod <pod-name> -n <namespace>

在这里插入图片描述

5.查看Pod里对应容器的日志
#使用logs -f参数可以实时跟踪日志
kubectl logs   <pod-name> -c <container-name> -n <namespace>

在这里插入图片描述

二、Pod几种异常状态问题分析

1.详细解释Pod常见异常状态
1.pending状态
Pending是挂起状态: 表示创建的Pod找不到可以运行它的物理节点, 不能调度到相应的节点上运行,我门可以从两个层面分析问题:

物理层面:
查看节点资源使用情况: 如free -m查看内存、 top查看CPU使用率、 df – h查看磁盘使用情况, 这样就可以快速定位节点资源情况, 判断是不是节点有问题
查看节点污点: kubectl describe nodes master1(控制节点名字),如果节点定义了污点, 那么Pod不能容忍污点, 就会导致调度失败, 如下: Taints: node-role.kubernetes.io/master:NoSchedule 这个看到的是控制节点的污点, 表示不允许Pod调度(如果Pod定义容忍度, 则可以实现调度)

HostPort被占用
pod本身分析:
在定义pod时, 如果指定了nodeName是不存在的, 那也会调度失败
在定义Pod时, 如果定义的资源请求比较大, 导致物理节点资源不够也是不会调度的

2.ImagePullBackOff状态
拉取镜像时间长导致超时
配置的镜像有错误: 如镜像名字不存在等
配置的镜像无法访问: 如网络限制无法访问hub上的镜像
配置的私有镜像仓库参数错误: 如imagePullSecret没有配置或者配置错误
dockerfile打包的镜像不可用

3.CrashLoopBackOff状态
容器内应用一直在崩溃,健康检查失败
yaml文件中对pod的一些字段配置有误
k8s集群的部署有问题

4.Error/Terminating/Unknow状态

Error:依赖的ConfigMap、 Secret、 PV、 StorageClass等不存在;
请求的资源超过了管理员设置的限制, 比如超过了limits等;
无法操作集群内的资源, 比如开启RBAC后, 需要为ServiceAccount配置权限。
违反集群的安全策略,比如违反了 PodSecurityPolicy 等

Terminating:pod未被正确回收
Unknow:kubelet未启动 kubelet节点与apiserver通信异常

5.Waiting /ContainerCreating/Evicted
Waiting /ContainerCreating:
镜像拉取失败,比如配置了镜像错误、Kubelet 无法访问镜像、私有镜像的密钥配置错误、镜像太大,拉取超时等
CNI 网络错误,一般需要检查 CNI 网络插件的配置,比如无法配置 Pod 、无法分配 IP 地址
容器无法启动,需要检查是否打包了正确的镜像或者是否配置了正确的容器参数
Evicted:多见于系统内存或硬盘资源不足

三、故障排查案例

案例1.镜像拉取失败案例分析

问题现象:济南节点coredns镜像拉取失败

在这里插入图片描述在这里插入图片描述

问题分析:
Pod imagepullbackoff常见情况
拉取镜像时间长导致超时
配置的镜像有错误: 如镜像名字不存在等
配置的镜像无法访问: 如网络限制无法访问hub上的镜像
配置的私有镜像仓库参数错误: 如imagePullSecret没有配置或者配置错误
dockerfile打包的镜像不可用
在这里插入图片描述
在这里插入图片描述
问题分析:Telent 仓库ip :80 不通

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

排查结果:镜像仓库策略问题,复制本地正常镜像到故障机器,重新reload下,恢复正常。

案例2.Pid占用导致docker无法启动

问题现象:通过查看节点信息可以看到node状态处于Notready导致caclico异常。

#查看节点详细信息
kubectl get node -o wide

在这里插入图片描述

#查看calico的网卡信息
calicoctl node status
#在线下载calicoctl的方法
Curl方法:
curl -O https://github.com/projectcalico/calicoctl/releases/download/v3.5.4/calicoctl

Wget方法:
wget https://github.com/projectcalico/calicoctl/releases/download/v3.5.4/calicoctl -O /usr/bin/calicoctl

在这里插入图片描述
问题分析:通过journalctl -u kubelet命令查看kubelet日志发现kubelet启动失败。这里尝试重启还是失败。那么我们就需要看下docker的状态的了。

#通过时间去查找当天的日志信息
journalctl -u <服务名> -S '2021-12-29'

#实时跟踪产生的日志
journalctl -xefu <服务名> 

在这里插入图片描述

问题分析:这里我们查看了docker状态,发现是failed,尝试systemctl start docker直接退出。

在这里插入图片描述
问题分析:这个时候需要我们看一下docker的日志。

#实时跟踪kubelet日志
journalctl -u docker -f

问题分析:我这里没有看到docker日志,所以那就看下service文件有没有配置错误的参数。(如果docker有日志,就查看docker的报错信息。)

在这里插入图片描述
问题分析:确定service文件没错之后,我们用启动命令debug一下。不加参数启动成功。看来问题是出现在参数部分。

#启动dockerd服务
/usr/bin/dockerd

在这里插入图片描述
问题分析:因为之前的docker服务退出异常,pid还在被占用。备份将这个pid移走。再次启动服务即可。

在这里插入图片描述

docker pid被占用,导致docker启动失败。备份将这个pid移走。再次启动服务。

案例3.calico指定多网卡导致无法解析service服务

问题现象:目前有3个节点,只有运行在本地的svc机器才能解析,其他节点无法解析。

#域名解析
nslookup <域名/IP地址>

在这里插入图片描述在这里插入图片描述

问题分析:首先我们查看calico相关pod是否健康。calico状态为0/1该pod不健康。

#查看kube-system命名空间下的pod
#kubectl get pod -n kube-system

在这里插入图片描述
问题分析:接下来需要看下calico的状态,calico的网段为多个,没有指定统一地址,导致calico没有建立连接关系。

#calico网卡信息
calicoctl node status

在这里插入图片描述
问题分析:调整网卡统一地址,calico恢复正常。

#集群统一ip地址(不需要调整网卡,可以不操作这步)
kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=interface=bond0.409(网卡)

#将集群的节点与master节点的calico网络互通(前提是ip可以互通),在master节点执行
kubectl set env daemonset/calico-node -n kube-system IP_AUTODETECTION_METHOD=can-reach=(指定ip)

在这里插入图片描述
排查结果:集群内指定多网卡会造成calico无法建立连接关系,导致依赖网络的服务都无法正常运行。需指定统一网卡建立calico连接。

案例4.集群节点无法连接到master

问题现象:节点系统组件都正常,但是节点没有就绪。

#查看节点信息加(-o wide可以查看集群详细信息)
#kubectl get node

在这里插入图片描述
问题分析:先看下最近产生的日志。可以看到这个33352这个端口无法连接到6443端口,也就是master的ApiServer的端口号。

#查看系统日志
journalctl -f

在这里插入图片描述

问题分析:根据日志提供的命名空间我们去看下该命名空间下的pod,可以看到有个异常的pod,这时就要考虑到是不是这个删除中的pod的随机端口33352已经不在了,所以导致无法连接到apiserver,所以尝试重启异常节点的kubelet,让其重新生成一个端口。

#查看pod状态
kubectl get pod -n <namespaces>

在这里插入图片描述
在这里插入图片描述

问题分析:异常节点重启kubelet,节点恢复正常。

#重启kubelet
systemctl restart kubelet

在这里插入图片描述

排查结果:删除失败的容器端口号已不存在,导致无法连接到集群,重启kubelet重新生成一个新的端口,节点恢复正常。

案例5.Docker启动后频繁down

问题现象:docker启动后短时间频繁down。导致该节点无法正常工作。

#查看集群节点信息
kubectl get node -o wide 

在这里插入图片描述
问题分析:我们知道容器是通过docker起的,如果docker挂了,那容器的状态肯定也是不正常的。而docker除了可以通过自己去创建容器外还可以调用containterd去创建和运行容器。

在这里插入图片描述
问题分析:我们再次尝试重启docker,可以看到给我们的提示大概是说docker被其他任务卡住了。

#重启docker
systemctl restart docker -l

在这里插入图片描述
在这里插入图片描述

排查结果:docker被其他任务卡住了那么我们可以重启containterd ,去加载守护进程,然后在重启docker。

#加载守护进程
systemctl daemon-reexec 
systemctl restart docker

在这里插入图片描述
在这里插入图片描述

案例6.caclio-node启动失败注册ip冲突
问题现象: 1. 一个calico-node一致在crash。 2. calicoctl get node 显示node仍为主机修改hostname之前主机名。

问题分析:vm-2节点加入不了集群,排查vm-2和vm-1发现ipv6地址存在冲突。发现是vm-1的ipv6地址配置错误。修改vm-1的地址,vm-2再次加入集群依旧报错

在这里插入图片描述

问题分析:可以看到vm-2的ipv6地址还是被占用了。怀疑是vm-1脏数据。检查一下vm-1的calico node信息

在这里插入图片描述

问题分析:发现calico node中ipv6address还是修改之前的地址,删除vm-1这个节点让他以正确的ip注册.也可以编辑yaml文件修改后再次检查vm-1的calico node信息

#ip注册
calicoctl delete node vm-1

#导出yaml编辑
calicoctl get node vm-1 -o yaml >vm-1.yaml

#运行yaml
cat vm-1.yaml|calicoctl apply -f -

在这里插入图片描述
问题分析:vm-1的ipv6address被成功更新,再次注册vm-2,这次可以成功注册进来了。不过发现vm-1的calico node的nodename还是以vm-1修改主机名之前的主机名注册的,get node内的信息为正确的信息,虽然不影响使用。还是想改成一致的。因为刚才修改ipv6时已经重新注册过了。nodename还是老的。应该是哪里有固化的脏数据。首先怀疑etcd。尝试把这个节点的calico记录在etcd里删除

在这里插入图片描述

问题分析:删除后重新注册,发现还是以老的主机名注册的

在这里插入图片描述

查询官方文档calico node的nodename由以下几个优先级
在这里插入图片描述

问题分析:由于没有NODENAME,检查节点/var/lib/calico/nodename
在这里插入图片描述

排查结果:果然是这个地方还是老的nodename。删除这个文件。重新注册上去,这次calicoctl get node显示的节点名称正常了

案例7.containerd退出导致pod异常

失败的业务pod都处于ContainerCreating状态。登陆集群,将非Running 的pod筛选出来

在这里插入图片描述
redis-xxx开头的是业务pod,通过图上我们发现处于ContainerCreating状态的pod都在同一台节点上,大概率是该节点的相关组件有问题,ContainerCreating状态是已经经过了k8s调度,分配了对应的节点,处于在节点上创建容器的阶段。根据这几个信息,可以将故障原因缩小到该节点kubelet或者kubelet往下的组件。
登陆节点,查看kubelet日志

在这里插入图片描述

发现/run/containerd/containerd.sock连不上,顺便也看下docker的日志
在这里插入图片描述

报错内容一致,都是/run/containerd/containerd.sock连接拒绝。检查containerd服务
在这里插入图片描述
查看cotainerd日志,有个go的指针报错导致了containerd退出

在这里插入图片描述
重启containerd,可以正常启动。检查docker和kubelet日志,日志恢复正常。节点上pod也恢复正常,问题解决
在这里插入图片描述

案例8.mysql k8s集群异常

执行kubectl命令报Error from server (Timeout): the server was unable to return a response in the time allotted, but may still be processing the request (get pods), 一会儿又报The connection to the server 10.193.149.2:6443 was refused - did you specify the right host or port?
这个说明kube-apiserver在不断的重启

在这里插入图片描述
查看kube-apiserver日志,显示去etcd集群获取资源耗时非常长。甚至有十几秒的报错。显示etcdserver: too many requests。从这边可以判断出是后端etcd的集群出现了故障。

etcd集群健康查看
在集群master执行,查看输出HEALTH是否都为true,正常应该都为true

#!/bin/bash
etcd_servers=$(sudo /apps/bin/kubectl get pod -n kube-system -o wide|grep etcd|awk '{printf "https://"$6":2379,"}'|sed 's/.$//')
sudo /apps/bin/kubectl -n kube-system exec $(sudo /apps/bin/kubectl get pod -n kube-system |grep etcd|awk 'NR==1{print $1}') -- etcdctl --endpoints=${etcd_servers} \
--cert=/apps/conf/kubernetes/ssl/etcd/server.crt \
--key=/apps/conf/kubernetes/ssl/etcd/server.key \
--cacert=/apps/conf/kubernetes/ssl/etcd/ca.crt \
endpoint health -w table

在集群master执行,查看输出是否都为healthy

#!/bin/bash
etcd_servers=$(sudo /apps/bin/kubectl get pod -n kube-system -o wide|grep kube-apiserver|awk '{printf "https://"$6":2379,"}'|sed 's/.$//')
sudo /apps/bin/etcdctl --endpoints=${etcd_servers} \
--cert-file /apps/conf/etcd/ssl/member-`hostname`.pem \
--key-file /apps/conf/etcd/ssl/member-`hostname`-key.pem \
--ca-file /apps/conf/etcd/ssl/ca.pem \
cluster-health

通过输出发现,03节点的etcd连接有问题,登录03节点,由于现网etcd是docker启动的。尝试docker看下日志。发现docker logs命令卡住,使用docker ps命令检查docker响应,发现docker ps也无法成功执行。可以初步判定docker状态异常。etcd 进程虽然还在但是已经无法正常提供服务了。etcd没有完全down导致另外两个节点被拖垮,尝试再03节点上停掉kubelet,docker和etcd服务。让03节点etcd不再对集群的造成影响.
停完03节点的etcd和docker后集群恢复正常,kubectl命令也正常执行。

异常时发现03节点上bcs的watch资源占用比较大,短短33天crash了2700次,甚至造成了dockerd的内存泄露。先把bcs-watch的deployments缩容为0.重启节点docker和kubelet。等待docker启动完毕后,重启etcd。再次检查。etcd集群恢复。至此问题解决

点击阅读全文
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐