- k8s之连接异常【集群故障】
- 查看pod状态
kubectl get pod - 查看pod信息
kubectl describe pod - 查看pod日志
kubectl logs -f - 查看kubelet状态
systemctl status kubelet - 查看kubelet日志
tail -1000f /var/log/message |grep kubelet
or
journalctl -f -u kubelet - 查看pod详细信息
kubectl describe pod
原因:由于当前节点被反复注册,导致网络出现问题。">显示
##场景1:
原因:由于当前节点被反复注册,导致网络出现问题。- 删除现有信息
kubectl delete default-ipv4-ippool.yaml - 修改default-ipv4-ippool.yaml文件中cidr为新cidr
- 应用
kubectl apply -f default-ipv4-ippool.yaml - 后续
修改iptables规则,重启网络插件
增加节点并确认网络
驱逐旧节点上的服务
删除旧的节点
重新加入旧的节点并确认网络 - 场景1
描述:
安装coredns后,容器内部无法解析集群外的域名。 - 场景2
描述:
pod基于域名访问基础服务mysql、redis等,经常出现超时,报错如下:
io.netty.resolver.dns.DnsNameResolverTimeoutException: [/10.96.0.10:53] query timed out after 1000 milliseconds(no stack trace available) - 场景一
描述:
刚好装好的k8s集群node节点Notready,coreDNS处于pendding状态。 - 场景二
描述:
k8s运行一段时间后,node节点是Notready状态。 - k8s之应用故障【应用异常】
- 查看pod状态
$ kubectl get po -o wide - 查看到svc也通过标签选择器关联到了pod,且有Endpoints
$ kubectl describe svc myapp-v1-service
$ kubectl get pods -owide
$ iptables -t nat -L |grep 10.244.103.5
">查看iptables(10.109.72.235是svc的cluster ip)
$ iptables -t nat -L |grep 10.109.72.235
$ kubectl get pods -owide
$ iptables -t nat -L |grep 10.244.103.5
- ">查看kube-proxy状态(服务已启动)
$ ps -ef |grep kube-proxy
- ">查看kube-proxy日志
$ cat /var/log/messages | grep kube-proxy
- ">查看kube-proxy占用的资源
$ kubectl top pods -n kube-system |grep proxy
- 按需修改kube-proxy的资源配额,问题解决。
k8s之连接异常【集群故障】
pod常见问题
集群中Pod容易出现问题的方面:
- 资源配置错误(部署deployment时,资源清单书写有问题导致pod无法正常创建)
- 代码问题(应用程序代码在容器启动后失败,需要通过排查代码)
- 网络问题(网络插件有问题导致pod启动后无法互相通信)
- 存储问题(pod挂载存储异常)
pod排查命令
查看pod状态
kubectl get pod
查看pod信息
kubectl describe pod
查看pod日志
kubectl logs -f
查看kubelet状态
systemctl status kubelet
查看kubelet日志
tail -1000f /var/log/message |grep kubelet
or
journalctl -f -u kubelet
pod问题示例
查看pod详细信息
kubectl describe pod
显示
##场景1:

原因:由于当前节点被反复注册,导致网络出现问题。
解决:查看此节点上其他pod是否能正常运行,如果都error,故可能节点网络问题,确保此节点上的所有pod调度到其他节点后,重置此节点。
场景2:

原因:k8s-node1节点的挂载有问题。
解决:节点安装 ceph common,yum -y install ceph-common
场景3:
pod一直处于 pending 状态。
原因:pending是挂起状态,表示创建的pod不能调度到相应的节点。
解决:查看pod是否绑定了node运行节点,节点是否有污点;节点cpu、mem资源是否充足。
场景4:
ImagePullBackOff 状态。
原因:拉镜像有问题。
解决:登陆到对应node节点拉镜像,或者添加镜像认证配置。
场景5:
CrashLoopBackOff 状态。
集群中pod正常运行,但里面的容器可能退出或多次重启或准备删除,导致出现这个状态。
分析:代码问题;环境变量缺失;配置了资源限额,给的资源不足以运行容器。
场景6:
Terminating 或 Unknown 状态
分析:
目前的k8s不会因为node失联而删除其正在运行的pod,而是将其标记为 Terminating 或 Unknown 状态,想要删除pod,可手动删除node,kubectl delete node
可:
- 查看kubectl状态和日志 systemctl status kubelet; journalctl -f -u kubelet
- 查看node节点状态 kubectl get nodes; free -m; df -h
- 查看apiserver是否异常 kubectl get pods -n kube-system | grep apiser
k8s之通信异常【网络故障】
通信分类
集群的通信需要依赖网络插件,如calico、flanne等。网络通信主要有如下几种:
- 容器间的通信(同一个pod内的多个容器间的通信)
- pod通信(从一个pod ip到另一个pod ip)
- pod与service通信(pod ip到cluster ip)
- 外部通信(service与集群外部客户端的通信)
排查示例
pod服务连接超时
描述:
pod内部ping不通www.baidu.com
解决:
centos系统中,查看 /proc/sys/net/bridge/bridge-nf-call-iptables 的值是不是1。如果不是,执行 echo ‘1’ > /proc/sys/net/bridge/bridge-nf-call-iptables
pod应用数据包丢失
描述:
tcpdump抓包显示发送了大量重复的SYN数据包,但没有收到ACK。
解决:
sysctl -p
显示:net.ipv4.ip_forward=0(意味着未开启包转发)
执行:将 net.ipv4.ip_forward=1 添加到 /etc/sysctl.conf 中,sysctl -p 使配置生效。
coredns经常重启和报错
描述:
coredns一直处于 CrashLoopBackOff 状态,查看日志,报错:plugin/loop: Loop (127.0.0.1:44222 -> :53) detected for zone.
分析:
coredns会读取宿主机/etc/resolv.conf中的nameserver内容,查看resolv.conf文件,如果里面存在本地回环如127.0.0.1或127.0.0:53就容易造成死循环。
解决:
将nameserver修改为114.114.114.114,重建coredns pod。
pod和pod通信路由中断
描述:在集群pod中ping另一个pod ip,报错:No route to host
分析:查看calico/flannel日志,如果发现pod网段和node节点机器网段重合,则需要修改pod网段地址。
解决:
#保存现有信息
kubectl get ippool default-ipv4-ippool -o yaml > default-ipv4-ippool.yaml
删除现有信息
kubectl delete default-ipv4-ippool.yaml
修改default-ipv4-ippool.yaml文件中cidr为新cidr
应用
kubectl apply -f default-ipv4-ippool.yaml
后续
修改iptables规则,重启网络插件
增加节点并确认网络
驱逐旧节点上的服务
删除旧的节点
重新加入旧的节点并确认网络
内部域名解析困难
场景1
描述:
安装coredns后,容器内部无法解析集群外的域名。
分析:查看coredns日志,coredns会挂载本地的/etc/resolv.conf文件,查看里面的nameserver是不是114.114.114.114
场景2
描述:
pod基于域名访问基础服务mysql、redis等,经常出现超时,报错如下:
io.netty.resolver.dns.DnsNameResolverTimeoutException: [/10.96.0.10:53] query timed out after 1000 milliseconds(no stack trace available)
分析:
域名解析异常,是pod内部resolv.conf文件有问题,登陆pod查看resolv.conf文件。
解决:
注意nameserver是coredns的cluster ip。searches(搜索域)根据实际环境配置生成的 /etc/resolv.cnf 如下:
nameserver 10.96.0.10
search redis.svc.cluster.local
options test
尝试多次重建pod,问题不再复现。
k8s之内部异常【节点故障】
node故障
场景一
描述:
刚好装好的k8s集群node节点Notready,coreDNS处于pendding状态。
解决:
是因为没有安装网络插件(calico or flannel)。
场景二
描述:
k8s运行一段时间后,node节点是Notready状态。
分析:
1)从物理服务器的环境排查
df -h # 查看磁盘空间使用情况
free -m # 查看内存使用情况
top -c # 查看cpu使用情况
2)通过以上排查发现资源足够,开始从k8s入手排查
kubectl describe node
Output >>
…
Kubelet stoped posting node status
Kubelet never posted node status
…
解决:
根据输出信息可看到,kubelet停止发送node状态。
systemctl status kubelet #查看kubelet服务状态
如果状态为Failed,重启kubelet服务。
为什么要重启kubelet?
- 监视分配给该node节点的pod
- 挂载pod所需要的volumes
- 下载pod的secret
- 通过docker/rkt来运行pod中的容器
- 周期地执行pod中为容器定义的liveness探针
- 上报pod的状态给系统的其他组件
- 上报node的状态
pod故障
pod调度流程
创建Pod过程:
1、用户创建pod的信息通过API Server存储到etcd中
2、调度器通过API Server从etcd中拿到信息并计算,将优先级高的node与pod绑定并告知API Server
3、API Server将此信息写入etcd,得到etcd回复后调用kubelet创建pod
4、kubelet创建pod,得到反馈信息后将其告知API Server
5、API Server将收到的信息写入etcd并得到反馈
6、此时用kubectl get pod就可以查看到信息了
pod污点说明
k8s常见内置污点如下,当某些条件为真时,节点控制器会自动为节点添加污点:
node.kubernetes.io/NoSchedule #如果一个pod没有声明容忍此Taint,则系统不会把该pod调度到有此Taint的node上
node.kubernetes.io/NoExecute #定义pod的驱逐行为,以应对节点故障
node.kubernetes.io/not-ready #节点尚未准备好
node.kubernetes.io/unreachable #无法从节点控制器访问节点
node.kubernetes.io/out-of-disk #节点磁盘不足
node.kubernetes.io/memory-pressure #节点有内存压力
node.kubernetes.io/disk-pressure #节点有磁盘压力
node.kubernetes.io/network-unavailable #节点的网络不可用
node.kubernetes.io/unschedulable #节点不可调度
pod调度故障
#场景一
描述:
机房断电,恢复后,发现pod无法启动。
分析:
kubectl describe pod
Output >>
…
1 node(s) had taints that the pod didn’t tolrate 2 node(s) didn’t match node selector
…
kubectl describe node
Output >>
…
Taints: node.kubernetes.io/unreachable:NoExecute
node.kubernetes.io/unreachable:NoSchedule
…
根据排查可知,因为机器断电重启,k8s集群自动为节点添加了不可被调度污点,导致pod不能调度到node上。
解决:
手动删除node节点上的污点
kubectl taint node
kubectl taint node
查看kubelet状态
systemctl status kubelet
Output >>
…
Active: died since Wed 2022-03-17 11:26:21 CST; 3h 26min ago
…
通过信息可知节点异常导致kubelet没有正常启动,执行重启
systemctl restart kubelet
查看污点是否还存在
kubectl describe node
输出信息可得node污点信息已清除,pod可以正常被调度了。
#场景二
描述:
pod数量太多超过节点资源限制
分析:
监控系统发出报警,大量pod在批量重启,且部分pod处于pending状态。
排查思路:
1)查看pod信息
kubectl describe pod
Output >>
…
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exxists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exxists for 300s
…
2)查看node信息
kubectl describe node
Output >>
…
Warning SystemOOM 78s kubelet System OOM encountered, victim process: java, pid :6095
…
3)查看kubelet
systemctl status kubelet
Output >>
…
20809 kubelet_pods.go:880] Unable to retrieve pull secret ms/registry-pull-secret for ms/en…
…
4)查看节点资源
$ free -m #内存正常
$ df -h #看到产生大量的目录
在k8s中每创建一个pod,都会生成上面的一个目录,可以发现可能是pod数量太多导致节点出现问题。
5)查看node节点现有pod的数量
kubectl get pods -A |grep
Output >>
108
因为k8s每个节点默认只能启动110个pod,现在某个node节点启动了108个。
解决:
可以调整可运行的pod数量,在kubelet中增加启动参数:—max-pods=300
重启生效
systemctl daemon-reload
systemctl restart kubelet
#场景三
描述:
Pod资源超过node节点资源限制。
分析:
在部署过程中,pod一直处于pending状态,查看具体描述,显示如下信息:
…
default-scheduler 0/2 nodes are available: 1 Insufficient memory, 1 node(s) had taint [node-role.kubernetes.io/master: ], that the pod didn’t tolerate.
…
解决:
增加node节点配置或者添加node节点到集群。
k8s之应用故障【应用异常】
概念
Service
在k8s中,Pod是有生命周期的,如果Pod重启IP很可能发生变化。如果服务都是将Pod的IP地址写死,Pod重启后其关联的服务会找不到关联的Pod。为了解决这个问题,定义了Service资源对象,一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例,Service是一组Pod的逻辑集合,这一组Pod能被Service访问到,通常是通过Label Selector实现。
kube-proxy
service为一组相同的pod提供了统一的入口,起到负载均衡的作用,svc具有这样的功能正是kube-proxy的功劳,kube-proxy是一个代理,安装在每个节点,当在暴露一个svc的时候,kube-proxy会在iptables中追加一些规则,实现路由与负载均衡的功能。
异常示例
svc访问异常
描述:
某个服务的svc访问异常。
排查:
$ kubeclt describe svc myapp
Name: myapp
Namespace: default
Labels:
Annotations:
Selector: app=myapp,version=1
IP: 10.98.1.137
Port: 80/TCP
Endpoints:
通过Endpoints的值为none可知并没有关联到pod,修改yaml资源文件,将Selector信息对应补全重新apply即可。
kube-proxy异常
查看pod状态
$ kubectl get po -o wide
查看到svc也通过标签选择器关联到了pod,且有Endpoints
$ kubectl describe svc myapp-v1-service
查看iptables(10.109.72.235是svc的cluster ip)
$ iptables -t nat -L |grep 10.109.72.235

