Search K
Appearance
Appearance
熟悉 kubernetes 的人都清楚,集群中存在一种这样的内置资源--statefulset,使用 yaml 创建statefulset 实例时,不知你有没有注意过如下的配置
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
....
serviceName: "nginx"
这里的 serviceName 即是 kubernetes service 类型的一种--headless service,仅创建 service 对象本身,但不为此 service 分配 clusterIP(CLUSTER-IP 为 None)
[root@master01 ~]# kubectl get svc -n kube-system kubelet
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubelet ClusterIP None <none> 10250/TCP,10255/TCP,4194/TCP 32d
无论 Pod IP 是否变化,我们也能通过特定的 DNS 名称访问到对应的后端 rs,这是因为 kubernetes 集群按照特定的规则已经在集群中注册了对应的域名解析
pod_name.svc_name.namespace.svc.cluste.local
这里顺便再提一点 headless service 可能混淆的地方
无论在宿主机也好,容器内也罢,当我们想访问域名对应的服务时,应当遵循如下流程:
那就顺便复习下 DNS 解析流程吧:
DNS 解析分为递归解析和迭代解析
spec.containers.dnsPolicy 共有 4 种类型:
如果 Pod.yaml 未指定 dnsPolicy,则会缺省配置为 ClusterFirst,不是 Default!
当前作为 kubernetes 集群默认的 DNS 服务器,主要负责 kubernetes 集群内部域名解析
从如下的命令可以看出,CoreDNS 在集群中以2副本形式的 Pod 运行,并且拥有对应的 VIP 地址 10.96.0.10
[root@master01 ~]# kubectl get pod -n kube-system -o wide |grep coredns
coredns-65dcc469f7-4tqxd 1/1 Running 14 (7h30m ago) 173d 192.168.59.193 master02 <none> <none>
coredns-65dcc469f7-jzd2t 1/1 Running 14 (7h30m ago) 173d 192.168.59.254 master02 <none> <none>
[root@master01 ~]#
[root@master01 ~]# kubectl get service -n kube-system |grep dns
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 173d
[root@master01 ~]#
[root@master01 ~]# kubectl get ep -n kube-system kube-dns
NAME ENDPOINTS AGE
kube-dns 192.168.59.193:53,192.168.59.254:53,192.168.59.193:53 + 3 more... 173d
问题一:先聊聊 CoreDNS 本身的配置文件
[root@master01 ~]# kubectl get cm -n kube-system coredns -o yaml
apiVersion: v1
data:
Corefile: |
.:53 { # 代表任何服务均可通过 53 端口访问
log # 记录日志的插件,coredns 默认记录域名解析过程中的日志,使用 log plugin 即可开启
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa { # 这里用于区分被解析域名是外部域名还是内部域名,比如以 cluster.local 结尾的域名就是内部域名,不会再执行到下面的 forward 配置
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf { # 转给 coredns 所在 node /etc/resolv.conf 上配置的 DNS 服务器解析
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kind: ConfigMap
metadata:
creationTimestamp: "2023-10-12T15:20:22Z"
name: coredns
namespace: kube-system
resourceVersion: "685077"
uid: ea0fb1ff-4ccb-4747-bbb9-f838bb38b5da
问题二:Pod 内 /etc/resolv.conf 配置
nginx-test-69c8bd774c-4vb5q:~# cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local # 和 ndots 有关,进行域名补全;比如被解析的域名是 aaa,那么则会依次将域名补全为 aaa.default.svc.cluster.local、aaa.svc.cluster.local 等
nameserver 10.96.0.10 # DNS 服务器,这里则是 CoreDNS 的 VIP
options ndots:5 # 5为默认值,当被解析的域名点小于5时,则进行域名补全,否则不进行 search domain 的补全
这里可能会对 ndots:5 不理解,我们再通过下面的例子进行详细说明:
如果被解析域名是 aaa.bbb,此时域名中只有一个点,则依次按照如下域名列表进行 DNS 解析,直到找出 IP 为止
aaa.bbb.default.svc.cluster.local -> aaa.bbb.svc.cluster.local -> aaa.bbb.cluster.local
如果被解析域名是 aaa.bbb.ccc.ddd.eee.fff,此时域名中带有5个点,则只会对1个域名发起解析流程
aaa.bbb.ccc.ddd.eee.fff
从 coredns 的配置文件可以看出,以 cluster.local 结尾的域名均是内部域名
我们通过抓包学习下 Pod 内解析内部域名,一共请求了多少次才最终返回正确的 IP
客户端请求:
nginx-test-7c676c8687-n87dr:~# nslookup nginx.svc.cluster.local 192.168.59.193
Server: 192.168.59.193
Address: 192.168.59.193#53
** server can't find nginx.svc.cluster.local: NXDOMAIN
抓包地点1: coredns 容器内
[root@master02 ~]# tcpdump -ni eth0 udp dst port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
23:16:22.389131 IP 192.168.59.192.55743 > 192.168.59.193.domain: 44433+ A? nginx.svc.cluster.local.default.svc.cluster.local. (67)
23:16:22.390064 IP 192.168.59.192.44490 > 192.168.59.193.domain: 18228+ A? nginx.svc.cluster.local.svc.cluster.local. (59)
23:16:22.390858 IP 192.168.59.192.38502 > 192.168.59.193.domain: 14253+ A? nginx.svc.cluster.local.cluster.local. (55)
23:16:22.391974 IP 192.168.59.192.53675 > 192.168.59.193.domain: 18250+ A? nginx.svc.cluster.local. (41)
抓包地点2: coredns 容器所在宿主机的外部网络网卡
[root@master02 ~]# tcpdump -i ens33 udp dst port 53 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
从上面的结果可以看出:
客户端请求:
nginx-test-7c676c8687-n87dr:~# nslookup baidu.com 192.168.59.193
Server: 192.168.59.193
Address: 192.168.59.193#53
Name: baidu.com
Address: 198.18.0.10
抓包地点1: coredns 容器内
[root@master02 ~]# tcpdump -ni eth0 udp dst port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
23:21:31.350074 IP 192.168.59.192.39253 > 192.168.59.193.domain: 47988+ A? baidu.com.default.svc.cluster.local. (53)
23:21:31.350495 IP 192.168.59.192.60719 > 192.168.59.193.domain: 12040+ A? baidu.com.svc.cluster.local. (45)
23:21:31.350797 IP 192.168.59.192.48859 > 192.168.59.193.domain: 13476+ A? baidu.com.cluster.local. (41)
23:21:31.351074 IP 192.168.59.192.39780 > 192.168.59.193.domain: 45284+ A? baidu.com. (27)
23:21:31.351197 IP 192.168.59.193.38545 > 8.8.8.8.domain: 64169+ A? baidu.com. (27)
23:21:31.354600 IP 192.168.59.192.37797 > 192.168.59.193.domain: 12629+ AAAA? baidu.com. (27)
23:21:31.354783 IP 192.168.59.193.35047 > 114.114.114.114.domain: 9720+ AAAA? baidu.com. (27)
抓包地点2: coredns 容器所在宿主机的外部网络网卡
[root@master02 ~]# tcpdump -i ens33 udp dst port 53 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens33, link-type EN10MB (Ethernet), capture size 262144 bytes
23:21:31.351244 IP 172.16.1.32.52454 > 8.8.8.8.domain: 64169+ A? baidu.com. (27)
23:21:31.354810 IP 172.16.1.32.35543 > 114.114.114.114.domain: 9720+ AAAA? baidu.com. (27)
不知道你有没有注意,无论是内部域名解析,还是外部域名解析,均存在请求的域名点数小于5,所以也进行了 search 域的域名补全,额外产生了几次无效的 DNS 解析流程
那我们可能就在想了,有没有什么办法避免此种情况呢?
在被解析域名的最后加上点,即可跳过 search domain 的补全,直接对目标域名发起解析流程。按照如上的方式自行抓包验证下
nginx-test-7c676c8687-n87dr:~# nslookup baidu.com. 192.168.59.193
Server: 192.168.59.193
Address: 192.168.59.193#53
Name: baidu.com
Address: 198.18.0.10
Pod.yaml 通过 dnsConfig 自定义 ndots 配置
spec:
containers:
...
dnsConfig:
options:
- name: ndots
value: "1"
通过这样的配置后,创建出的 Pod ndots 就不再是默认值 5 了
如果 dnsPolicy 为 ClusterFirst 模式下,域名点数小于5均会进行 search domain 补全。可根据实际的情况进行解析优化