Menu

  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay
  • Home
  • Work
    • Cloud
      • Virtualization
      • IaaS
      • PaaS
    • Java
    • Go
    • C
    • C++
    • JavaScript
    • PHP
    • Python
    • Architecture
    • Others
      • Assembly
      • Ruby
      • Perl
      • Lua
      • Rust
      • XML
      • Network
      • IoT
      • GIS
      • Algorithm
      • AI
      • Math
      • RE
      • Graphic
    • OS
      • Linux
      • Windows
      • Mac OS X
    • BigData
    • Database
      • MySQL
      • Oracle
    • Mobile
      • Android
      • IOS
    • Web
      • HTML
      • CSS
  • Life
    • Cooking
    • Travel
    • Gardening
  • Gallery
  • Video
  • Music
  • Essay

CoreDNS学习笔记

22
May
2019

CoreDNS学习笔记

By Alex
/ in PaaS
0 Comments
简介

CoreDNS是一个基于Go的DNS服务器,非常灵活,支持插件链。CoreDNS内置了30+的插件,你还可以将一些外部插件也编译到CoreDNS的二进制文件中。

安装
编译
Shell
1
2
3
4
5
6
7
8
export GOPATH=${GOPATH-~/go}
mkdir -p $GOPATH/src/github.com/coredns
cd $GOPATH/src/github.com/coredns/
wget https://github.com/coredns/coredns/archive/v1.0.5.tar.gz
tar xvf v1.0.5.tar.gz
mv coredns-1.0.5 coredns
cd coredns
make CHECKS= godeps all 
Docker

CoreDNS的每个版本都发布了Docker镜像,在容器中启动CoreDNS的示例:

Shell
1
2
3
docker run --name coredns -h coredns --network local --ip 172.21.0.12 -p 127.0.0.1:53:53 -p 127.0.0.1:53:53/udp \
           --volume /media/alex/Repository/Linkage/Docker/coredns/:/root/ \
           --restart=always  -d docker.gmem.cc/coredns/coredns:1.5.0 -conf /root/Corefile
插件机制

在加载了配置文件(默认为当前工作目录下的Corefile)后,CoreDNS就会运行一系列的DNS服务器。每个服务器由两个属性来识别:

  1. 其服务的区域(Zone),也就是DNS后缀
  2. 其监听的端口

当CoreDNS接收到一个DNS请求时,处理的步骤如下:

  1. 找到匹配端口的服务器
  2. 如果有多个服务器监听目标端口,则将请求转发给具有最匹配Zone(最长DNS后缀)的服务器
  3. 遍历匹配服务器的插件链,遍历的顺序就是配置文件中插件声明的顺序
  4. 每个插件都会检查DNS查询请求,判断自己是否应当处理它。某些插件支持基于查询的名称或者其它属性进行过滤匹配。插件会执行以下操作之一
    1. 处理请求 —— 为客户端提供响应
    2. 不处理请求
    3. 不处理请求,但是将请求传递给下一个插件(fallthrough)
    4. 处理请求,并为请求添加一个hint,后续插件会继续处理请求,但是当前插件有机会对最终的响应进行后续的操作
Unregistered插件

有一类特殊的插件,它们不去处理DNS请求,但是会影响CoreDNS的行为。例如bind插件决定CoreDNS绑定哪些网络接口。

插件架构

每个插件由三个部分组成:

  1. Setup:解析配置文件,以及插件指令(Directives)
  2. Registration:在编译期间,注册到CoreDNS中
  3. Handler:处理查询的逻辑所在
命令行
选项
选项 说明
-conf 指定配置文件,如果不指定使用当前目录的Corefile
-cpu CPU用量限制,默认100%
-pidfile PID文件路径
-plugins 列出可用的插件
-quiet 安静模式
-version 显示版本
-dns.port 指定默认端口
配置
格式
注释

以 #开头的行为注释。

环境变量

你可以在Corefile的任何地方使用环境变量,格式 {$ENV_VAR}或者 {%ENV_VAR%}。在解析Corefile时,环境变量被自动替换为实际的值。

可重用片段

利用import插件,可以定义复用的配置片段:

1
2
3
4
5
6
7
8
9
10
11
12
# 定义一个片段
(snip) {
    prometheus
    log
    errors
}
 
. {
    whoami
    # 导入片段
    import snip
}
服务器配置块