$ kubectl get pods -owide

$ iptables -t nat -L |grep 10.244.103.5

通过分析可知,kube-proxy会为暴露svc追加iptables规则,具体流程如下:
1、所有进出请求都会经过 KUBE-SERVICES 链
2、KUBE-SERVICES 链有发布的每一个服务,每个服务的链会对应到DNAT到service的endpoint
3、KUBE-SERVICES链最后的是KUBE-NODEPORTS链,会匹配请求本主机的一些端口,这就是通过NODEPORT类型发布服务能在集群外部访问的原因
通过分析,svc和pod关联正常,pod也处于running状态,那请求svc访问不到pod,很可能就是kube-proxy引起。
查看kube-proxy状态(服务已启动)
$ ps -ef |grep kube-proxy

查看kube-proxy日志
$ cat /var/log/messages | grep kube-proxy

根据日志可判断是由于内存溢出和内核崩溃,导致系统主动kill进程。
查看kube-proxy占用的资源
$ kubectl top pods -n kube-system |grep proxy

按需修改kube-proxy的资源配额,问题解决。
pod | ns无法正常删除
在k8s中,可能会产生很多垃圾pod,也就是有些pod虽然是running状态,可是其所调度到的node节点已经从k8s集群剔除了,但是通过命令kubectl get pod -o wide查看到pod还是显示在被剔除的node上,没有被驱逐,针对这种情况就需要把pod删除。
Pod删除的方式:
1、删除pod所在的namespace
2、如果pod是通过控制器管理,可以删除控制器资源
3、如果pod是自主式管理,直接删除pod资源
有时在删除pod资源的时候,pod会一直terminate状态,长时间无法删除。可执行强制删除命令:kubectl delete pod
说明:—grace-period表示过渡存活期,默认30s,在删除pod前允许pod慢慢终止其里面的容器进程,从而优雅退出。
但是在删除namespace时,加了参数—force —grace-period=0,可能ns还是terminate状态。强制删除参考如下方式:
a)获取ns的json文件
$ kubectl get ns crab -ojson > crab.json
$ cat crab.json
b)修改crab.json文件,删除 “finalizers:[kubernetes]” 内容
c)调用api-server接口进行删除
打开新终端,执行 kubectl proxy —port=8001
curl -k -H “Content-Type: application/json” -X PUT —data-binary @crab.json http://127.0.0.1:8001/api/v1/namespaces/crab/finalize
d)如果kubectl get ns crab -ojson的结果中 “spec”:{} 中为空,则要看metadata部分是否有finalizers字段,如下:
说明:Finalizers是由字符串组成的列表,当Finaizers字段存在时,相关资源不允许被强制删除。
e)把metadata中finalizers的两行删除
$ kubectl edit ns crab #进去后直接删除保存退出即可,处于Terminating状态的ns便没有了
