kubernetes常见故障处理-k8s之应用故障(应用异常)
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-killer
和 Comm: 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的日志。