域名系统(英语:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用TCP和UDP端口53。
DNS 不仅方便了人们访问不同的互联网服务,更为很多应用提供了,动态服务发现和全局负载均衡(Global Server Load Balance,GSLB)的机制。这样,DNS 就可以选择离用户最近的 IP 来提供服务。即使后端服务的 IP 地址发生变化,用户依然可以用相同域名来访问。
DNS 协议在 TCP/IP 栈中属于应用层,是一个典型的 客户端 - 服务器应用,客户端发起域名查询请求,服务端对请求进行应答。
CoreDNS是Kubernetes集群中负责DNS解析的组件,能够支持解析集群内部自定义服务域名和集群外部域名。CoreDNS具备丰富的插件集,在集群层面支持自建DNS、自定义hosts、CNAME、rewrite等需求。与Kubernetes一样,CoreDNS项目由CNCF托管。
DNS 服务器支持正向查找(A 和 AAAA 记录)、端口发现(SRV 记录)、反向 IP 地址发现(PTR 记录)等。
如果 Pod 的 dnsPolicy
设置为 default
,则它将从 Pod 运行所在节点继承名称解析配置。Pod 的 DNS 解析行为应该与节点相同。
如果你不想这样做,或者想要为 Pod 使用其他 DNS 配置,则可以使用 kubelet 的 --resolv-conf
标志。
1)业务Pod(Pod Client)试图访问Nginx服务(Service Nginx)时,先会请求本地DNS配置文件(/etc/resolv.conf)中指向的DNS服务器(nameserver 172.21.0.10,即Service kube-dns)获取服务IP地址,得到解析结果为172.21.0.30的IP地址。
2)业务Pod(Pod Client)再直接发起往该IP地址的请求,请求最终经过Nginx服务(Service Nginx)转发到达后端的Nginx容器(Pod Nginx-1和Pod Nginx-2)上。
CoreDNS 是模块化且可插拔的 DNS 服务器,每个插件都为 CoreDNS 添加了新功能。可以通过维护 Corefile,即 CoreDNS 配置文件, 来配置 CoreDNS 服务器。作为一个集群管理员,你可以修改 CoreDNS Corefile 的 ConfigMap, 以更改 DNS 服务发现针对该集群的工作方式。
在 Kubernetes 中,CoreDNS 安装时使用如下默认 Corefile 配置:
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
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
cache 30
loop
reload
loadbalance
}
Corefile 配置包括以下 CoreDNS 插件:
http://localhost:8080/health
处提供 CoreDNS 的健康报告。在这个扩展语法中,lameduck
会使此进程不健康,等待 5 秒后进程被关闭。ttl
来定制响应的 TTL。默认值是 5 秒钟。TTL 的最小值可以是 0 秒钟, 最大值为 3600 秒。将 TTL 设置为 0 可以禁止对 DNS 记录进行缓存。pods insecure
选项是为了与 kube-dns 向后兼容。pods verified
选项,该选项使得仅在相同名字空间中存在具有匹配 IP 的 Pod 时才返回 A 记录。pods disabled
选项。http://localhost:9153/metrics
上提供。你可以通过修改 ConfigMap 来更改默认的 CoreDNS 行为。
可选插件: log:记录解析日志
配置 Pod 打散
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: k8s-app
operator: In
values:
- kube-dns
topologyKey: kubernetes.io/hostname
合理设置副本数
1)80节点以下
副本数 = min ( max ( ceil (QPS/10000), ceil (集群节点数/8) ), 10 )
# 手动调整 CoreDNS 副本数
kubectl scale --replicas={target} deployment/coredns -n kube-system #{target} 目标副本数量
示例: 集群节点数为10,DNS 服务请求 QPS 为22000,则副本数为3。 集群节点数为30,DNS 服务请求 QPS 为15000,则副本数为4。
2)80节点以上,安装 NodeLocal DNSCache
# 下载 YAML 文件
wget https://raw.githubusercontent.com/kubernetes/kubernetes/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml
# 修改变量
kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}`
domain=`grep clusterDomain '/var/lib/kubelet/config.yaml' | awk '{print $2}'`
localdns="169.254.20.10"
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/,__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml
sed -i 's#registry.k8s.io/dns/k8s-dns-node-cache:1.22.28#registry.cn-hangzhou.aliyuncs.com/clay-wangzhi/registry.k8s.io.dns.k8s-dns-node-cache:1.22.28#g' nodelocaldns.yaml
# 安装
kubectl create -f nodelocaldns.yaml
# 修改 kubelet 重启
echo "sed -i "s/$kubedns/$localdns/g" /var/lib/kubelet/config.yaml"
# 在每台 Node 节点,使用上面命令的输出结果替换 dns ip , 然后重启
systemctl restart kubelet.service
在客户端,也可以做适当的优化配置,来提升 DNS 的使用体验。
/etc/resolv.conf
可以知道 ndots
选项默认为 5。例如,在 debug 命名空间查询 kubernetes.default.svc.cluster.local
这个 service:
域名中有 4 个 .
,小于 5,尝试拼接上第一个 search 进行查询,即kubernetes.default.svc.cluster.local.debug.svc.cluster.local
,查不到该域名。
继续尝试 kubernetes.default.svc.cluster.local.svc.cluster.local
,查不到该域名。
继续尝试 kubernetes.default.svc.cluster.local.cluster.local
,仍然查不到该域名。
尝试不加后缀,即 kubernetes.default.svc.cluster.local
,查询成功,返回响应的 ClusterIP。
上面一个简单的 service 域名解析需要经过 4 轮解析才能成功,集群中充斥着大量无用的 DNS 请求。因此需要根据业务配置的访问方式来为其设置合理的 ndots 来降低查询次数:spec:
dnsConfig:
options:
- name: ndots
value: "2"
<service-name>
访问。
Pod 访问其它命名空间的 Service,使用 <service-name>.<namespace-name>
访问。
Pod 访问外部域名,使用 FQDN 类型域名访问,在域名最后添加 .
以减少无效搜索。spec:
dnsConfig:
options:
- name: timeout
value: "1"
- name: attempts
value: "2"
用自带的监控大盘即可,重点关注 Requests (total)、Responses (by rcode)、Responses (duration) 这几个指标即可,进行容量扩容,或结合日志进一步问题定位。
参考链接:
维基百科:https://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E7%B3%BB%E7%BB%9F
自定义 DNS 服务:https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/dns-custom-nameservers/
DNS概述:https://help.aliyun.com/zh/ack/ack-managed-and-ack-dedicated/user-guide/dns-overview
TKE DNS 最佳实践:https://cloud.tencent.com/document/product/457/78005
在 Kubernetes 集群中使用 NodeLocal DNSCache:https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/nodelocaldns/
我是 Clay,下期见 👋