kubernetesK8S

kubernetes常见故障处理-k8s之应用故障(应用异常)

2022-08-08  本文已影响0人  Chris0Yang

1.k8s中的service概念和pod的匹配情况

故障排查: Service访问异常
Service是什么?为什么容易出现问题?
在kubernetes中, Pod是有生命周期的,如果Pod重启IP很有可能会发生变化,如果我们的服务都是将Pod的IP地址写死, Pod的挂掉或者重启,和刚才重启的pod相关联的其他服务将会找不到它所关联的Pod,为了解决这个问题,在kubernetes中定义了service资源对象, Service定义了一个服务访问的入口,客户端通过这个入口即可访问服务背后的应用集群实例, Service是一组Pod的逻辑集合,这一组Pod能够被Service 访问到,通常是通过Label Selector实现的。

2.k8s中service访问异常的常见问题

1)service没有正确匹配到后端的pod标签

(1).service匹配的label标签没有匹配上后面的pod(导致访问不到界面)
(2).service匹配的label标签匹配到后面其他错误的pod(导致访问的别的界面)

2)kube-proxy服务故障导致service无法提供服务
kube-proxy是什么:
Service为一组相同的pod提供了统一的入口,起到负载均衡的效果。Service具有这样的功能,真是kube-proxy的功劳,kube-proxy是一个代理,安装在每一个k8s节点,当我们暴露一个service的时候,kube-proxy会在iptables中追加一些规则,为我们实现路由与负载均衡的功能。
kube-proxy的两种转发规则: iptables(DNAT规则转发到后台pod)和ipvs

故障现象:
service的标签选择器正常,pod也正常,但是访问service的ip时,还是代理不到pod,就需要检查kube-proxy组件。

解决思路:

(1).查看相应node节点kube-proxy服务是否正常。
(2).查看相应node节点上kube-proxy相关日志,有没有报错,资源不足,如:cpu/内存/磁盘
(3)查看相应node节点上系统日志中有没有关于kube-proxy的日志报错.
cat /var/log/messages[kube-proxy] |grep kube-proxy或 kubectl logs pod名 |grep kube-proxy

解决方法:

(1).扩容节点资源,增加服务器或者虚拟机的cpu和内存。
(2).修改kube-proxy的yaml中的limit资源限制,限制可使用的cpu和内存。

故障排查: Service访问异常
上面直接请求service的ip报异常,那么我们查看下对应的service详细信息

[root@k8s-master01 ~]# kubectl describe svc/kubernetes
......
Selector:          app=myapp1, version=v2
IP:                10.96.0.1
......
Events:            <none>

通过上面信息可以看到Endpoint处的值为none,说明没有关联到pod,那么我们前面说过,service跟pod关联是靠标签选择器的,上面service写的标签选择器是Selector: app=myapp1, version=v2,而我们在创建pod时候给pod的标签是app=myapp, version=v1,这样大家应该就发现问题了,是因为我们在创建service的时候,标签选择器没有选择拥有跟其匹配的pod, 修改service.yaml, 把Selector: app=myapp1, version=v2成Selector: app=myapp, version=v1, 重新kubectl apply -f service, yaml更新, 再请求service ip就可以正常访问了。

[root@k8s-master01 ~]# ping 10.96.0.1
PING 10.96.0.1 (10.96.0.1) 56(84) bytes of data.
64 bytes from 10.96.0.1: icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from 10.96.0.1: icmp_seq=2 ttl=64 time=0.039 ms

常见的service异常;
故障概述一:service没有正确关联pod
1、试图请求下pod ip,看是否有返回值

[root@k8s-master01 ~]# curl IP地址

2、直接请求pod ip没问题,可以访问,接下来请求上面pod前端的service,看能否请求成功

[root@k8s-master01 ~]# curl 10.96.0.1
curl: (7) Failed connect to 10.96.0.1:80; Connection refused

故障概述二:kube-proxy异常

[root@k8s-master01 test-yaml01]# kubectl get pod -o wide -n dev03
NAME                  READY   STATUS    RESTARTS   AGE   IP             NODE           
nginx-statefulset-0   1/1     Running   0          38s   10.244.0.124   k8s-master01   
nginx-statefulset-1   1/1     Running   0          20s   10.244.0.125   k8s-master01   
nginx-statefulset-2   1/1     Running   0          18s   10.244.0.126   k8s-master01 

Service也通过标签选择器关联到了pod,而且也有Endpoint
pod正常运行

[root@k8s-master01 test-yaml01]# kubectl describe svc/nginx -n dev03
Name:                     nginx
Namespace:                dev03
Annotations:              <none>
Selector:                 app=myapp, version=v1
Type:                     NodePort
IP:                       10.101.93.77
Port:                     web  80/TCP
TargetPort:               80/TCP
NodePort:                 web  8081/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

kube proxy是什么?
service 为一组相同的pod提供了统一的入口,起到负载均衡的败果,service具有这样的功能,正是kube-proxy的功劳,kube-proxy是一个代理,安装在每一个k8s节点,当我们暴露一个service 的时候, kube-proxy 会在iptables中追加一些规则,为我们实现路由与负载均衡的功能。