Corefile中可以定义多个服务器,每个服务器的配置格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 每个服务器以它权威负责(Authoritative)的Zone开头
# 多个Zone以空格分隔
#
# 可以为每个Zone指定它支持的协议:
# dns:// 原始DNS协议,默认值
# tls://  DNS over TLS
# grpc:// DNS over gRPC
#
# 可以为Zone指定端口,默认53
[PROTOCOL]ZONE[:PORT] [ZONE1 ZONE2] {
 
}
 
# 示例,点号表示此服务器处理任何请求
. {
}
插件链

在每个服务器内部,可以定义0-N个插件组成的插件链:

1
2
3
4
5
6
7
8
9
10
ZONE {
  
  # 简单的插件,配置一些指令
  PLUGIN [DIRECTIVE1] [DIRECTIVE2]
 
  # 复杂插件,具有更多的配置项,定义为插件块
  PLUGIN {
  
  }  
}
常用插件
bind

指定服务器监听的网络接口(IP地址): bind ADDRESS ...

示例:

1
2
3
4
5
6
7
8
. {
    bind 127.0.0.1 ::1
}
 
. {
    bind 127.0.0.1
    bind ::1
}
autopath

允许服务器端进行的搜索后缀(search domain)补全。如果插件发现客户端查询的名称,匹配search path的第一个元素,则自动遍历search path中的domain链,并返回第一个非NXDOMAIN结果。如果出现失败,则返回原始查询的应答。

由于autopath的应答中的名称,和原始问题不匹配,因此他会在CoreDNS中添加一个CNAME,从原始名称指向应答中的名称。

格式:

1
2
3
4
# ZONE autopath权威负责的Zone
# RESOLV-CONF 包含search domain的配置文件。或者指向其它插件,例如@kubernetes,这时从其它插件读取search domain
# 配置文件中必须有 search domain1 domain2 ... 这样的行
autopath [ZONE...] RESOLV-CONF
cache

实现前端缓存,用于查询后端(Upstream、Database...)成本较高的场景。启用此插件后,除了Zone transfers / Metadata以外的记录会被缓存默认3600s。 

格式:

1
2
3
4
5
6
7
8
9
# TTL 缓存有效期,单位秒,默认3600
# ZONES 哪些Zone支持缓存
cache [TTL] [ZONES...] {
    # 成功的DNS应答的缓存配置
    success CAPACITY [TTL] [MINTTL]
    # Denial of existence应答的缓存配置
    denial CAPACITY [TTL] [MINTTL]
    prefetch AMOUNT [[DURATION] [PERCENTAGE%]]
}
loop

能够检测简单的forwarding循环并终止服务器。

debug

能够从Panic中恢复,用于调试用途

errors

启用错误日志记录,格式:

1
2
3
4
errors {
    # 在DURATION期间抓取匹配REGEXP的错误日志,聚合为单条日志
    consolidate DURATION REGEXP
}

示例:

1
2
3
4
5
6
. {
    errors {
        consolidate 5m ".* i/o timeout$"
        consolidate 30s "^Failed to .+"
    }
}
etcd 

从Etcd V3中读取Zone数据。Etcd中的数据必须编码为SkyDNS风格的消息 。格式:

1
2
3
4
5
6
7
8
etcd [ZONES...] {
    fallthrough [ZONES...]
    path PATH
    endpoint ENDPOINT...
    credentials USERNAME PASSWORD
    upstream [ADDRESS...]
    tls CERT KEY CACERT
}
forward

将DNS请求转发给上游DNS服务器,支持DNS  / TCP  / DNS over TLS。该插件代替原先的proxy插件。

格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# FROM 匹配此后缀的DNS查询会被转发
# TO 上游服务器的端点,支持指定协议,例如tls://9.9.9.9
forward FROM TO... {
    # 空格分隔的,不进行转发的域名列表
    except IGNORED_NAMES...
    # 强制基于TCP协议
    force_tcp
    # 优先使用UDP
    prefer_udp
    # 多久后丢弃连接,
    expire DURATION
    # 判定为不健康需要的连续失败辞书
    max_fails INTEGER
    # DNS over TLS配置
    tls CERT KEY CA
    tls_servername NAME
    # 选取上游服务器的算法,默认random
    policy random|round_robin|sequential
    # 健康检查周期
    health_check DURATION
}

直接转发,用于兜底的示例:

1
forward . 223.5.5.5 1.1.1.1

使用TLS的示例:

1
2
3
4
forward . tls://9.9.9.9 {
    tls_servername dns.quad9.net
    health_check 5s
}

强制TCP转发:

Shell
1
2
3
4
5
svc.k8s.gmem.cc {
  forward . 127.0.0.1:5353 {
    force_tcp
  }
}

从文件中读取上游DNS:

Shell
1
forward . /etc/resolv.conf

 如果CoreDNS运行在K8S中,则CoreDNS的Pod的/etc/resolv.conf内容的基础,取决于kubelet的--resolv-conf配置,默认值指向宿主机的/etc/resolv.conf文件。

上游健康检查

首次转发,随机选取一个上游服务器,后续一直使用,直到它不健康了。

当出现一个错误  —— 任何DNS响应都不看作错误(REFUSED, NOTIMPL, SERVFAIL ... )—— 则CoreDNS启动健康检查循环(默认0.5s一次),直到上游服务器恢复健康。

如果max_fails设置为0则不进行健康检查,总是认为上游服务器是健康的。

CoreDNS不向不健康的上游服务器转发请求,如果所有上游服务器都不健康,则随机选取一个转发。 

health

启用进程级别的监控检查。示例: health :8080,你可以访问:8080/health获取健康状态。

ready

提供readiness探针。示例: ready localhost:8091

hosts

以/etc/hosts风格提供Zone数据,格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# FILE 从文件中读取Zone数据,默认从/etc/hosts读取
# ZONES 此插件的权威Zone
hosts [FILE [ZONES...]] {
    # 内联的HOSTS条目
    [INLINE]
    # 修改生成的DNS记录的DNS TTL
    ttl SECONDS
    # 禁止自动生成in-addr.arpa或ip6.arpa条目
    no_reverse
    # 重新载入文件的间隔,例如 300ms 1.5h 2h45m
    reload DURATION
    # 对于匹配的ZONES,如果此插件没有记录,则由下一个插件处理
    fallthrough [ZONES...]
}

示例:

1
2
3
4
hosts {
   172.21.0.1      kdc-1
   fallthrough
}
import 

该插件有两个用途:

  1. 导入其它配置文件到主配置文件
  2. 导入配置片段 

格式: import PATTERN

log

记录查询日志,格式:

1
2
3
4
5
6
7
# NAMES 匹配的DNS查询被记录
# FORMAT 日志格式,
log [NAMES...] [FORMAT]
 
log [NAMES...] [FORMAT] {
    class CLASSES...
}
CLASSES

指定哪些RCode会被记录

取值 说明
success

记录成功的请求

denial 记录NXDOMAIN的请求、NOERROR但是没有数据的(nodata,域名存在,但是请求的记录类型没有)
error 记录SERVFAIL、NOTIMP、REFUSED等等,任何提示远程服务器不愿意解析请求的应答都包含在内
all 默认,记录所有请求
FORMAT

日志格式,默认格式为:

1
2
{remote}:{port} - {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}"
    {rcode} {>rflags} {rsize} {duration}

详细请参考官方文档。 

rewrite

执行内部的消息重写。格式:

1
2
3
4
5
6
7
# FIELD 请求/应答的什么字段需要被重写
# type 请求的TYPE字段
# class 消息的类型
# name 请求中的DNS名称
# answer name 应答中的DNS名称
# ttl TTL值
rewrite [continue|stop] FIELD [FROM TO|FROM TTL]

要重写DNS请求中的名称,使用格式:

1
rewrite [continue|stop] name [exact|prefix|suffix|substring|regex] STRING STRING

示例:

1
2
3
rewrite name substring k8s.gmem.cc k8s.gmem.cc
rewrite name regex (.*)\.gmem\.cc {1}.gmem.cc
rewrite name suffix .gmem.cc. .gmem.cc.

要重写DNS响应中的名称,参考:

1
2
3
4
rewrite stop {
    name regex (.*)\.gmem\.site {1}.gmem.cc
    answer name (.*)\.gmem\.site {1}.gmem.cc
} 
template

提供一个模板,基于请求来动态的生成响应。格式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# CLASS 查询分类,IN或ANY
# TYPE 查询类型,A、PTR... ANY匹配所有类型
# ZONE 此模板的Zone
template CLASS TYPE [ZONE...] {
    # 匹配请求DNS名称的正则式
    match REGEX...
    # DNS应答
    answer RR
    additional RR
    authority RR
    rcode CODE
    # 用于解析CNAMEs的上有集群
    upstream
    fallthrough [ZONE...]
}
泛域名

