k8s域名,K8s拉起容器无法域名访问外网

阅读(145)发布于 2023-09-25

09-kubernetes中的域名解析流程 从Kubernetes1.11版本开始,Kubernetes集群的DNS服务由CoreDNS提供。pod的resolv.conf文件主要有三个部分,分别为nameserver、search和option。search域 resolv.conf文件的第二行指定的是DNSsearch域。K8s中默认的配置是5。也就是说,如果我访问的是a.b.c.e.f.g,那么域名查找的顺序如下: 通过svc访问 在K8s中,Pod之间通过svc访问的时候,会经过DNS域名解析,再拿到ip通信。而K8s的域名全称为"..svc.cluster.local",而我们通常只需将svcname当成域名就能访问到pod,这一点通过上面的域名解析过程并不难理解。

配图

从Kubernetes1.11版本开始,Kubernetes集群的DNS服务由CoreDNS提供。CoreDNS是CNCF基金会的一个项目,是用Go语言实现的高性能、插件式、易扩展的DNS服务端。CoreDNS解决了KubeDNS的一些问题,例如dnsmasq的安全漏洞、externalName不能使用stubDomains设置,等等。

CoreDNS支持自定义DNS记录及配置upstreamDNSServer,可以统一管理Kubernetes基于服务的内部DNS和数据中心的物理DNS。

CoreDNS没有使用多个容器的架构,只用一个容器便实现了KubeDNS内3个容器的全部功能。

从kubernetes官方提供的coredns.yml文件中,不难看出coredns服务配置至少需要一个ConfigMap、一个Deployment和一个Service共3个资源对象。ConfigMapcoredns主要配置文件Corefile的内容:

其中主要有二个地方来解析配置

1、这段配置的意思是cluster.local后缀的域名都是kubernetes内部域名,coredns会监控service的变化来修改域名的记录

2、如果coredns没有找到dns记录,则去找/etc/resolv.conf中的nameserver解析

接下来使用一个带有nslookup工具的Pod来验证DNS服务能否正常工作:

通过nslookup进行测试。

查找defaul命名空间存在的ng-deploy-80服务

如果某个Service属于不同的命名空间,那么在进行Service查找时,需要补充Namespace的名称,组合成完整的域名。下面以查找kubernetes-dashboard服务为例,

众所周知,DNS服务器用于将域名转换为IP(具体为啥要转换建议复习下7层网络模型).Linux服务器中DNS解析配置位于/etc/resolv.conf,在Pod中也不例外,

DNS策略可以逐个Pod来设定。当前kubernetes支持这4中DNS策略

如果我们不填dnsPolicy,默认策略就是ClusterFirst。

kubelet在起pause容器的时候,会将其DNS解析配置初始化成集群内的配置。配置:它的nameserver就是指向coredns的

k8s里面有4种DNS策略,而coredns使用的DNS策略就是Default,这个策略的意思就是继承宿主机上的/etc/resolve.conf,所以corednsPod里面的/etc/resolve.conf的内容就是宿主机上的内容。

在集群中pod之间互相用svcname访问的时候,会根据resolv.conf文件的DNS配置来解析域名,下面来分析具体的过程。

pod的resolv.conf文件主要有三个部分,分别为nameserver、search和option。而这三个部分可以由K8s指定,也可以通过pod.spec.dnsConfig字段自定义。

nameserver

resolv.conf文件的第一行nameserver指定的是DNS服务的IP,这里就是coreDNS的

clusterIP:

也就是说所有域名的解析,都要经过coreDNS的虚拟IP10.100.0.2进行解析,不论是内部域还是外部域名。

search域

resolv.conf文件的第二行指定的是DNSsearch域。解析域名的时候,将要访问的域名依次带入search域,进行DNS查询。

比如我要在刚才那个pod中访问一个域名为ng-deploy-80的服务,其进行的DNS域名查询的顺序是:

options

resolv.conf文件的第三行指定的是其他项,最常见的是dnots。dnots指的是如果查询的域名包含的点“.”小于5,则先走search域,再用绝对域名;如果查询的域名包含点数大于或等于5,则先用绝对域名,再走search域。K8s中默认的配置是5。

也就是说,如果我访问的是a.b.c.e.f.g,那么域名查找的顺序如下:

通过svc访问

在K8s中,Pod之间通过svc访问的时候,会经过DNS域名解析,再拿到ip通信。而K8s的域名全称为"<service-name>.<namespace>.svc.cluster.local",而我们通常只需将svcname当成域名就能访问到pod,这一点通过上面的域名解析过程并不难理解。

参考

(1)K8S落地实践之服务发现(CoreDNS)

https://blog.51cto.com/u_12965094/2641238

(2)自定义DNS服务

https://kubernetes.io/zh/docs/tasks/administer-cluster/dns-custom-nameservers/

(3)Kubernetes服务发现之coreDNS

https://juejin.cn/post/6844903965520297991

(4)Kubernetes集群DNS服务发现原理

https://developer.aliyun.com/article/779121

(5)Kubernetes之服务发现和域名解析过程分析

https://www.jianshu.com/p/80ad7ff37744

这里涉及两个知识点。第一个是ingress,第二个是externaldomains。ingress大家可能比较熟悉,比如下面的配置,访问hello-world.info的域名,请求”/“目录,将会把请求转发到web这个服务。

externaldomains大家可能不经常使用,这个是k8s提供的CNAME能力,比如下面通过外部域名的功能,为my-service的域名增加一个my.database.example.com的CNAME,这样当我们在容器里面访问my-service域名的时候,域名解析到CNAMEmy.database.example.com,从而将请求转发到my.database.example.com。

但外部域名有个小问题,就是它只是重定向域名,并不会修改HTTPheader,这就导致一个问题:请求url里面域名和header中的域名不一致。而ingress大部分都是HTTP请求。比如下面service的定义。

当通过my-sample.com请求ingress的时候,ingress转发请求的时候,HTTPHOSTheader还是my-sample.com,但上面设置的外部域名是example.com,这就导致不一致了,nginx无法转发流量。

但我们还可以通过nginx.ingress.kubernetes.io/upstream-vhost这个annotation修改我们的请求header,如上面例子,我们将请求header的HOST修改成example.com就可以成功请求了。

1.问题描述

问题表面原因:

在coredns默认配置下,proxy./etc/resolv.conf

在Poc部署环境中,经常出现在/etc/resolv.conf中没有配置域名的情况,会出现coredns报错的情况:

2.原因分析

在coredns中,默认有fallthrough的配置

coredns默认配置会将反向地址解析传到配置外部DNS,默认外部DNS为8.8.8.8,会导致反向地址解析要经过超时才有返回。

当而有组件会自动进行反向地址解析,会导致访问超时。

平台组件存在进行反向地址解析的操作,所以导致平台访问变慢。

3.解决方案(任选一个)

3.1.注释掉fallthrough

3.2.配置正确的外部DNS

问题2:

出现某个域名在某个节点上解析不通,排障思路,进去cordnspod中nslookup该域名,如果通说明pod解析没问题,如果不通则在集群svcip层面进行nslookup,如果不通那么是svc层面问题,进入到节点,一般为kubeletdns解析出现问题

解决方法:

1、删除原先coredns的配置(随后重启即可)2、部署coredns3.删除原先的pod、service、重新创建。

最近新拉了一个K8s1.17版本的集群,由于服务器资源有限,只有一个Master和一个Minion,就把Master设置为可分配业务Pod。

由于Master和Minion为同性质工作,后来重启K8s集群的时候,有一个CoreDNS被分配到了Minion主机上。

当时也没太留意,只是在启动一个服务的时候,发现只能访问外网的IP,不能通过域名方面,感觉好奇怪。

查看了下/etc/resolv.conf里面的配置啥的也都正确,按理来说不应该出现问题。

由于用的是Centos7操作系统,就把Firewalld给关闭了尝试下,就可以正常通过域名访问,由此可见还是Firewalld给拦截了。

考虑到Firewalld的拦截,很奇怪,因为我们的pod是访问外网,不是外面访问它,应该不是开放端口的问题,最后查看了下宿主机上的NAT路由转发,结果发现,Master上的处于开启状态,Minion上的处于关闭状态,怪不得无法访问外网的域名服务器进行域名的正常解析,开启后,一切正常。

以上就是关于k8s域名的解答,如果对你有帮助,不妨关注本站,本站将为你整理更多内容。