[root@k8s-master01 test-yaml01]# iptables -t nat -L|grep 10.101.93.77
....

通过上面可以看到之前创建的service,会通过kube-proxy 在iptables中生成一个规则,来实现流量路由。

故障排查:
经过上面的分析,service和pod正确关联,pod也处手运行状态,那请求service还是访问不到pod, 90%就是kube-proxy引起的。
查看kube-proxy是否在机器上透行:

[root@k8s-master01 ~]# ps auxw |grep kube-proxy
root     2044282  0.0  0.0 115928  1008 pts/1    S+   11:14   0:00 grep --color=auto kube-proxy

[root@k8s-node01 ~]# ps auxw |grep kube-proxy
root     1944178  0.0  0.0 115932  1004 pts/0    S+   11:16   0:00 grep --color=auto kube-proxy

上面可以看到,kube-proxy正在节点上于行,下一步,确认它有没有出现其他异常,比如连接主节点失败。要做到这一点,必须查看目志;/var/log/messages kube-proxy.log,也使用journalctl访问目志,应该看到类似的东西;

cat /var/log/messages |grep kube-proxy

如果日志看到oom-killerComm: kube-proxy Kdump
可以判断是由于内存溢出和内核崩清,导致系统主动kill进程

1)扩容节点资源,增加服务器成者虚拟机的cpu和内存
2)修改kube-proxy的limit,限制可使用的cpu和内存
resources:
  requests:
    cpu: 100m
    memory: 2000Mi
  limits:
    memory: 1Gi

3.k8s中pod删除失败的解决

故障现象:在k8s中,可能会产生很多垃圾pod,也就是有些pod虽然是running状态,可是其所调度到的k8s的node节点已经从k8s集群删除了,但是pod还是在这个node上,没有被驱逐,针对这种情况就需要把pod删除。

故障描述:删除pod时候,pod一直处于terminate状态,很长时间无法删除。
解决方案:在k8s中,可能会产生很多垃圾pod,也就是有些pod虽然是running扶态,可是其所调度到的k8s node节点已经从k8s集群删除了,但是pod还是在这个node上,没有被驱逐,针对这种情况就需把pod手动执行命令删除。

删除pod的几种办法:

1)删除pod所在namespace
2)如果pod是通过控制器管理的,可以删除控制器资源
3)如何pod是自主式管理,直接删除pod资源就可以了

但是我们常常遇见这样一种情况,我们在删除pod资源的时候, pod会一直.terminate状态,很长时间无法删除。

kubectl delete pod pod名 --force --grace-period=0

4.k8s中命名空间的强制删除

虽然pod可以强制删除,但是可能命名空间还是处于terminate状态,无法删除。
解决方法:

1)强制删除命名空间
kubectl delete ns 命名空间 --force --grace-period=0

2)获取namespace的json文件,删除相关内容
kubectl get ns 命名空间 -o json > /root/xx.json
vim /root/xx.json
删除spec下的`finalizers`:[ 和`kubernetes` 内容
调用api-server接口进行删除:
打开一个新的终端,或者把下面的命令放到后台执行: 
kubectl proxy --port=8081

调用接口删除:
curl -k -H "Content-Type: application/json" -X PUT --data-binary @xx.json
http://127.0.0.1:8081/api/v1/namespaces/命名空间名/finalize
如果kubectl get ns 命名空间 -o json的结果中`spec`:{}中为空了,但是metadata部分还有finalizers字段
需要将里面相关finalizers的内容也删除。

kubectl edit ns 命名空间
进去后,直接删除相关finalizers的内容即可,保存退出后,出入Terminating状态的ns便没有了。

5.k8s中跨主机连接不通(pod和pod)

1.pause容器概念:
Pause容器,又叫Infra容器,Pause容器对应的镜像属于k8s平台的一部分,除了pause容器,每个pod还包含一个或者多个紧密相关的用户业务容器。

2.pause容器的作用:

(1).pod里的多个业务容器共享pause容器的ip,共享pause容器挂载的volume,这样简化了业务容器之间的通信问题,也解决了容器之间的问题件共享问题。
(2).pod中的容器共享同一个ip地址。故同一个pod中container可以做到直接通过localhost直接通信。

3.同一个节点多个pod通信机制:
pause容器启动之前,会为容器创建虚拟一对ethernet接口,一个保留在宿主机vethxxx(插在网桥上),一个保留在容器网络命名空间内,并重命名为eth0。两个虚拟接口的两端,从一端进入,从另一端出来。任何pod连接到该网桥的pod都可以收发数据。

4.跨节点pod通信机制:
跨节点pod通信,相当于创建一个整个集群公用的 [网桥] ,然后把集群中所有的pod连接起来,就可以通信了。

5.跨主机连接不通(pod和pod)的故障排查方法:

1).排查宿主机网络是否正常,在宿主机上ping www.baidu.com,或tcpdump抓包看是否丢包.
2).查看k8s中的网络插件是否正常,查看网络组件calico或flannel的日志。
上一篇下一篇

猜你喜欢

热点阅读