使用template插件可以实现泛域名解析,下面是一个例子:

1
2
3
4
5
template IN A mesh.gmem.cc {
  match .*\.mesh\.gmem\.cc
  answer "{{ .Name }} 60 IN A 10.0.11.11"
  fallthrough
}

当前版本有一个奇怪的行为: 上述配置导致hosts插件指定的10.0.11.1 mesh.gmem.cc条目失效,必须指定fallthrough才能避免此问题。

kubernetes

需要注意fallthrough不能包含集群域名后缀:

Conf
1
2
3
4
kubernetes k8s.gmem.cc{
   # 注意这种配置
   fallthrough k8s.gmem.cc
}

 否则会出现DNS解析错误,在Pod里面解析chartmuseum.gmem.cc,会自动添加Search domain导致解析出错:

Shell
1
2
[ERROR] plugin/errors: 2 chartmuseum.gmem.cc.devops.svc.k8s.gmem.cc. A: plugin/proxy: no next plugin found
[ERROR] plugin/errors: 2 chartmuseum.gmem.cc.svc.k8s.gmem.cc. AAAA: plugin/proxy: no next plugin found
← SOFAStack学习笔记
Gin学习笔记 →

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Related Posts

  • 通过自定义资源扩展Kubernetes
  • 利用kind搭建本地K8S集群
  • Kubernetes的Service Catalog机制
  • 为裸金属K8S集群提供外部负载均衡器
  • 基于Rook的Kubernetes存储方案

Recent Posts

  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
  • A Comprehensive Study of Kotlin for Java Developers
  • 背诵营笔记
  • 利用LangChain和语言模型交互
  • 享学营笔记
ABOUT ME

汪震 | Alex Wong

江苏淮安人,现居北京。目前供职于腾讯云,专注容器方向。

GitHub:gmemcc

Git:git.gmem.cc

Email:gmemjunk@gmem.cc@me.com

ABOUT GMEM

绿色记忆是我的个人网站,域名gmem.cc中G是Green的简写,MEM是Memory的简写,CC则是我的小天使彩彩名字的简写。

我在这里记录自己的工作与生活,同时和大家分享一些编程方面的知识。

GMEM HISTORY
v2.00:微风
v1.03:单车旅行
v1.02:夏日版
v1.01:未完成
v0.10:彩虹天堂
v0.01:阳光海岸
MIRROR INFO
Meta
  • Log in
  • Entries RSS
  • Comments RSS
  • WordPress.org
