coredns-什么时候能解析到pod ip

2,173 阅读2分钟

我们知道k8s的文档Kubernetes DNS-Based Service Discovery Specification 规定了k8s 的dns 实现规范

但有个细节他没有设定规范,就是 如果service 是ClusterIp的时候pod的dns如何解析

我们目前用的应该都是coredns了(如果你还是kube-dns,对不起,你可以不用看了😄) dns 在实现的时候讨论过https://github.com/coredns/coredns/issues/729 他的实现是保持了clusterip类型的service 同headless service具有相同的解析行为

结论: 如果你想解析pod ip,在coredns作为dns时,你需要为pod配置Hostname和Subdomain并且有一个name等于Subdomain的service(类型不限,但个人建议为了避免出问题还是推荐写成headless service),就能通过<Hostname>.<Subdomain>.<namespace>.svc.cluster.local的形式解析到 pod ip --如果你是statefuleSet,设定了serviceName后这两个变量会自动加入到pod内

如果没兴趣就不用看了,如果想看原因请继续

代码分析

kubernetes: 1.18版本
coredns: 1.6.9之前版本
之前的coredns 源码解析中介绍了 coredns 插件的加载方式 当一个新的 dns 发送解析请求后(假如你的coredns 在127.0.0.1:553上 dig @127.0.0.1 -p 553 busybox-1.default-subdomain.default.svc.cluster.local),会流转到kubernetes插件的Services方法,

我们以查询格式是(busybox-1.default-subdomain.default.svc.cluster.local)来分析,因为是查询service的某个pod的A记录,所以逻辑到了k.Records(ctx, state, false)k.findServices(r, state.Zone),如下图

这里会根据service name 和 namespace 解析出 service,在此时的r.endpoint 值是"busybox-1",即pod hostname 然后找到service对应的endpoint,判断如果match(r.endpoint, endpointHostname(addr, k.endpointNameMode)) 为真,返回该endpoint

到这里发现能不能返回endpoint 全是endpointHostname这个方法决定,如下

这里的判断发现,如果在endpoint里面有Hostname 就会直接返回Hostname 所以结论就是,如果你以busybox-1.default-subdomain.default.svc.cluster.local查询pod的ip,只要endpoint里面有hostname信息就能查询成功

endpoint 什么时候能返回hostname呢?
看看k8s的代码

在k8s的pkg/controller/endpoint/endpoint_controller.go里面,我们看到了hostname设置相关的代码

可以看出,如果Hostname存在,并且pod的Subdomain和service的name相同 就加入

总:如果你想解析pod ip,在coredns作为dns时,你需要为pod配置Hostname和Subdomain并且有一个name等于Subdomain的service(类型不限),就能通过<Hostname>.<Subdomain>.<namespace>.svc.cluster.local的形式解析到 pod ip