个人笔记,适合对 Kubernetes 有一定了解的同学。
前言
最近一直在学习 Kubernetes,但是手头没有个自有域名,要测试 ingress 就比较麻烦,每次都是手动改 hosts 文件。。
今天突然想到——K8s 内部就是用 DNS 做的服务发现,我为啥不自己弄一个 DNS 服务器呢?然后所有节点的 DNS 都配成它,这样有需要时直接改这个 DNS 服务器的配置就行, 一劳永逸。
我首先想到的是 群晖/Windows Server 自带的那种自带图形化界面的 DNS 服务器,但是这俩都是平台特定的。
网上搜一圈没找到类似带 UI 的 DNS 工具,所以决定就用 CoreDNS,刚好熟悉一下它的具体使用。
不过讲 CoreDNS 前,我们还是先来熟悉一下 DNS 吧。
一、DNS 是个啥?
DNS,即域名系统(Domain Name System),是一项负责将一个 human readable 的所谓域名,转换成一个 ip 地址的协议。
而域名的好处,有如下几项:
- 域名对人类更友好,可读的字符串总比一串 ip 数字好记。
- 一个域名可以对应多个 ip,实现所谓的负载均衡。
- 多个域名可以对应同一个 ip,在系统内部再通过软件将数据转发到对应的程序。
DNS 协议是一个基于 UDP 的应用层协议,它默认使用 53 端口进行通信。
应用程序通常将 DNS 解析委派给操作系统的 DNS Resolver 来执行,程序员对它几乎无感知。
DNS 虽然说一般只用来查个 ip 地址,但是它提供的记录类型还蛮多的,有如下几种:
A
记录:它记录域名与 IPv4 地址的对应关系。目前用的最多的 DNS 记录就是这个。AAAA
记录:它对应的是 IPv6,可以理解成新一代的A
记录。以后会用的越来越多的。NS
记录:记录 DNS 域对应的权威服务器域名,权威服务器域名必须要有对应的A
记录。- 通过这个记录,可以将子域名的解析分配给别的 DNS 服务器。
CNAME
记录: 记录域名与另一个域名的对应关系,用于给域名起别名。这个用得也挺多的。MX
记录:记录域名对应的邮件服务器域名,邮件服务器的域名必须要有对应的A
记录。SRV
记录:SRV 记录用于提供服务发现,看名字也能知道它和 SERVICE 有关。- SRV 记录的内容有固定格式:
优先级 权重 端口 目标地址
,例如0 5 5060 sipserver.example.com
- 主要用于企业域控(AD)、微服务发现(Kubernetes)
- SRV 记录的内容有固定格式:
上述的所有 DNS 记录,都是属于将域名解析为 IP 地址,或者另一个域名,这被称做** DNS 正向解析。
除了这个正向解析外,还有个非常冷门的反向解析,基本上只在设置邮件服务器时才会用到**。
反向解析主要的记录类型是:PTR
记录,它提供将 IP 地址反向解析为域名的功能。
而且因为域名是从右往左读的(最右侧是根, www.baidu.com.
),而 IP 的网段(如 192.168.0.0/16
)刚好相反,是左边优先。
因此 PTR 记录的“域名”必须将 IP 地址反着写,末尾再加上 .in-addr.arpa.
表示这是一个反向解析的域名。(ipv6 使用 ip6.arpa.
)
拿 baidu.com 的邮件服务器测试一下:
其他还有些 TXT
、CAA
等奇奇怪怪的记录,就用到的时候自己再查了。
二、域名的分层结构
国际域名系统被分成四层:
- 根域(Root Zone):所有域名的根。
- 根域名服务器负责解析
顶级域名
,给出顶级域名的 DNS 服务器地址。 - 全世界仅有十三组根域名服务器,这些服务器的 ip 地址基本不会变动。
- 它的域名是 "",空字符串。而它的全限定域名(FQDN)是
.
,因为 FQDN 总是以.
结尾。(FQDN 在后面解释,可暂时忽略)
- 根域名服务器负责解析
- 顶级域(Top Level Domains, TLD):
.com
.cn
等国际、国家级的域名- 顶级域名服务器负责解析
次级域名
,给出次级域名的 DNS 服务器地址。 - 每个顶级域名都对应各自的服务器,它们之间是完全独立的。
.cn
的域名解析仅由.cn
顶级域名服务器提供。
- 顶级域名服务器负责解析
- 次级域(Second Level Domains):这个才是个人/企业能够买到的域名,比如
baidu.com
- 每个次级域名都有一到多个权威 DNS 服务器,这些 DNS 服务器会以 NS 记录的形式保存在对应的顶级域名(TLD)服务器中。
- 权威域名服务器则负责给出最终的解析结果:ip 地址(A 记录 ),另一个域名(CNAME 记录)、另一个 DNS 服务器(NS 记录)等。
- 子域(Sub Domians):
*.baidu.com
统统都是baidu.com
的子域。- 每一个子域都可以有自己独立的权威 DNS 服务器,这通过在子域中添加 NS 记录实现。
普通用户通常是通过域名提供商如阿里云购买的次级域名,接下来我们以 rea.ink
为例介绍域名的购买到可用的整个流程。
这时阿里云会向该中插入几条 NS 记录,指向阿里云的次级 DNS 服务器(vip1.alidns.com
)。
- 你在某域名提供商处购买了一个域名
rea.ink
- 域名提供商向
.ink
对应的顶级域名服务器中插入一条以上的 NS 记录,指向它自己的次级 DNS 服务器,如dns25.hichina.com.
- 你在该域名提供商的 DNS 管理界面中添加
A
记录,值为你的服务器 IP。 - OK 现在 ping 一下
rea.ink
,就会发现它已经解析到你自己的服务器了。
上述流程中忽略了我大天朝的特殊国情——备案,勿介意。
三、DNS 递归解析器:在浏览器中输入域名后发生了什么?
下面的图片拷贝自 Amazon Aws 文档,它展示了在不考虑任何 DNS 缓存的情况下,一次 Web 请求的经过,详细描绘了 DNS 解析的部分。
其中的第 3 4 5 步按顺序向前面讲过的根域名服务器、顶级域名服务器、权威域名服务器发起请求,以获得下一个 DNS 服务器的信息。这很清晰。
图中当前还没介绍的部分,是紫色的 DNS Resolver
(域名解析器),也叫 Recursive DNS resolver
(DNS 递归解析器)。
它本身只负责递归地请求 3 4 5 步中的上游服务器,然后把获取的最终结果返回给客户端,同时将记录缓存到本地以加快解析速度。
这个 DNS 解析器,其实就是所谓的公共 DNS 服务器:Google 的 8.8.8.8
,国内著名的 114.114.114.114
。
这些公共 DNS 用户量大,缓存了大量的 DNS 记录,有效地降低了上游 DNS 服务器的压力,也加快了网络上的 DNS 查询速度。
接下来使用 dig +trace baidu.com
复现一下上述的查询流程(这种情况下 dig 自己就是一个 DNS 递归解析器):
另外前面有讲过 DNS 的反向解析,也是同样的层级结构,是从根服务器开始往下查询的,下面拿 baidu 的一个邮件服务器进行测试:
TTL(Time To Live)
上面讲了公共 DNS 服务器通过缓存技术,降低了上游 DNS 服务器的压力,也加快了网络上的 DNS 查询速度。
可缓存总得有个过期时间吧!为了精确地控制 DNS 记录的过期时间,每条 DNS 记录都要求设置一个时间属性——TTL,单位为秒。这个时间可以自定义。
任何一条 DNS 缓存,在超过过期时间后都必须丢弃!
四、本地 DNS 服务器
这类服务器只在当前局域网内有效,是一个私有的 DNS 服务器,企业常用。一般通过 DHCP 或者手动配置的方式,使内网的服务器都默认使用局域网 DNS 服务器进行解析。
局域网 DNS 服务器的规模与层级,视局域网的大小而定。一般小公司一个就行,要容灾设三个副本也够了。
以 CoreDNS 为例,局域网 DNS 服务器也可以被设置成一个 DNS Resolver,可以设置只转发特定域名的 DNS 解析。这叫将某个域设为转发区域。
著名的 Kubernetes 容器集群系统(它内部使用的是自己的虚拟局域网),就是使用的 CoreDNS 进行局域网的域名解析,以实现服务发现功能。
五、操作系统的 DNS 解析器
应用程序实际上都是调用的操作系统的 DNS Resolver 进行域名解析的。在 Linux 中 DNS Resolver 由 glibc/musl 提供,配置文件为 /etc/resolv.conf
。
比如 Python 的 DNS 解析,就来自于标准库的 socket 包,这个包只是对底层 c 语言库的一个简单封装。
基本上只有专门用于网络诊断的 DNS 工具包,才会自己实现 DNS 协议。
1. hosts 文件
操作系统中还有一个特殊文件:Linux 中的 /etc/hosts
和 Windows 中的 C:\Windows\System32\drivers\etc\hosts
系统中的 DNS resolver 会首先查看这个 hosts
文件中有没有该域名的记录,如果有就直接返回了。没找到才会去查找本地 DNS 缓存、别的 DNS 服务器。
只有部分专门用于网络诊断的应用程序(e.g. dig)不会依赖 OS 的 DNS 解析器,因此这个 hosts
会失效。hosts
对于绝大部分程序都有效。
移动设备上 hosts 可能会失效,部分 app 会绕过系统,使用新兴的 HTTPDNS 协议进行 DNS 解析。
2. HTTPDNS
传统的 DNS 协议因为使用了明文的 UDP 协议,很容易被劫持。顺应移动互联网的兴起,目前一种新型的 DNS 协议——HTTPDNS 应用越来越广泛,国内的阿里云腾讯云都提供了这项功能。
HTTPDNS 通过 HTTP 协议直接向权威 DNS 服务器发起请求,绕过了一堆中间的 DNS 递归解析器。好处有二:
- 权威 DNS 服务器能直接获取到客户端的真实 IP(而不是某个中间 DNS 递归解析器的 IP),能实现就近调度。
- 因为是直接与权威 DNS 服务器连接,避免了 DNS 缓存污染的问题。
HTTPDNS 协议需要程序自己引入 SDK,或者直接请求 HTTP API。
3. 默认 DNS 服务器
操作系统的 DNS 解析器通常会允许我们配置多个上游 Name Servers,比如 Linux 就是通过 /etc/resolv.conf
配置 DNS 服务器的。
$ cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
search lan
不过现在这个文件基本不会手动修改了,各 Linux 发行版都推出了自己的网络配置工具,由这些工具自动生成 Linux 的各种网络配置,更方便。
比如 Ubuntu 就推荐使用 netplan 工具进行网络设置。
Kubernetes 就是通过使用容器卷映射的功能,修改 /etc/resolv.conf,使集群的所有容器都使用集群 DNS 服务器(CoreDNS)进行 DNS 解析。
通过重复使用 nameserver
字段,可以指定多个 DNS 服务器(Linux 最多三个)。DNS 查询会按配置中的顺序选用 DNS 服务器。
仅在靠前的 DNS 服务器没有响应(timeout)时,才会使用后续的 DNS 服务器!所以指定的服务器中的 DNS 记录最好完全一致!!!不要把第一个配内网 DNS,第二个配外网!!!
4. DNS 搜索域
上一小节给出的 /etc/resolv.conf
文件内容的末尾,有这样一行: search lan
,它指定的,是所谓的 DNS 搜索域。
讲到 DNS 搜索域
,就不得不提到一个名词:全限定域名(Full Qulified Domain Name, FQDN),即一个域名的完整名称,www.baidu.com
。
一个普通的域名,有下列四种可能:
www.baidu.com.
: 末尾的.
表示根域,说明www.baidu.com
是一个 FQDN,因此不会使用搜索域!www.baidu.com
: 末尾没.
,但是域名包含不止一个.
。首先当作 FQDN 进行查询,没查找再按顺序在各搜索域中查询。/etc/resolv.conf
的options
参数中,可以指定域名中包含.
的临界个数,默认是 1.
local
: 不包含.
,被当作host
名称,非 FQDN。首先在/etc/hosts
中查找,没找到的话,再按顺序在各搜索域中查找。
上述搜索顺序可以通过
host -v
进行测试,该命令会输出它尝试过的所有 FQDN。
修改/etc/resolv.conf
中的search
属性并测试,然后查看输出。
就如上面说例举的,在没有 DNS 搜索域
这个东西的条件下,我们访问任何域名,都必须输入一个全限定域名 FQDN。
有了搜索域我们就可以稍微偷点懒,省略掉域名的一部分后缀,让 DNS Resolver 自己去在各搜索域中搜索。
在 Kubernetes 中就使用到了搜索域,k8s 中默认的域名 FQDN 是 service.namespace.svc.cluster.local
,
但是对于 default namespace 中的 service,我们可以直接通过 service
名称查询到它的 IP。
对于其他名字空间中的 service,也可以通过 service.namespace
查询到它们的 IP,不需要给出 FQDN。
Kubernetes 中 /etc/resolv.conf
的示例如下:
nameserver 10.43.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
可以看到 k8s 设置了一系列的搜索域,并且将 .
的临界值设为了 5。
也就是少于 5 个 dots 的域名,都首先当作非 FQDN 看待,优先在搜索域里面查找。
该配置文件的详细描述参见 manpage - resolv.conf,或者在 Linux 中使用 man resolv.conf
命令查看。
六、DNS 诊断的命令行工具
dig +trace baidu.com # 诊断 dns 的主要工具,非常强大
host -a baidu.com # host 基本就是 dig 的弱化版,不过 host 有个有点就是能打印出它测试过的所有 FQDN
nslookup baidu.com # 和 host 没啥大差别,多个交互式查询不过一般用不到
whois baidu.com # 查询域名注册信息,内网诊断用不到
详细的使用请 man dig
七、CoreDNS 的使用
主流的本地 DNS 服务器中,提供 UI 界面的有 Windows DNS Server 和群晖 DNS Server,很方便,不过这两个都是操作系统绑定的。
接下来以 CoreDNS 为例,讲述如何配置一个 DNS 服务器,添加私有的 DNS 记录,并设置转发规则以解析公网域名。
参考
- DNS 原理入门
- What Is DNS? | How DNS Works - Cloudflare
- What is DNS? - Amazon AWS
- 鸟哥的 Linux 私房菜——主機名稱控制者: DNS 伺服器
- CoreDNS - Manual
- Kubernetes - DNS for Services and Pods