Recent Posts
  • Investigating and Solving the Issue of Failed Certificate Request with ZeroSSL and Cert-Manager
    In this blog post, I will walk ...
  • A Comprehensive Study of Kotlin for Java Developers
    Introduction Purpose of the Study Understanding the Mo ...
  • 背诵营笔记
    Day 1 Find Your Greatness 原文 Greatness. It’s just ...
  • 利用LangChain和语言模型交互
    LangChain是什么 从名字上可以看出来,LangChain可以用来构建自然语言处理能力的链条。它是一个库 ...
  • 享学营笔记
    Unit 1 At home Lesson 1 In the ...
  • K8S集群跨云迁移
    要将K8S集群从一个云服务商迁移到另外一个,需要解决以下问题: 各种K8S资源的迁移 工作负载所挂载的数 ...
  • Terraform快速参考
    简介 Terraform用于实现基础设施即代码(infrastructure as code)—— 通过代码( ...
  • 草缸2021
    经过四个多月的努力,我的小小荷兰景到达极致了状态。

  • 编写Kubernetes风格的APIServer
    背景 前段时间接到一个需求做一个工具,工具将在K8S中运行。需求很适合用控制器模式实现,很自然的就基于kube ...
  • 记录一次KeyDB缓慢的定位过程
    环境说明 运行环境 这个问题出现在一套搭建在虚拟机上的Kubernetes 1.18集群上。集群有三个节点: ...
  • eBPF学习笔记
    简介 BPF,即Berkeley Packet Filter,是一个古老的网络封包过滤机制。它允许从用户空间注 ...
  • IPVS模式下ClusterIP泄露宿主机端口的问题
    问题 在一个启用了IPVS模式kube-proxy的K8S集群中,运行着一个Docker Registry服务 ...
  • 念爷爷
      今天是爷爷的头七,十二月七日、阴历十月廿三中午,老人家与世长辞。   九月初,回家看望刚动完手术的爸爸,发

  • 6 杨梅坑

  • liuhuashan
    深圳人才公园的网红景点 —— 流花山

  • 1 2020年10月拈花湾

  • 内核缺陷触发的NodePort服务63秒延迟问题
    现象 我们有一个新创建的TKE 1.3.0集群,使用基于Galaxy + Flannel(VXLAN模式)的容 ...
  • Galaxy学习笔记
    简介 Galaxy是TKEStack的一个网络组件,支持为TKE集群提供Overlay/Underlay容器网 ...
TOPLINKS
  • Zitahli's blue 91 people like this
  • 梦中的婚礼 64 people like this
  • 汪静好 61 people like this
  • 那年我一岁 36 people like this
  • 为了爱 28 people like this
  • 小绿彩 26 people like this
  • 杨梅坑 6 people like this
  • 亚龙湾之旅 1 people like this
  • 汪昌博 people like this
  • 彩虹姐姐的笑脸 24 people like this
  • 2013年11月香山 10 people like this
  • 2013年7月秦皇岛 6 people like this
  • 2013年6月蓟县盘山 5 people like this
  • 2013年2月梅花山 2 people like this
  • 2013年淮阴自贡迎春灯会 3 people like this
  • 2012年镇江金山游 1 people like this
  • 2012年徽杭古道 9 people like this
  • 2011年清明节后扬州行 1 people like this
  • 2008年十一云龙公园 5 people like this
  • 2008年之秋忆 7 people like this
  • 老照片 13 people like this
  • 火一样的六月 16 people like this
  • 发黄的相片 3 people like this
  • Cesium学习笔记 90 people like this
  • IntelliJ IDEA知识集锦 59 people like this
  • 基于Kurento搭建WebRTC服务器 38 people like this
  • Bazel学习笔记 37 people like this
  • PhoneGap学习笔记 32 people like this
  • NaCl学习笔记 32 people like this
  • 使用Oracle Java Mission Control监控JVM运行状态 29 people like this
  • Ceph学习笔记 27 people like this
  • 基于Calico的CNI 27 people like this
  • Three.js学习笔记 24 people like this
Tag Cloud
ActiveMQ AspectJ CDT Ceph Chrome CNI Command Cordova Coroutine CXF Cygwin DNS Docker eBPF Eclipse ExtJS F7 FAQ Groovy Hibernate HTTP IntelliJ IO编程 IPVS JacksonJSON JMS JSON JVM K8S kernel LB libvirt Linux知识 Linux编程 LOG Maven MinGW Mock Monitoring Multimedia MVC MySQL netfs Netty Nginx NIO Node.js NoSQL Oracle PDT PHP Redis RPC Scheduler ServiceMesh SNMP Spring SSL svn Tomcat TSDB Ubuntu WebGL WebRTC WebService WebSocket wxWidgets XDebug XML XPath XRM ZooKeeper 亚龙湾 单元测试 学习笔记 实时处理 并发编程 彩姐 性能剖析 性能调优 文本处理 新特性 架构模式 系统编程 网络编程 视频监控 设计模式 远程调试 配置文件 齐塔莉
Recent Comments
  • qg on Istio中的透明代理问题
  • heao on 基于本地gRPC的Go插件系统
  • 黄豆豆 on Ginkgo学习笔记
  • cloud on OpenStack学习笔记
  • 5dragoncon on Cilium学习笔记
  • Archeb on 重温iptables
  • C/C++编程:WebSocketpp(Linux + Clion + boostAsio) – 源码巴士 on 基于C/C++的WebSocket库
  • jerbin on eBPF学习笔记
  • point on Istio中的透明代理问题
  • G on Istio中的透明代理问题
  • 绿色记忆:Go语言单元测试和仿冒 on Ginkgo学习笔记
  • point on Istio中的透明代理问题
  • 【Maven】maven插件开发实战 – IT汇 on Maven插件开发
  • chenlx on eBPF学习笔记
  • Alex on eBPF学习笔记
  • CFC4N on eBPF学习笔记
  • 李运田 on 念爷爷
  • yongman on 记录一次KeyDB缓慢的定位过程
  • Alex on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • will on Istio中的透明代理问题
  • haolipeng on 基于本地gRPC的Go插件系统
  • 吴杰 on 基于C/C++的WebSocket库
©2005-2025 Gmem.cc | Powered by WordPress | 京ICP备18007345号-2