一次k8s 某一个node 上 pod 访问dns无法解析排查思路

*1.技术背景

1.k8s 版本 1.16.8 
2.cce 集群kube-proxy 网络模式采用lvs 模式
3.网络插件由百度ovs实现.

2问题现象

1.开发反馈Java应用程序启动时候出现无法解析域名问题如下报错:
java.net.UnknownHostException: bcs-apm-collector-grpc-prod.chj.cloud: system error
#以上报错信息很明显应用所在 pod 中无法解析dns 域名

3.排查思路

#打开另一个操作终端进行查看service dns cluster-ip 地址
[root@c-9gG4IHm6-z9AOD9wj ~]# kubectl get service -n kube-system
NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   
kube-dns             ClusterIP   172.16.0.10      <none>        53/UDP,53/TCP,9153/TCP   251d 

2.1 进入出现问题的业务pod检测dns地址是否配置正确

第一步 检查dns配置是否存在异常
#cat /etc/resolv.conf 
nameserver 172.16.0.10 #这个地址是coredns 服务的service  ClusterIP 地址
search prod.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
#以上输出信息得出结论: 以上pod resolv.conf 配置文件中 dns配置正常

第二步 检查pod中是否能访问到cord-dns服务: clusterIP 和53端口 
#进入存在无法解析POd中操作
# telnet 172.16.0.10 53
telnet:  host (172.16.0.10): Connection refused
/ # 
#以上信息输出结论 1.无法访问cord-dns CLUSTER-IP的53端口

#进入正常访问的pod中也进行访问测试
# telnet 172.16.0.10 53
Console escape. Commands are:
 l      go to line mode
 c      go to character mode
 z      suspend telnet
 e      exit telnet
Entering character mode
Escape character is '^]'.
Connection closed by foreign host
#以上信息.结论正常pod访问 coredns 正常
#注意:由于默认的业务镜像中telnet 命令输出方式不同.
#有人在想为什么不使用ping 检查ip地址是否能访问?

#原因:coreDns 的 Service 的 ClusterIP,这个IP是虚拟IP,无法ping,但可以访问

2.2 深入排查问题点 出现问题pod 无法访问coredns CLUSTER-IP端口

分析1:在容器内发请求时,会根据 /etc/resolv.conf 进行解析流程。选择 nameserver  172.16.0.10 进行解析,然后用bcs-apm-collector-grpc-prod.chj.cloud ,依次带入 /etc/resolve.conf 中的 search 域,进行DNS查找.

 结论:不论是 Kubernetes 内部域名还是外部的域名, 都需要使用coredns 虚拟IP 172.16.0.10 进行解析)

分析2:由于k8s 的CLUSTER-IP是通过kube-proxy 创建出来的(默认情况下k8s采用iptable service转发模式,百度CCE使用lvs工作模式,pod请求dns 由kube-proxy service 模式转发至后端coreDns pod中进行解析处理)

 --->以上论证: 1.kube-porxy 出现问题导致无法正常工作导致无法通coredns service LUSTER-IP方式访问.

检查百度kube-proxy 发现kube-proxy 镜像拉取失败导致 kube-proxy没有进行正常工作

#注意:
以上不论哪种,kube-proxy都通过watch的方式监控着kube-APIServer写入etcd中关于Pod的最新状态信息,它一旦检查到一个Pod资源被删除了 或 新建,它将立即将这些变化,反应再iptables 或 ipvs规则中,以便iptables和ipvs在调度Clinet Pod请求到Server Pod时,不会出现Server Pod不存在的情况.

4.解决方案

1.解决kube-proxy 镜像拉取失败导致问题

5.知识扩展

service类型
Service同其他Kubernetes对象一样,也是通过yaml或json文件进行定义。
此外,它和其他Controller对象一样,通过Label Selector来确定一个Service将要使用哪些Pod。

1.ClusterIP模式
用于为集群内Pod访问时,提供的固定访问地址,默认是自动分配地址,可使用ClusterIP关键字指定固定IP.

2.NodePort模式
用于为集群外部访问Service后面Pod提供访问接入端口.
这种类型的service工作流程为:
Client----->NodeIP:NodePort----->ClusterIP:ServicePort----->PodIP:ContainerPort

3.LoadBalancer模式
用于当K8s运行在一个云环境内时,若该云环境支持LBaaS,则此类型可自动触发创建一个软件负载均衡器用于对Service做负载均衡调度.
因为外部所有Client都访问一个NodeIP,该节点的压力将会很大, 而LoadBalancer则可解决这个问题。
而且它还直接动态监测后端Node是否被移除或新增了,然后动态更新调度的节点数。

4.ExternalName模式
用于将集群外部的服务引入到集群内部,在集群内部可直接访问来获取服务。
它的值必须是 FQDN, 此FQDN为集群内部的FQDN, 即: ServiceName.Namespace.Domain.LTD.
然后CoreDNS接受到该FQDN后,能解析出一个CNAME记录, 该别名记录为真正互联网上的域名.
如: www.test.com, 接着CoreDNS在向互联网上的根域DNS解析该域名,获得其真实互联网IP.

Kubernetes DNS 策略

在Kubernetes 中,有4种 DNS 策略,从 Kubernetes 源码中看:
const (
    // DNSClusterFirstWithHostNet indicates that the pod should use cluster DNS
    // first, if it is available, then fall back on the default
    // (as determined by kubelet) DNS settings.
    DNSClusterFirstWithHostNet DNSPolicy = "ClusterFirstWithHostNet"

    // DNSClusterFirst indicates that the pod should use cluster DNS
    // first unless hostNetwork is true, if it is available, then
    // fall back on the default (as determined by kubelet) DNS settings.
    DNSClusterFirst DNSPolicy = "ClusterFirst"

    // DNSDefault indicates that the pod should use the default (as
    // determined by kubelet) DNS settings.
    DNSDefault DNSPolicy = "Default"

    // DNSNone indicates that the pod should use empty DNS settings. DNS
    // parameters such as nameservers and search paths should be defined via
    // DNSConfig.
    DNSNone DNSPolicy = "None"
)

1.None
表示空的DNS设置
这种方式一般用于想要自定义 DNS 配置的场景,而且,往往需要和 dnsConfig 配合一起使用达到自定义 DNS 的目的。

2.Default
有人说 Default 的方式,是使用宿主机的方式,这种说法并不准确。
这种方式,其实是,让 kubelet 来决定使用何种 DNS 策略。而 kubelet 默认的方式,就是使用宿主机的 /etc/resolv.conf(可能这就是有人说使用宿主机的DNS策略的方式吧),但是,kubelet 是可以灵活来配置使用什么文件来进行DNS策略的,我们完全可以使用 kubelet 的参数:–resolv-conf=/etc/resolv.conf 来决定你的DNS解析文件地址。

3.ClusterFirst
这种方式,表示 POD 内的 DNS 使用集群中配置的 DNS 服务,简单来说,就是使用 Kubernetes 中 kubedns 或 coredns 服务进行域名解析。如果解析不成功,才会使用宿主机的 DNS 配置进行解析。

4.ClusterFirstWithHostNet
在某些场景下,我们的 POD 是用 HOST 模式启动的(HOST模式,是共享宿主机网络的),一旦用 HOST 模式,表示这个 POD 中的所有容器,都要使用宿主机的 /etc/resolv.conf 配置

猜你喜欢

转载自blog.51cto.com/breaklinux/2633655