DNS
K8s 中的 DNS 解析流程
Pod → 本节点 nodelocaldns → CoreDNS → 外部上游- 本节点 nodelocaldns 为容器 /etc/resolv.conf 文件中 nameserver 所定义的 IP
nodelocaldns
每个 Node 上会以 DaemonSet 形式运行一个 nodelocaldns(本地 DNS 缓存代理)
该 Pod 监听地址通常为 169.254.25.10:53 以及 ::ffff:169.254.25.10:53
- 该 IP 源自于 kubelet 的配置参数
这个本地缓存代理再把请求向上游转发(上游通常就是 CoreDNS 的 ClusterIP)
CoreDNS
- CoreDNS 是 k8s 的核心插件,提供了 DNS 和 Serviec Discover 功能;
- Serviec Discover 可以动态发现 endpoint 中的 pod 列表,从而实现动态添加和删除相关解析记录。
- CoreDNS 将传统的DNS服务直接提供一个云原生解决方案,他支持从apiserver动态加载相关的service及端点信息,并自动生成资源记录。
# kubectl get pod -n kube-system -l k8s-app=kube-dns
NAME READY STATUS RESTARTS AGE
coredns-65c54cc984-8sfk8 1/1 Running 35 (43h ago) 104d
coredns-65c54cc984-fpv5f 1/1 Running 35 (43h ago) 104d
# kubectl describe svc -n kube-system kube-dns
Name: kube-dns
Namespace: kube-system
Labels: k8s-app=kube-dns
kubernetes.io/cluster-service=true
kubernetes.io/name=CoreDNS
Annotations: prometheus.io/port: 9153
prometheus.io/scrape: true
Selector: k8s-app=kube-dns
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.0.10 # 默认为10.96.0.10
IPs: 10.96.0.10
Port: dns 53/UDP
TargetPort: 53/UDP
Endpoints: 10.244.0.74:53,10.244.0.75:53
Port: dns-tcp 53/TCP
TargetPort: 53/TCP
Endpoints: 10.244.0.74:53,10.244.0.75:53
Port: metrics 9153/TCP
TargetPort: 9153/TCP
Endpoints: 10.244.0.74:9153,10.244.0.75:9153
Session Affinity: None
Events: <none>参考文档:
配置文件
# kubectl get configmap coredns -n kube-system -o yaml
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
...- CoreDNS 监听地址和端口: CoreDNS 配置文件中的
.:53指定了 CoreDNS 的监听地址和端口。这表示 CoreDNS 将监听默认的 DNS 端口 53,以接收 DNS 查询请求。 - 健康检查和就绪状态: 配置中的
health块定义了健康检查相关的配置,其中lameduck 5s表示在关闭 CoreDNS 之前等待 5 秒钟,以确保正在进行的 DNS 查询能够完成。ready表示 CoreDNS 将提供就绪状态检查的端点。 - Kubernetes 集群的 DNS 配置:
kubernetes块定义了对 Kubernetes 集群的 DNS 配置。其中的cluster.local是默认的域名后缀,用于解析集群内的服务和 Pod。pods insecure表示可以通过直接使用 Pod 名称进行 DNS 查询,而不需要完全限定的域名。fallthrough in-addr.arpa ip6.arpa表示对于逆向 DNS 查询(反向解析),将继续使用in-addr.arpa和ip6.arpa域名。ttl 30表示 DNS 解析结果的 TTL(Time to Live)为 30 秒。 - Prometheus 指标暴露:
prometheus :9153表示 CoreDNS 将在端口 9153 上暴露 Prometheus 指标,以供监控和指标收集。 - DNS 解析的转发:
forward . /etc/resolv.conf表示 CoreDNS 将对于除了本地区域的 DNS 查询请求转发到/etc/resolv.conf文件中指定的上游 DNS 服务器。max_concurrent 1000表示最大并发转发请求数为 1000。 - DNS 缓存和其他功能:
cache 30表示启用 DNS 缓存,并设置缓存的 TTL 为 30 秒。loop表示启用 DNS 循环查询,以支持循环引用的 DNS 配置。reload表示启用动态配置重载。loadbalance表示启用负载均衡功能。
默认资源记录类型
- CoreDNS 对于每个Service对象,都会具有以下3个类型的DNS资源记录。
A & AAAA
- 根据 ClusterIP 的地址类型,为 IPv4 生成 A 记录,为 IPv6 生成 AAAA 记录;
- service_name –> service_ip
# A
<service>.<ns>.svc.<zone>. <ttl> IN A <cluster-ip>
# AAAA
<service>.<ns>.svc.<zone>. <ttl> IN AAAA <cluster-ip>范例:
- 环境说明
# kubectl describe service demoapp-svc
Name: demoapp-svc
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=demoapp
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.99.152.124
IPs: 10.99.152.124
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.13:80,10.244.1.14:80,10.244.1.15:80
Session Affinity: None
Events: <none>
# 在不同的名称空间中创建pod测试
# kubectl create ns testns
namespace/testns created
# kubectl run testpod --image=ikubernetes/demoapp:v1.0 -n testns
pod/testpod created- 测试
# kubectl exec -it -n testns testpod -- sh
# 获取zone(k8s.xiangzheng.com)
[root@testpod /]# cat /etc/resolv.conf
nameserver 10.96.0.10
search testns.svc.k8s.xiangzheng.com svc.k8s.xiangzheng.com k8s.xiangzheng.com
options ndots:5
# 测试
[root@testpod /]# nslookup -q=a demoapp-svc.default.svc.k8s.xiangzheng.com
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: demoapp-svc.default.svc.k8s.xiangzheng.com
Address: 10.99.152.124
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.16, ServerName: demoapp-65bc49b76-n8rv9, ServerIP: 10.244.1.15!
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.16, ServerName: demoapp-65bc49b76-t782v, ServerIP: 10.244.1.14!
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
iKubernetes demoapp v1.0 !! ClientIP: 10.244.1.16, ServerName: demoapp-65bc49b76-c5fst, ServerIP: 10.244.1.13!
[root@testpod /]# curl demoapp-svc.default.svc.k8s.xiangzheng.com
# coredns内部生成的解析记录格式:
demoapp-svc.default.svc.k8s.xiangzheng.com. 30 IN A 10.99.152.124SRV
- 主要负责端口解析
- 为每个定义了名称的端口生成一个SRV记录,未命名的端口号则不具有该记录;
_<port>._<proto>.<service>.<ns>.svc.<zone>. <ttl> IN SRV <weight> <priority> <port-number> <service>.<ns>.svc.<zone>.
PTR
- service_ip –> service_name
- 对于每个给定的A记录(例如a.b.c.d)或AAAA记录(例如a1a2a3a4:b1b2b3b4:c1c2c3c4:d1d2d3d4:e1e2e3e4:f1f2f3f4:g1g2g3g4:h1h2h3h4)都要生成PTR记录,它们各自的格式如下所示:
# A
<d>.<c>.<b>.<a>.in-addr.arpa. <ttl> IN PTR <service>.<ns>.svc.<zone>.
# AAAA
h4.h3.h2.h1.g4.g3.g2.g1.f4.f3.f2.f1.e4.e3.e2.e1.d4.d3.d2.d1.c4.c3.c2.c1.b4.b3.b2.b1.a4.a3.a2.a1.ip6.arpa <ttl> IN PTR <service>.<ns>.svc.<zone>.范例:
- 环境说明
# kubectl describe service demoapp-svc
Name: demoapp-svc
Namespace: default
Labels: <none>
Annotations: <none>
Selector: app=demoapp
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.99.152.124
IPs: 10.99.152.124
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.13:80,10.244.1.14:80,10.244.1.15:80
Session Affinity: None
Events: <none>
# 在不同的名称空间中创建pod测试
# kubectl create ns testns
namespace/testns created
# kubectl run testpod --image=ikubernetes/demoapp:v1.0 -n testns
pod/testpod created- 测试
# kubectl exec -it -n testns testpod -- sh
# 获取zone(k8s.xiangzheng.com)
[root@testpod /]# cat /etc/resolv.conf
nameserver 10.96.0.10
search testns.svc.k8s.xiangzheng.com svc.k8s.xiangzheng.com k8s.xiangzheng.com
options ndots:5
# 正向解析获取到serviceIP
[root@testpod /]# nslookup -q=a demoapp-svc.default.svc.k8s.xiangzheng.com
Server: 10.96.0.10
Address: 10.96.0.10#53
Name: demoapp-svc.default.svc.k8s.xiangzheng.com
Address: 10.99.152.124
# 反向解析获取到serviceIP对应的name
[root@testpod /]# nslookup -q=ptr 10.99.152.124
Server: 10.96.0.10
Address: 10.96.0.10#53
124.152.99.10.in-addr.arpa name = demoapp-svc.default.svc.k8s.xiangzheng.com.
# coredns内部生成的解析记录格式:
124.152.99.10.in-addr.arpa. 30 IN PTR demoapp-svc.default.svc.k8s.xiangzheng.com.默认行为说明
例如,在 default 名称空间中创建 Service 对象 demoapp-svc 的地址为 10.97.72.1,且为 TCP 协议的 80 端口取名 http,对于默认的 cluster.local 域名来说,此它会拥有如下3个 DNS 资源记录。
# A记录:
demoapp-svc.default.svc.cluster.local. 30 IN A 10.97.72.1
# SRV记录:
_http._tcp.demoapp-svc.default.svc.cluster.local. 30 IN SRV 0 100 80 demoapp-svc.default.svc.cluster.local.
# PTR记录:
1.72.97.10.in-addr.arpa. 30 IN PTR demoapp-svc.default.svc.cluster.local.注意事项
CoreDNS配置文件中的转发策略(forward XXX{XXX})一定要指向企业内部的DNS服务器,而非公网的DNS,否则一些内网域名将无法解析
- 如:数据库存放在外部,而数据的访问都是从企业内部的DNS服务器来进行名字解析从而进行访问的
FAQ
如何查询K8s集群域名?
- 大多数的集群域名为
cluster.local,如不确定,可通过以下方式查看:
# 方法一:通过 CoreDNS 的 ConfigMap 查看
$ kubectl -n kube-system get cm coredns -o jsonpath='{.data.Corefile}'
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa { # cluster.local 就是集群域名。
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
# 方法二:查看某个 Pod 中的 resolv.conf 文件
$ kubectl exec -n harbor harbor-nginx-5ff8c5896d-69sjh -- cat /etc/resolv.conf
nameserver 169.254.25.10
search harbor.svc.cluster.local svc.cluster.local cluster.local
options ndots:5如何通过域名访问 service?
# 域名格式如下:
<service_name>.<namespace>.svc.<zone> # <zone>为集群本地域名,例如 cluster.local,例如 prometheus-server.monitoring.svc.cluster.local
# 验证方式
$ nslookup prometheus-server.monitoring.svc.cluster.local $(kubectl get svc -n kube-system | grep coredns | awk '{print $3}')
Server: 10.233.0.3
Address: 10.233.0.3#53
Name: prometheus-server.monitoring.svc.cluster.local
Address: 10.233.11.201
$ kubectl get svc -n monitoring | grep prometheus-server
prometheus-server NodePort 10.233.11.201 <none> 80:30036/TCP 642d