一、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全生命周期开发者社区

更多推荐