文章 91
评论 1
浏览 166369
Coredns

Coredns

一、Coredns简介

官方文档:https://coredns.io/plugins/

CoreDNS是一个DNS服务器,它是用Go编写的。CoreDNS与其他DNS服务器不同,因为它非常灵活几乎所有功能都包含到插件中。

kubernetes中使用coredns提供service资源名称的域名解析,使用kubernetes插件。

当然coredns还有许多的实用插件,官方网站:https://coredns.io/plugins/

二、Coredns使用

2.1 Coredns配置文件

.:53 {    
    hosts {
      10.0.0.1 example.org
      fallthrough
    }
    forward . 114.114.114.114:53  #上面无法处理的请求会传到这里
    prometheus   
    loadbalance
    log 
}

2.2 插件

1.errors

在查询处理过程中遇到的任何错误都将打印到标准输出。特定类型的错误可以在一段时间内合并和打印一次。

基本语法:

errors

2.health

启用进程范围的健康探测接口。当CoreDNS启动并运行时,它会返回200 OK HTTP状态代码。默认情况下,健康状况在端口8080/health上导出。

基本语法:

health 127.0.0.1:8080 
#注意如果绑定所有地址可写:8080

3.ready

启用就绪探测接口,默认为:8181固定路径为/ready,当该服务器准备就绪时,就绪端点返回 200 响应代码和“OK”字样。否则返回 503和未准备好的插件列表。

基本语法:

ready 127.0.0.1:8181
#注意如果绑定所有地址可写:8181

4.hosts

hosts插件可以用来直接定义自己所需的dns解析让coredns进行解析返回。

基本语法:

hosts . {
  10.0.0.1 example.org  #自己填写dns解析,可以写多条
  fallthrough    #表示处理完这个插件内容继续处理其余插件内容
}

5.kubernetes

运行 kubernetes 插件的 CoreDNS 可用作 kubernetes 集群中 kube-dns 的替代品。

基本语法:

kubernetes cluster.local {
    endpoint https://192.168.10.71:6443  #访问k8s的apiserver的url     
    kubeconfig /kube/config              #访问集群的kubeconfig认证文件
    namespaces default                   #进行解析资源的命名空间,不写表示所有
    labels application=nginx             #匹配解析资源标签,不写所有
    ttl 5                                #默认值5秒,允许的最小TTL为0秒,最大值为3600秒。将TTL设置为0将防止记录被缓存。
    fallthrough                          #表示处理完这个插件内容继续处理其余插件内容
}

6.prometheus

使用prometheus,您可以从 CoreDNS 和任何拥有它们的插件中导出指标。指标的默认位置是localhost:9153。指标路径固定为/metrics

基本语法:

prometheus localhost:9253
#注意如果绑定所有地址可写:9253

7.cache

启用缓存,除区域传输和元数据记录外的所有记录都将被缓存长达 3600 秒。当从后端(上游、数据库等)获取数据成本高昂时缓存最有用。

基本语法:

cache 30  #缓存多少秒

8.loop

循环插件负责防止coredns进入到死循环,自动中断循环。

loop

9.reload

自动重载配置,在修改配置文件后coredns会自动检测配置文件修改并且重新加载配置。

reload

10.loadbalance

自动实现DNS负载均衡。

loadbalance

11.forward

forward插件将DNS请求转发到上游。它支持UDP、TCP 和 DNS-over-TLS 并可以实现监控检测。这个插件每个服务器只能使用一个。

可以配置外部dns服务IP也可以使用主机的/etc/resolv.conf配置。

配置示例:

forward  . /etc/resolv.conf {
    except www.zhangzhuo.org  #排除的域名
    expire 10s  #缓存时间10秒默认
}

12.log

日志插件只会影响查询日志记录,CoreDNS 的任何其他日志记录都会显示出来。请注意对于繁忙的服务器,日志记录会导致性能下降。

配置示例:

log

2.3 启动coredns

1.命令直接启动

/usr/bin/coredns -conf /root/corefile

2.以systemd守护进程运行

[10:57:22 root@centos7 ~]#cat /etc/systemd/system/coredns.service 
[Unit]                                                                                                                                                                                                            
Description=coredns
Documentation=https://coredns.io
Wants=network-noline.target
After=network-noline.target

[Service]
WorkingDirectory=/usr/local/coredns
User=root
Group=root
ExecStart=/usr/bin/coredns -conf /etc/coredns/Corefile
Restart=always

[Install]
WantedBy=multi-user.target

三、kubernetes部署coredns

3.1 部署coredns

caredns主要用来解决k8s内部service名称的域名解析

下载地址:https://github.com/coredns/deployment/blob/master/kubernetes/coredns.yaml.sed

#需要修改的位置
kubernetes cluster.local in-addr.arpa ip6.arpa {    #集群内部dns                        
  fallthrough in-addr.arpa ip6.arpa
}
forward . 114.114.114.114 {   #代理外部dns服务器
  max_concurrent 1000
}
clusterIP: 10.200.0.2 #service地址池的第二个地址

执行创建

[19:50:00 root@k8s-master dns]#kubectl apply -f coredns.yaml

