☰
ExternalDNS Pod Source:基于 Kubernetes Pod 资源自动注册 DNS 记录与 PTR 反解配置指南
2026/9/25 2:43:52 网站建设 项目流程
  • 云原生

【免费下载链接】external-dns

Configure external DNS servers dynamically from Kubernetes resources

项目地址:https://gitcode.com/gh_mirrors/ex/external-dns
点击查看免费下载

本篇指南聚焦 external-dns 的pod数据源(Source),讲解它如何将 KubernetesPod资源转换为 DNS 记录,涵盖--pod-source-domain默认域名机制、--ignore-non-host-network-pods过滤行为、基于注解(annotation)的 FQDN 解析,以及面向无 SNAT 本地集群的“全量 Pod + PTR 反解”实战配置组合。读完本文,你将掌握 pod source 的全部核心命令行参数、底层端点生成逻辑与可复用的部署方案。

什么是 Pod Source

Pod source 是 external-dns 内置的数据源之一,其职责是根据 KubernetesPod资源生成 DNS 记录。启用方式很简单,在 external-dns 启动参数中通过--source=pod指定:

./external-dns --source=pod --provider=...

从源码结构看,pod source 的实现位于 source/pod.go,其中podSource结构体同时维护了 Pod 与 Node 两个 informer(source/pod.go)。Pod informer 负责读取 Pod 列表及其注解,Node informer 则在需要把记录解析到节点地址时使用。该 source 标注的能力维度(source/pod.go)包括:

  • 资源类型:Pod
  • 过滤方式:annotation、label
  • 命名空间:支持 all(全部)与 single(单个)
  • 支持 FQDN 模板(fqdn-template)、事件驱动(events)
  • 不涉及 provider 特有逻辑(provider-specific=false)

也就是说,pod source 是纯粹的 Kubernetes 核心资源驱动型数据源,不依赖任何特定 DNS 厂商。

默认行为:仅考虑使用 host networking 的 Pod

Pod source 的默认行为有一个重要前提:只处理启用了 host networking(hostNetwork: true)的 Pod。这是因为 Pod 自身的 IP 在集群内部网络中往往不可被外部 DNS 直接引用,而 host networking 模式下 Pod 共享节点网络栈,其地址才具有集群外的可达性。

你可以通过--ignore-non-host-network-pods选项覆盖这一默认行为——加上该选项后,非 host networking 的 Pod 将被忽略。该参数在 pkg/apis/externaldns/types.go 中注册,默认值为false,完整定义见 docs/flags.md:

--[no-]ignore-non-host-network-pods Ignore pods not running on host network when using pod source (default: false)

在实现层面,这个开关的判定逻辑位于addPodEndpointsToEndpointMap函数(source/pod.go):

if ps.ignoreNonHostNetworkPods && !pod.Spec.HostNetwork { log.Debugf("skipping pod %s. hostNetwork=false", pod.Name) return }

即只有当ignoreNonHostNetworkPods=true且pod.Spec.HostNetwork=false时才跳过该 Pod,并输出skipping pod ... hostNetwork=false的调试日志。source/pod_test.go 中的测试用例(如"mixed valid and hostNetwork=false pods"、"when ignoreNonHostNetworkPods=false, no skip logs should be generated")验证了两种开关状态下的行为差异。

三种行为模式对比

配置hostNetwork=true 的 PodhostNetwork=false 的 Pod
默认(不加任何选项)被处理被处理
--ignore-non-host-network-pods被处理被忽略(产生 skip 日志)

为 Pod 指定 FQDN 的三种途径

Pod source 生成 DNS 记录时,目标域名(FQDN)可以来自三个互不冲突的来源,最终端点会通过endpoint.MergeEndpoints合并去重(source/pod.go):

  1. 注解(annotation):默认情况下,pod source 从 Pod 注解中查找关联的 FQDN,相关注解键定义于 source/annotations/annotations.go:

    • external-dns.alpha.kubernetes.io/hostname:为该 Pod 注册指定主机名。若未设置target注解,记录将解析到该 Pod 所在节点的地址(见下文“节点地址解析”);若设置了target注解,则解析到 target 指定的地址。
    • external-dns.alpha.kubernetes.io/internal-hostname:注册内部主机名,默认解析到 Pod 自身的 IP(pod.Status.PodIP)。
    • external-dns.alpha.kubernetes.io/target:显式指定记录的目标地址(可多个,逗号分隔)。
    • external-dns.alpha.kubernetes.io/ttl:指定记录 TTL。 注解整体说明可参考 docs/annotations/annotations.md。
  2. --pod-source-domain默认域名:为所有 Pod 统一生成 FQDN(见下一节)。

  3. FQDN 模板(fqdn-template):通过模板引擎批量生成,对应podSource.templateEngine(source/pod.go),支持{{.Name}}等占位符。

