CoreDNS构建高性能DNS服务器

一、 概述与核心概念

1.1 什么是 CoreDNS?

CoreDNS 是一个用 Go 语言编写的、高度可扩展和插件化的 DNS 服务器。它来自云原生计算基金会(CNCF),是 Kubernetes 的默认 DNS 服务器,其设计目标是易于使用且功能强大。

核心特点

  • 插件化架构:几乎所有功能都通过插件实现,可以灵活组合,适用于传统 DNS、服务发现、负载均衡等多种场景。
  • 高性能与可靠性:基于 Go 语言,性能优异。支持自动重试、健康检查和负载均衡。
  • 易于配置:使用简单易懂的 Caddyfile 格式配置文件。
  • Kubernetes 原生:深度集成 K8s,用于集群内服务发现。
1.2 CoreDNS 与传统 DNS(如 BIND)的区别

传统 DNS 服务器功能固定且庞大。CoreDNS 则像一个“DNS 功能总线”,通过加载不同的插件来实现特定功能,这使得它更轻量、更灵活。正如其官方所说:CoreDNS is powered by plugins.

1.3 核心配置文件:Corefile

CoreDNS 的行为由 Corefile 定义。其基本结构如下:

1
2
3
4
5
# ZONE: 定义服务器负责的区,PORT 默认为 53
ZONE:[PORT] {
# PLUGIN: 定义要加载的插件及其参数
[PLUGIN] [PLUGIN_ARGUMENTS]...
}

示例

1
2
3
4
5
6
7
.:53 {
whoami
}

weiyigeek.top {
file db.weiyigeek.top
}

二、 安装与基础配置

2.1 安装 CoreDNS

方式一:二进制安装(推荐)

1
2
3
4
COREDNS_VERSION="1.11.1"
wget https://github.com/coredns/coredns/releases/download/v${COREDNS_VERSION}/coredns_${COREDNS_VERSION}_linux_amd64.tgz
tar xf coredns_${COREDNS_VERSION}_linux_amd64.tgz -C /usr/local/bin/
ln -s /usr/local/bin/coredns /usr/bin/coredns

方式二:从源码编译

1
2
3
4
5
git clone -b v1.11.1 https://github.com/coredns/coredns
cd coredns
make
# 或使用 Docker 环境编译
docker run --rm -i -t -v $PWD:/v -w /v golang:1.21 make
2.2 系统服务化部署
  1. 创建专用用户和目录
    1
    2
    3
    useradd coredns -s /sbin/nologin
    mkdir -p /etc/coredns/
    chown -R coredns /etc/coredns/
  2. 创建 Systemd 服务文件 (/usr/lib/systemd/system/coredns.service):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [Unit]
    Description=CoreDNS DNS server
    Documentation=https://coredns.io
    After=network.target

    [Service]
    LimitNOFILE=1048576
    User=coredns
    WorkingDirectory=/etc/coredns
    ExecStart=/usr/bin/coredns -conf=/etc/coredns/Corefile
    ExecReload=/bin/kill -SIGUSR1 $MAINPID
    Restart=on-failure

    [Install]
    WantedBy=multi-user.target
1
2
systemctl daemon-reload
systemctl enable coredns
  1. 配置防火墙
    1
    2
    firewall-cmd --permanent --add-service=dns
    firewall-cmd --reload
2.3 基础配置文件示例

创建 /etc/coredns/Corefile,配置一个简单的 DNS 服务器,使用 hosts 插件进行本地解析,并转发未知查询到上游 DNS。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.:53 {
bind 0.0.0.0
hosts {
# 自定义本地解析
192.168.1.2 www.weiyigeek.top
192.168.1.3 blog.weiyigeek.top
ttl 60
reload 1m
fallthrough # 未匹配时继续执行下一个插件
}
# 转发未知查询到公共 DNS
forward . 223.6.6.6 114.114.114.114
cache 120 # 缓存
log # 记录日志
errors # 记录错误
}
  1. 启动并测试
    1
    2
    3
    systemctl start coredns
    dig www.weiyigeek.top @localhost
    dig google.com @localhost # 应被转发解析

三、 插件系统详解

3.1 插件概述与工作模式

CoreDNS 的功能完全由插件驱动。插件分为两类:

  • Normal 插件:参与请求处理逻辑,并出现在插件链中(如 hosts, file, forward)。
  • Other 插件:不参与请求逻辑,仅修改服务器配置(如 health, ready, prometheus)。

插件链执行逻辑

  1. 请求进入匹配的 Server Zone。
  2. plugin.cfg 定义的顺序依次执行插件链上的插件。
  3. 每个插件决定如何处理请求:直接响应、传递 (fallthrough)、或添加信息后继续传递。

查看可用插件coredns -plugins

3.2 常用插件详解
hosts 插件

用于从 /etc/hosts 风格的文件或内联配置提供 A/AAAA/PTR 记录。适合少量静态记录。

  • 语法
    1
    2
    3
    4
    5
    6
    hosts [FILE] {
    [INLINE_ENTRIES]
    ttl SECONDS
    reload DURATION
    fallthrough [ZONES...]
    }
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    .:53 {
    hosts {
    192.168.1.10 api.internal
    192.168.1.11 db.internal
    fallthrough
    }
    forward . 8.8.8.8
    }
file 插件

用于从符合 RFC 1035 标准的主区域文件提供 DNS 服务。适合大量记录或需要标准区域文件管理的场景。

  • 语法
    1
    2
    3
    file DBFILE [ZONES...] {
    reload DURATION
    }
  • 示例
    1
    2
    3
    weiyigeek.top {
    file /etc/coredns/db.weiyigeek.top
    }
    *区域文件示例 (/etc/coredns/db.weiyigeek.top)*:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $TTL 86400
    @ IN SOA ns1.weiyigeek.top. admin.weiyigeek.top. (
    2023082501 ; Serial
    7200 ; Refresh
    3600 ; Retry
    1209600 ; Expire
    3600 ) ; Negative Cache TTL
    ;
    @ IN NS ns1
    ns1 IN A 192.168.1.100
    www IN A 192.168.1.101
forward 插件

将查询转发到上游 DNS 服务器。是构建递归解析器或指定上游的关键插件。

  • 语法
    1
    forward . UPSTREAM_DNS...
  • 示例
    1
    2
    3
    4
    .:53 {
    forward . 8.8.8.8:53 1.1.1.1:53 /etc/resolv.conf
    cache 60
    }
cache 插件

缓存 DNS 响应,减少上游查询,提升性能。

  • 语法
    1
    2
    3
    4
    cache [TTL] {
    success CAPACITY [TTL]
    denial CAPACITY [TTL]
    }
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    .:53 {
    forward . 8.8.8.8
    cache 120 # 缓存所有响应120秒
    # 或更精细控制
    cache {
    success 5000 300
    denial 1000 60
    }
    }
3.3 Kubernetes 集成插件 (kubernetes)

CoreDNS 在 K8s 中的核心插件,用于服务发现(将 Service 名称解析为 ClusterIP)。

  • 典型 K8s 配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    .:53 {
    errors
    health
    kubernetes cluster.local in-addr.arpa ip6.arpa {
    pods verified
    fallthrough in-addr.arpa ip6.arpa
    }
    prometheus :9153
    forward . /etc/resolv.conf
    cache 30
    loop
    reload
    loadbalance
    }

四、 高级配置与实战

4.1 多区域与复杂配置

一个 Corefile 可以定义多个服务器块,处理不同域或端口的请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 处理内部域
internal.company {
file /etc/coredns/db.internal
log
}

# 处理外部域,监听在5300端口
example.com:5300 {
forward . 8.8.8.8
cache 300
}

# 默认处理所有其他查询
.:53 {
forward . 1.1.1.1 9.9.9.9
cache 60
errors
log
}
4.2 DNSSEC 配置

CoreDNS 支持动态 DNSSEC 签名。

  1. 生成 DNSSEC 密钥
    1
    2
    3
    cd /etc/coredns
    dnssec-keygen -a ECDSAP256SHA256 -f KSK weiyigeek.top
    # 生成 Kweiyigeek.top.+013+12345.key 和 .private 文件
  2. 使用 dnssec 插件(动态签名响应):
    1
    2
    3
    4
    5
    6
    weiyigeek.top {
    file /etc/coredns/db.weiyigeek.top
    dnssec {
    key file /etc/coredns/Kweiyigeek.top.+013+12345.key
    }
    }
  3. 使用 sign 插件(预签名区域文件):
    1
    2
    3
    4
    5
    6
    weiyigeek.top {
    sign /etc/coredns/db.weiyigeek.top {
    key file /etc/coredns/Kweiyigeek.top.+013+12345.key
    directory /var/lib/coredns
    }
    }
    签名后的区域文件将保存在 /var/lib/coredns/db.weiyigeek.top.signed
4.3 TSIG 配置(事务签名)

用于验证和签名 DNS 请求/响应,常用于区域传输(AXFR/IXFR)安全。

  1. 生成 TSIG 密钥
    1
    tsig-keygen -a hmac-sha256 dns-tsig-key. > /etc/coredns/dns-tsig.secrets
  2. 配置 tsig 插件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    weiyigeek.top {
    file /etc/coredns/db.weiyigeek.top
    tsig {
    secrets /etc/coredns/dns-tsig.secrets
    require AXFR IXFR # 要求区域传输必须签名
    }
    transfer {
    to * # 允许向任何请求者传输(生产环境应限制IP)
    }
    }
4.4 使用 etcd 插件实现动态服务发现

可以将服务记录存储在 etcd 中,CoreDNS 从中读取。

1
2
3
4
5
6
7
8
9
etcd-weiyigeek.local:53 {
etcd {
path /skydns
endpoint http://172.22.50.98:2379
fallthrough
}
cache 160
log
}

在 etcd 中存储记录

1
etcdctl put /skydns/local/etcd-weiyigeek/www '{"host":"172.22.50.100","ttl":60}'

查询dig www.etcd-weiyigeek.local

五、 故障排查与性能优化

  • 查看日志:确保配置中启用了 logerrors 插件。
  • 检查插件顺序:插件链顺序很重要,例如 cache 应在 forward 之后。
  • 监控:启用 prometheus 插件(默认在 :9153 端口)以获取指标。
  • 性能调优
    • 合理设置 cache 插件的 TTL 和容量。
    • 根据负载调整 forward 插件中的上游 DNS 服务器列表。
    • 使用 loadbalance 插件实现上游 DNS 的轮询负载均衡。

六、 总结

CoreDNS 凭借其插件化、高性能和易配置的特性,已成为从传统 DNS 到云原生服务发现的理想选择。通过灵活组合 hostsfileforwardcache 等插件,可以轻松构建出满足各种需求的 DNS 架构。对于 Kubernetes 环境,它更是不可或缺的核心组件。

官方资源


提示:生产环境部署时,请务必关注安全最佳实践,如使用非 root 用户运行、配置适当的防火墙规则、为区域传输启用 TSIG、以及定期更新 CoreDNS 版本。