[19:50:26 root@k8s-master dn[root@net-test1 /]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=127 time=37.9 ms
^C
--- baidu.com ping statistics ---
2 packets transmitted, 1 received, 50% packet loss, time 3ms
rtt min/avg/max/mdev = 37.894/37.894/37.894/0.000 ms
[root@net-test1 /]# ping kubernetes
PING kubernetes.default.svc.cluster.local (10.200.0.1) 56(84) bytes of data.
64 bytes from kubernetes.default.svc.cluster.local (10.200.0.1): icmp_seq=1 ttl=64 time=0.031 mss]#kubectl get pod -A
NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE
default       net-test1                  1/1     Running   0          14m
kube-system   coredns-6d99d5879f-hvpgl   1/1     Running   0          18s
kube-system   kube-flannel-ds-bvfls      1/1     Running   0          28m
kube-system   kube-flannel-ds-l2gtz      1/1     Running   0          28m
kube-system   kube-flannel-ds-sss77      1/1     Running   0          28m
[19:50:57 root@k8s-master dns]#kubectl get svc -A
NAMESPACE     NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
default       kubernetes   ClusterIP   10.200.0.1   <none>        443/TCP                  4h39m
kube-system   kube-dns     ClusterIP   10.200.0.2   <none>        53/UDP,53/TCP,9153/TCP   39s
#测试
[root@net-test1 /]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=127 time=37.9 ms
[root@net-test1 /]# ping kubernetes
PING kubernetes.default.svc.cluster.local (10.200.0.1) 56(84) bytes of data.
64 bytes from kubernetes.default.svc.cluster.local (10.200.0.1): icmp_seq=1 ttl=64 time=0.031 ms

3.2 部署本地DNS缓存

kubernetes官方介绍:https://kubernetes.io/zh/docs/tasks/administer-cluster/nodelocaldns/

官方github:https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/dns/nodelocaldns

1.为什么需要本地DNS缓存

  • 减轻集群DNS解析压力,提高DNS性能
  • 避免netfilter做DNAT导致conntrack冲突引发DNS 5秒延时
镜像底层库 DNS 解析行为默认使用 UDP 在同一个 socket 并发 A 和 AAAA 记录请求,由于 UDP 无状态,两个请求可能会并发创建 conntrack 表项,如果最终 DNAT 成同一个集群 DNS 的 Pod IP 就会导致 conntrack 冲突,由于 conntrack 的创建和插入是不加锁的,最终后面插入的 conntrack 表项就会被丢弃,从而请求超时,默认 5s 后重试,造成现象就是 DNS 5 秒延时; 底层库是 glibc 的容器镜像可以通过配 resolv.conf 参数来控制 DNS 解析行为,不用 TCP 或者避免相同五元组并发(使用串行解析 A 和 AAAA 避免并发或者使用不同 socket 发请求避免相同源端口),但像基于 alpine 镜像的容器由于底层库是 musl libc,不支持这些 resolv.conf 参数,也就无法规避,所以最佳方案还是使用本地 DNS 缓存。

2.原理

本地 DNS 缓存以 DaemonSet 方式在每个节点部署一个使用 hostNetwork 的 Pod,创建一个网卡绑上本地 DNS 的 IP,本机的 Pod 的 DNS 请求路由到本地 DNS,然后取缓存或者继续使用 TCP 请求上游集群 DNS 解析 (由于使用 TCP,同一个 socket 只会做一遍三次握手,不存在并发创建 conntrack 表项,也就不会有 conntrack 冲突)

访问流程结构图对比

image-20210831200305289

不使用dns缓存时,所有的k8s的node节点的pod如果需要dns解析,所有的请求都通过pod自己跟k8s中的dns组件的service进行请求,如果集群规模较大dns组件的负载会比较高,也会导致dns延时5秒的问题

image-20210831195940589

使用dns缓存时,每个节点都会运行一个dns缓存pod,并且在宿主机创建一个虚拟网卡并检查dns解析端口(53),本机的pod如果需要dns解析,先请求本地的dns缓存pod,如果dns缓存pod有请求的数据,由dns缓存pod直接进行回复报文,如果没有dns缓存pod会通过k8s的dns组件获取dns解析,之后返回报文给对应的pod。这样可以极大的减少dns组件的负载,也可以解决dns延迟5秒的问题

3.部署过程

yaml文件下载地址:https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/dns/nodelocaldns/nodelocaldns.yaml

下在后需要修改的配置,我这里kube-proxy模式为IPVS,如果你的kube-proxy模式为IPTABLES以下配置并不适应

#需要三个参数
kubedns=`kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}`
damain=cluster.loacl
localdns=169.254.1.1
#kubedns就是集群中kube-dns的svc的IP
#damain集群的damain
#localdns每台node节点监听的地址,不要跟集群中任何IP地址段冲突即可


#文件中所有的__PILLAR__LOCAL__DNS__修改为localdns变量内容
#文件中所有的__PILLAR__DNS__DOMAIN__修改为damain变量内容
#文件中所有的__PILLAR__DNS__SERVER__修改为空
#文件中所有的__PILLAR__CLUSTER__DNS__修改为kubedns变量的值
#文件中所有的__PILLAR__UPSTREAM__SERVERS__修改为集群外部的dns服务器地址,如果没有也可以设置为kubedns
#修改命令
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


#之后使用yaml启动pod,如果pod启动正常执行以下步骤
如果 kube-proxy 运行在 IPVS 模式,需要修改 kubelet 的 --cluster-dns 参数为 NodeLocal DNSCache 正在侦听的 <node-local-address> 地址。 

vim /etc/kubernetes/conf/kubelet-conf.yml
clusterDNS:
  - "169.254.1.1"  #修改这个

#之后重启kubelet服务,验证测试,创建一个新的测试pod
kubectl run test1 --image=centos:latest sleep 36000

#进入容器验证dns解析服务器地址是不是169.254.1.1
kubectl exec -it test1
cat /etc/resolv.conf
nameserver 169.254.1.1  #主要看这里

#ping一个k8s中的svc监测是否正常可用,如果可以正常解析表示正常
ping kubernetes

标题:Coredns
作者:Carey
地址:HTTPS://zhangzhuo.ltd/articles/2022/08/25/1661391743787.html

生而为人

取消