4. ExternalDNS 核心原理
ExternalDNS 是一个 Kubernetes 原生的附加组件,它通过监听集群内 Service、Ingress 等资源的变化,自动同步 DNS 记录到外部的 DNS 提供商。理解其核心工作机制——DNS Provider、Source、Owner 和 TTL——是构建可靠多集群 DNS 流水线的基础。
核心概念速览: ExternalDNS 通过 Source 发现需要管理的 DNS 端点,通过 DNS Provider 执行实际的记录增删改查,通过 Owner 机制防止记录冲突,通过 TTL 控制缓存时间。
4.1 整体工作流程
ExternalDNS 以循环控制器的模式运行,其核心流程可概括为以下步骤:
- 列举 Sources: 从 Kubernetes API 中获取所有匹配的 Ingress、Service(类型为 LoadBalancer 或 NodePort)等资源。
- 提取端点: 从这些资源中提取出 DNS 名称和目标 IP 地址(或 Hostname),形成
Endpoints列表。 - 查询当前 DNS 记录: 调用 DNS Provider 的 API,获取当前托管区中已有的记录。
- 差异计算与调和: 对比期望的 Endpoints 与实际的 DNS 记录,生成创建、更新或删除的操作计划。
- 执行变更: 通过 DNS Provider 的 API 执行操作计划,并应用 Owner 标签和 TTL 设置。
4.2 DNS Provider:与外部 DNS 服务的桥梁
DNS Provider 是 ExternalDNS 与外部 DNS 服务交互的适配层。它封装了不同 DNS 服务商的 API 差异,提供统一的接口用于 DNS 记录的增删改查。
| Provider 名称 | 支持的 DNS 服务 | 记录类型支持 | 多集群场景注意事项 |
|---|---|---|---|
| AWS Route53 | Amazon Route 53 | A, AAAA, CNAME, TXT | 需 IAM 权限控制;TXT 记录用于 Owner 标识 |
| Google Cloud DNS | Google Cloud DNS | A, AAAA, CNAME, TXT | 使用服务账号;支持托管区自动发现 |
| Azure DNS | Azure DNS | A, AAAA, CNAME, TXT | 需 Azure 身份认证;资源组管理 |
| 阿里云 DNS | 阿里云解析 DNS | A, AAAA, CNAME, TXT | AccessKey 管理;支持 PrivateZone |
| CoreDNS (etcd) | CoreDNS + etcd 后端 | A, AAAA, CNAME | 适合私有云;需自行维护 etcd 集群 |
最佳实践: 在多集群场景中,建议为每个集群使用独立的 DNS Provider 实例或使用
--provider-owner-id 参数区分,避免集群间误操作对方的 DNS 记录。
4.3 Source:DNS 记录的来源
Source 定义了 ExternalDNS 从哪些 Kubernetes 资源中提取 DNS 端点信息。常见的 Source 类型包括:
- Ingress: 从 Ingress 资源的
spec.rules.host字段提取域名,从status.loadBalancer.ingress提取目标 IP 或 Hostname。 - Service: 从类型为
LoadBalancer或NodePort的 Service 中提取 DNS 名称(通过 annotationexternal-dns.alpha.kubernetes.io/hostname指定)和负载均衡器 IP。 - Gateway API: 支持 Kubernetes Gateway API 资源(如 HTTPRoute),适用于更复杂的流量管理场景。
- CRD Source: 允许用户自定义资源作为 DNS 记录的来源,适用于特殊业务需求。
# 示例:通过 Service annotation 指定 DNS 名称
apiVersion: v1
kind: Service
metadata:
name: my-app
annotations:
external-dns.alpha.kubernetes.io/hostname: "app.example.com."
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
4.4 Owner:防止 DNS 记录冲突的标识机制
Owner 是 ExternalDNS 实现“谁创建、谁管理、谁删除”的核心机制。它通过在 DNS 记录中写入一个唯一的标识(通常使用 TXT 记录),来标记该记录由哪个 ExternalDNS 实例管理。
Owner 的工作原理:
- 当 ExternalDNS 创建一条 DNS 记录(如
app.example.com)时,它会同时创建一条同名的 TXT 记录(如app.example.com),其值包含 Owner ID。 - 在后续的调和循环中,ExternalDNS 会检查 TXT 记录中的 Owner ID 是否与自身配置的
--owner-id匹配。 - 如果匹配,则允许修改或删除该记录;如果不匹配,则跳过该记录,避免误操作。
多集群关键配置: 每个集群的 ExternalDNS 必须设置唯一的
--owner-id。例如:--owner-id=cluster-1-prod。否则,一个集群可能会删除另一个集群创建的 DNS 记录,导致服务中断。
4.5 TTL:DNS 记录的缓存时间控制
TTL(Time To Live)决定了 DNS 记录在客户端和递归解析器中的缓存时长。合理的 TTL 设置可以在“更新及时性”和“查询性能”之间取得平衡。
| TTL 值 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 30-60 秒 | 金丝雀发布、频繁切换的测试环境 | 变更即时生效 | DNS 查询压力大,客户端缓存失效快 |
| 300 秒 (5 分钟) | 生产环境默认值,常规发布 | 平衡更新速度与缓存效率 | 变更后需等待 5 分钟完全生效 |
| 600-3600 秒 | 稳定的生产服务,IP 极少变动 | 减少 DNS 查询次数,降低 Provider 费用 | 变更后生效延迟较长 |
ExternalDNS 中的 TTL 配置方式:
- 全局默认 TTL: 通过启动参数
--default-ttl设置,例如--default-ttl=300。 - 按资源覆盖: 通过 annotation
external-dns.alpha.kubernetes.io/ttl为特定 Ingress 或 Service 设置独立的 TTL。
# 示例:为特定 Ingress 设置 TTL 为 60 秒
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
external-dns.alpha.kubernetes.io/ttl: "60"
spec:
rules:
- host: canary.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: canary-service
port:
number: 80
多集群 TTL 策略: 在跨集群的全局负载均衡场景中,建议将 TTL 设置为 60-120 秒,以便在集群故障切换时,客户端能快速感知 DNS 记录的变更,缩短故障恢复时间。
4.6 四大核心机制的关系总结
下表总结了 DNS Provider、Source、Owner 和 TTL 在 ExternalDNS 中的角色与相互关系:
| 机制 | 核心职责 | 关键配置参数 | 多集群影响 |
|---|---|---|---|
| DNS Provider | 与外部 DNS 服务通信,执行记录操作 | --provider, --domain-filter |
每个集群可独立配置 Provider 实例 |
| Source | 定义从哪些 K8s 资源提取 DNS 端点 | --source, annotations |
各集群可监听不同的资源类型 |
| Owner | 通过 TXT 记录标识记录归属,防止冲突 | --owner-id |
必须唯一,否则导致记录被误删 |
| TTL | 控制 DNS 记录在客户端的缓存时间 | --default-ttl, annotations |
低 TTL 加速故障切换,高 TTL 减少 Provider 调用 |
核心要点: 在多集群发布流水线中,Owner 机制是保障安全性的基石,TTL 是控制发布速度的旋钮,DNS Provider 和 Source 决定了“从哪里来,到哪里去”。理解这四者的协同工作方式,是配置生产级 ExternalDNS 的前提。