节点地址解析规则

当使用hostname注解且未指定target时,记录解析到节点地址。addPodNodeEndpointsToEndpointMap(source/pod.go)通过 Node informer 读取pod.Spec.NodeName对应节点,遍历node.Status.Addresses,遵循如下规则:

  • NodeExternalIP类型的地址直接采用;
  • NodeInternalIP类型的地址仅在记录类型为 AAAA(IPv6)时采用——源码注释解释了原因:IPv6 地址虽被标记为 NodeInternalIP,但同样可被外部使用(source/pod.go)。

记录类型由endpoint.SuitableType(address)根据地址是 IPv4(A)还是 IPv6(AAAA)自动判定。

使用默认域名:--pod-source-domain

默认情况下 pod source 依赖 Pod 注解来发现 FQDN,这对于大规模、无需逐个打注解的场景并不友好。此时可以使用--pod-source-domain选项,为所有 Pod 自动构建 FQDN。

例如启动参数:

./external-dns --source=pod --pod-source-domain=example.org

名为test-pod的 Pod 会被注册为test-pod.example.org。该选项注册于 pkg/apis/externaldns/types.go,默认值为空字符串,完整定义见 docs/flags.md:

--pod-source-domain="" Domain to use for pods records (optional)

其底层实现位于addPodSourceDomainEndpoints(source/pod.go),核心逻辑即为字符串拼接:

domain := pod.Name + "." + ps.podSourceDomain

在未设置target注解时,<podName>.<podSourceDomain>解析到 Pod 自身的 IP(pod.Status.PodIP),记录类型根据 IP 版本自动判定;若 Pod 带有target注解,则优先解析到注解指定的目标地址。

值得注意的一个细节:--pod-source-domain与注解机制可以同时生效。addPodEndpointsToEndpointMap中依次处理 internal-hostname、hostname、kops 兼容注解与 pod-source-domain 四类端点(source/pod.go),最终所有记录都会被合并输出,因此同一个 Pod 可以同时拥有注解定义的 FQDN 与默认域名生成的 FQDN。

实战场景:全量注册 Pod 及其 PTR 记录

文档 docs/sources/pod.md 给出了一个将这些选项组合使用的典型场景:

当你在本地(on-premise)Kubernetes 集群中运行,且 Pod 网络未启用 SNAT时,外部流量到达集群后无法通过 Pod IP 快速回溯到对应工作负载。此时可以把所有 Pod 连同其 PTR 记录一起注册到 DNS,使集群外的流量来源可以通过nslookup或dig命令对 Pod IP 做反向解析,迅速定位到对应的工作负载。这在运行大量 Kubernetes 集群时尤其有用。

反向解析(PTR)的原理:Pod IP 形如10.0.0.5,其 PTR 记录位于5.0.0.10.in-addr.arpa。因此要让全部 Pod 支持反解,需要同时把正向域名与反向 in-addr.arpa 域名都纳入 DNS 管辖。完整配置组合如下:

./external-dns \ --domain-filter=example.org \ --domain-filter=10.0.0.in-addr.arpa \ --source=pod \ --pod-source-domain=example.org \ --create-ptr \ --rfc2136-zone=example.org \ --rfc2136-zone=10.0.0.in-addr.arpa

各参数职责拆解

参数作用
--domain-filter=example.org只管理example.org域下的记录,过滤掉无关域名
--domain-filter=10.0.0.in-addr.arpa同时管理10.0.0.0/24网段对应的反向查询域
--source=pod启用 pod source
--pod-source-domain=example.org为每个 Pod 生成<podName>.example.org正向记录
--create-ptr为每条记录同时创建对应的 PTR 反向记录
--rfc2136-zone=example.org指定正向记录写入的 RFC2136(BIND 等)DNS 区域
--rfc2136-zone=10.0.0.in-addr.arpa指定反向 PTR 记录写入的反向区域

