包阅导读总结
1. 关键词:去哪儿、Kube DNS、架构优化、测试记录、上线方案
2. 总结:本文介绍了去哪儿公司的 Kube DNS 架构优化方案,包括 q-dnsmasq 的配置及优势、测试记录、上线步骤,还提及了对公有云环境的后续规划。
3. 主要内容:
– 去哪儿 Kube DNS 架构优化
– 公司服务器节点装机时安装 q-dnsmasq 用于缓解 Localdns 压力
– dnsmasq 支持将 DNS 查询发送给所有配置的服务器,提高性能和可靠性
– 符合业务需求,确保响应快速可靠
– 测试记录
– 配置展示示例信息
– Pod 使用测试
– Dnsmasq 缓存有效性
– q-dnsmasq/coredns pod 故障测试
– 上线方案
– 配置 q-dnsmasq
– 配置 Kubelet
– 配置 kube-dns
– 准备 Coredns Daemonset
– 测试加入 Coredns Daemonset 实例后的 kube-dns svc 是否正常
– 将 Coredns Daemonset 投入使用
– 调整 Coredns 配置
– 总结与后续规划
– 介绍方案优势及不足,提供可实践方案和上线方式
– 对公有云已有解决思路,Q3 逐步验证和实施
思维导图:
文章地址:https://mp.weixin.qq.com/s/HW68y_K7VR6Rb_3bAftcDw
文章来源:mp.weixin.qq.com
作者:王坤
发布时间:2024/6/21 8:23
语言:中文
总字数:6204字
预计阅读时间:25分钟
评分:88分
标签:Kubernetes,DNS,架构,优化
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
1. 公司服务器节点(物理机或KVM等),在装机时均有安装q-dnsmasq,是在容器化之前就存在、用于缓解Localdns压力。
2. dnsmasq支持将所有 DNS 查询发送给所有配置的DNS服务器(–all-servers),可以很大提高 DNS 查询的性能以及可靠性。
3. 相比较更符合业务需求,能够确保快速且可靠地得到响应。
三、测试记录
配置展示
示例信息注明,如下信息均为虚拟
Cluster : abc
Cluster Domain:abc.k8s.xxx.qunar.com
1. q-dnsmasq
[user@node1 ~]$ cat /usr/lib/systemd/system/q-dnsmasq .service
...
ExecStart= /usr/local/sbin/dnsmasq -k -h -C /etc/q-dnsmasq .conf --dns-forward-max=3000 # dnsmasq默认值较小,这里做了调整
...
|
[user@node1 ~]$ cat /etc/q-dnsmasq .conf
...
all-servers
resolv- file = /etc/dnsmasq .d /q-ns .conf
servers- file = /etc/q-kubedns .servers
...
|
[user@node1 ~]$ cat /etc/q-kubedns .servers
# servers for abc
# 1. node coredns pod
server= /abc .k8s.xxx/${local_Node_IP} #53
server= /abc .k8s.xxx.qunar.com/${local_Node_IP} #53
# 2. kube-dns svc
server= /abc .k8s.xxx/${kube-dns_IP} #53
server= /abc .k8s.xxx.qunar.com/${kube-dns_IP} #53
# 3. svc 反解析配置
server= /xx .xx.10. in -addr.arpa/$( hostname -I | sed 's/ //g' ) #xx53
server= /xx .xx.10. in -addr.arpa/${kube-dns_IP} #53
server= /xx .xx.10. in -addr.arpa/$( hostname -I | sed 's/ //g' ) #xx53
server= /xx .xx.10. in -addr.arpa/${kube-dns_IP} #53
...... # 按实际环境配置全部添加
|
[user@node1 ~]$ cat /etc/dnsmasq .d /q-ns .conf
nameserver ${localdns-1_IP} # xxx localdns-1
nameserver ${localdns-2_IP} # xxx localdns-2
|
2.Node resolv.conf
[user@node1 ~]$ cat /etc/resolv .conf
search qunar.com
nameserver ${local_Node_IP} # node ip
nameserver ${localdns-1_IP} # xxx localdns-1
nameserver ${localdns-2_IP} # xxx localdns-2
|
3.Kubelet config
[user@node1 ~]$ cat /var/lib/kubelet/config .yaml
...
clusterDNS:
- ${local_Node_IP} # node ip
- ${kube-dns_IP} # kube-dns (coredns svc)
clusterDomain: abc.k8s.xxx.qunar.com
...
|
Pod 使用测试
测试场景
1. 将测试用pod调度至调整后的节点,并确认Dns policy: ClusterFirst。
2. 进入pod内,查看其/etc/resolv.conf是否符合预期(kubelet clusterDNS指定的2个dns地址)。
3. pod内部,使用dig工具进行测试,并在宿主节点查看q-dnsmasq解析日志,同时开始抓包查看走向,确保解析链路符合预期。
4. 宿主节点,使用dig工具进行测试。
测试过程
因信息敏感性与篇幅限制,实测记录相关信息不再贴出,简述整体过程;测试场景要覆盖如下:
-
Pod – 集群外部域名
-
Pod – 集群内部域名
-
Pod – 内外域名+search
-
Dnsmasq 缓存有效性
1. 配置确认
检查改造节点的如下配置文件是否修改符合预期。
-
/etc/q-dnsmasq.conf
-
/etc/dnsmasq.d/q-ns.conf
-
/etc/q-kubedns.server
2. Pod调度
确认测试的Pod通过nodeName或affinity等方式定向调度至了”改造后的目标节点”。
3. Pod内环境确认
确认/etc/resolv.conf配置文件是否符合预期。
4. 集群外部域名测试
4.1 域名解析
Pod内dig www.qunar.com确认是否可正常解析。
4.2 抓包记录
在”改造后的目标节点”通过抓包观察,确认链路为如下走向:
4.3 解析日志
如果开启了dnsmasq的log-queries,也可以通过其日志,确认链路为如下走向:
5. 集群内部域名测试
参照[ 4. 集群外部域名测试 ]过程,正常解析链路表现应当如下:
6. 缓存测试
30s内连续dig两次,关注第二次是否直接由q-dnsmasq返回结果即可。
7. 宿主节点测试
K8S内部域名
K8S外部域名
8. q-dnsmasq/coredns pod 故障测试
在这里我们环境有些特殊,之前为了方便可直接使用svc(Qunar的容器网络是打通的,pod ip/svc均可直接通信)访问相关应用,我们在公司localdns服务器上做了forward,它会将*.abc.k8s.xxx.qunar.com全部转发至对应集群的kube-dns。
也就是说,在node上执行dig时,哪怕q-dnsmasq挂掉了直接请求到了localdns上,也是可以正常提供解析的;这个场景应对多数公司都用不到,可以忽略。
# pod resolv.conf
[root@testpod ~] # cat /etc/resolv.conf
search ops- test .svc.abc.k8s.xxx.qunar.com svc.abc.k8s.xxx.qunar.com abc.k8s.xxx.qunar.com qunar.com
nameserver ${local_Node_IP} # node ip
nameserver ${kube-dns_IP} # kube-dns (coredns svc)
options ndots:2 (可选优化,按实际场景需要调整)
# node resolv.conf
[root@l-k8snode ~] # cat /etc/resolv.conf
search qunar.com
nameserver ${local_Node_IP} # node ip
nameserver ${localdns-1_IP} # xxx localdns-1
nameserver ${localdns-2_IP} # xxx localdns-2
|
8.1 停止q-dnsmasq
8.2 pod内分别测试内、外部域名
四、上线方案
配置q-dnsmasq
# 删除原配置文件
sudo mv /etc/q-dnsmasq .conf /etc/q-kubedns .servers /tmp/
# 修改q-dnsmasq配置文件
sudo cat >> /etc/q-dnsmasq .conf << EOF
...
all-servers
resolv- file = /etc/dnsmasq .d /q-ns .conf
servers- file = /etc/q-kubedns .servers
...
EOF
# 修改q-dnsmasq server-file文件
sudo cat >> /etc/q-kubedns .servers << EOF
# servers for abc
# 1. coredns pod on node
server= /abc .k8s.xxx/$( hostname -I | sed 's/ //g' ) #xx53
server= /abc .k8s.xxx.qunar.com/$( hostname -I | sed 's/ //g' ) #xx53
# 2. kube-dns svc
server= /abc .k8s.xxx/${kube-dns_IP} #53
server= /abc .k8s.xxx.qunar.com/${kube-dns_IP} #53
# 3. svc 反解析配置
server= /xx .xx.10. in -addr.arpa/$( hostname -I | sed 's/ //g' ) #xx53
server= /xx .xx.10. in -addr.arpa/${kube-dns_IP} #53
server= /xx .xx.10. in -addr.arpa/$( hostname -I | sed 's/ //g' ) #xx53
server= /xx .xx.10. in -addr.arpa/${kube-dns_IP} #53
...... # 按实际环境配置全部添加
EOF
# 修改resolv.conf
sudo sed -i '/search .*/a\nameserver ' "$(hostname -I | sed 's/ //g')" '' /etc/resolv .conf
# 重启q-dnsmasq
sudo systemctl restart q-dnsmasq
|
配置Kubelet
Kubelet clusterdns Setting Scripts
# 驱逐节点
sudo kubectl drain ${node} --ignore-daemonsets
# 修改kubelet config
sudo sed -i 's/- ${kube-dns_IP}/- ' "$(hostname -I | sed 's/ //g')" '\n- ${kube-dns_IP}/' /var/lib/kubelet/config .yaml
# 重启kubelet服务
sudo systemctl restart kubelet
# 放开调度
sudo kubectl uncordon ${node}
|
截止此处,Pod的首选DNS已经指向为q-dnsmasq,调度到该节点上的Pod不会再去访问kube-svc进行解析。
配置kube-dns
1. 准备Coredns Daemonset
1.1 创建新的Coredns ConfigMap – coredns-2,端口配置为xx53
apiVersion: v1
data:
Corefile: |
.:xx 53 {
errors
health {
lameduck 15s
}
ready
kubernetes abc.k8s.xxx.qunar.com 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
metadata:
name: coredns-2
namespace: kube-system
|
1.2 创建Coredns DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: kube-dns
name: coredns
namespace: kube-system
spec:
...
hostNetwork: true
...
volumes:
- configMap :
defaultMode: 420
items:
- key : Corefile
path: Corefile
name: coredns-2
name: config-volume
...
|
2. 测试加入Coredns Daemonset实例后的kube-dns svc是否正常
# 确保coredns daemonset加进来后不会影响当前解析
1. 循环、持续探测关注解析结果
# 测试首选q-dnsmasq的新架构使用是否正常
1. 调度Pod至存在coredns daemonset的节点
2. 进入pod内进行 dig 、curl等测试K8S内SVC是否可正常解析(pod → q-dnsmasq → coredns daemonset pod / kube-dns svc)
|
2.1 小结-观察确认
变更过程中,中间态的必要理解:
1. kube-dns svc下的endpoints列表,会新增coredns daemonset的实例(为hostip)。
2. kube-dns svc的port为53,转发endpoints的目标端口也为53(这里理解下,新增进去的coredns daemonset端口为xx53,理论上来讲其实转发到coredns daemosnet 53端口时,因coredns daemonset pod未监听53端口,应当是要出问题的;但是并不会。因coredns daemonset为hostip,虽然coredns daemonset pod未监听53端口,但所在节点上的q-dnsmasq是监听着53端口的)。
所以,这里的新增coredns daemonset pod加入kube-dns svc的endpoints列表后不受影响的详细,如下图所示:
kube-dns svc: ${kube-dns-svc_IP]
kube-dns endpoints: pod-1_ip:53,pod-2_ip:53,…,host-1_ip:53,host-2_ip:53,…
3. 将Coredns Daemonset投入使用
缩容cordons deployment
$ sudo kubectl scale --replicas=0 deployment -n kube-system coredns
|
修改kube-svc service
-
kube-dns svc tcp port存在不可修改情况,需要recreate才能成功修改生效。
-
在kube-dns svc修改完成后,此时,直接访问kube-dns svc的链路,将会由变更时中间态(pod → kube-dns svc:53 → q-dnsmasq:53)修正为 pod → kube-dns svc:53 → coredns daemonset pod:xx53(不再是q-dnsmasq)。
-
至此,coredns deployment将彻底完成下线,整个架构转换彻底完成。
$ sudo kubectl edit svc -n kube-system kube-dns
# 修改service的tartPort端口为xx53
ports:
- name: dns
port: 53
protocol: UDP
targetPort: xx53
- name: dns-tcp
port: 53
protocol: TCP
targetPort: xx53
- name: metrics
port: 9153
protocol: TCP
targetPort: 9153
|
4. 调整Coredns配置
在如上已经完成了变更。该步骤可忽略,此处为为了方便统一进行的额外调整。
#修改configmap coredns,将其端口配置由53更改为xx53
$ kubectl edit configmap coredns -n kube-system
apiVersion: v1
data:
Corefile: |
.:xx53 {
...
#修改daemosnet coredns,将其引用的configmap由coredns-2更改为coredns
$ kubectl edit ds -n kube-system coredns
...
volumes:
- configMap:
defaultMode: 420
items:
- key: Corefile
path: Corefile
name: coredns
name: config-volume
...
#逐个delete daemonset coredns pod完成手动滚动更新
$ kubectl delete pod -n kube-system ${coredns_pod}
#全部完成更新后,删除configmap coredns-2
$ kubectl delete configmap -n kube-system coredns-2
|
五、总结与后续规划
文章介绍了在Qunar的业务需求场景下,kube-dns调整方案的优势以及原生k8s dns方案的
不足,并提供可实践、可复刻的方案,以及测试验收、无损上线方式。
希望对在大规模场景下kube-dns,对解析有较大依赖性的团队能够提供一种优化思路或优化方案候选项。
另外,Qunar是有使用到公有云作为弹性资源的,DNS解析相关问题在云上也会存在,因公有云virtual-kubelet并不允许Daemonset调度,所以文中方案对公有云并不适用,但我们对云上环境也已有相关解决思路,在Q3会逐步验证和实施: