文章 90
评论 1
浏览 765444
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

生而为人

你是夜猫子呀?这么晚还不睡觉,明天起的来嘛
取消