其中--create-ptr与--rfc2136-zone属于 rfc2136 provider 的能力:--create-ptr让 external-dns 在生成 A/AAAA 记录的同时派生 PTR 记录,而重复声明两个--rfc2136-zone则保证正向与反向记录被正确路由到对应的 zone 文件。有关 rfc2136 provider 的部署细节可参考 docs/tutorials/rfc2136.md 与 docs/advanced/ptr-records.md。

运行效果示意

假设集群中有名为web-0、Pod IP 为10.0.0.5的 Pod,上述配置生效后 DNS 中会同时出现:

  • 正向记录:web-0.example.org. A 10.0.0.5
  • 反向记录:5.0.0.10.in-addr.arpa. PTR web-0.example.org.

此时在集群外执行:

nslookup 10.0.0.5 dig -x 10.0.0.5

即可将来源 IP 反解为具体的工作负载名,快速完成流量溯源。

从源码看端点的生成链路

理解 pod source 的完整工作流有助于排障与二次开发,其核心链路如下(source/pod.go):

  1. 启动阶段:NewPodSource创建共享 informer factory,注册 Pod 与 Node informer,并为 Pod informer 挂载注解过滤器(IndexSelectorWithAnnotationFilter)、标签选择器(IndexSelectorWithLabelSelector)与控制器匹配条件(IndexSelectorWithConditions),同时注册事件处理器,等待本地缓存同步完成后返回podSource(source/pod.go)。

  2. 端点收集阶段:Endpoints从 informer indexer 中列出全部 Pod,对每个 Pod 依次执行:

    • endpointsFromPodAnnotations:解析 Pod 注解(internal-hostname / hostname / kops 兼容注解 / pod-source-domain)生成端点(source/pod.go);
    • templateEngine.ApplyFQDNTargetTemplate:应用 FQDN/目标模板;
    • templateEngine.CombineWithEndpoints:合并模板生成的端点;
    • endpoint.AttachRefObject:为端点附加对象引用,供事件系统使用(source/pod.go)。
  3. 合并去重:endpoint.MergeEndpoints汇总所有 Pod 的端点,交由后续 plan/registry/provider 阶段处理。

在生成端点时,TTL 统一通过annotations.TTLFromAnnotations(pod.Annotations, fmt.Sprintf("pod/%s", pod.Name))从注解读取(source/pod.go),未设置时采用 provider 的默认 TTL。

此外,pod source 还保留了对kops-dns-controller兼容模式的支持:当--compatibility=kops-dns-controller时,会额外读取 kops 风格的 hostname 注解并生成对应记录(source/pod.go)。

小结与验证建议

Pod source 是 external-dns 中唯一直接以工作负载资源(而非负载均衡/路由资源)为驱动的核心数据源,适用于需要为每个 Pod 建立可解析身份的场景。使用时把握三条主线即可:

  1. 过滤:用--ignore-non-host-network-pods控制是否只关注 host networking Pod;
  2. 命名:注解(external-dns.alpha.kubernetes.io/hostname/internal-hostname)逐 Pod 定制,--pod-source-domain全局兜底;
  3. 组合:结合--create-ptr与反向 zone 实现 Pod IP 的反向溯源。

如需验证行为,可直接运行仓库中的单元测试,例如 source/pod_test.go 的TestPodSource覆盖了注解解析、节点地址解析、ignoreNonHostNetworkPods跳过逻辑与 skip 日志输出;pkg/apis/externaldns/types_test.go 则验证了--ignore-non-host-network-pods与--pod-source-domain=example.org等命令行参数的解析。建议在测试环境先用 inmemory provider(--provider=inmemory)验证生成的记录集合,再切换到真实 DNS provider。

  • 云原生

【免费下载链接】external-dns

Configure external DNS servers dynamically from Kubernetes resources

项目地址:https://gitcode.com/gh_mirrors/ex/external-dns
点击查看免费下载

相关推荐

上一篇:Qwen3-1.7B-FP8数据预处理:训练数据格式要求详解
下一篇:Qwen2.5-7B-Instruct-GPTQ-Int4数学推理能力测试:量化模型在数学任务上的表现

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询