云原生【免费下载链接】external-dnsConfigure external DNS servers dynamically from Kubernetes resources项目地址https://gitcode.com/gh_mirrors/ex/external-dns点击查看免费下载本文讲解如何在 ExternalDNS 中启用节点Node作为记录源将集群内每个节点的 IP 地址自动同步为 DNS 记录A / AAAA并详细说明其记录生成规则、不可调度节点排除策略、IPv6 处理行为以及完整的 RBAC 部署清单。读完本文你将掌握--sourcenode的完整配置方式并能结合源码理解其底层实现直接在生产集群中落地部署。为什么需要以 Node 作为 DNS 源在需要为集群中每台节点机器维护按主机名的 DNS 记录例如构建机、堡垒机、节点级监控端点、物理/虚拟服务器直连访问时传统 Service 或 Ingress 源无法覆盖这类场景。ExternalDNS 的 node source 正是为此设计它读取 KubernetesNode对象的状态把每个节点的地址转换成endpoint.Endpoint再交由选定的 Provider如 AWS Route53同步到对应的 DNS 托管区。使用方式只需在启动参数中加入--sourcenode即可。在 source/node.go 的源码注释中该源被定义为// externaldns:source:namenode // externaldns:source:categoryKubernetes Core // externaldns:source:descriptionCreates DNS entries based on Kubernetes Node resources // externaldns:source:resourcesNode // externaldns:source:filtersannotation,label // externaldns:source:fqdn-templatetrue // externaldns:source:provider-specificfalse即它属于 Kubernetes Core 类别只监听Node一种资源支持注解与标签过滤支持 FQDN 模板且不携带任何 Provider 专有注解能力。记录生成规则与 TTL 控制根据 docs/sources/nodes.md 与 source/node.go 的实现node source 生成的记录遵循以下规则每个节点生成一条A 记录目标为节点的externalIP如果节点没有externalIP则回退使用任意一个 IPv4internalIP。每个节点的 IPv6internalIP会额外生成一条AAAA 记录具体行为见下文IPv6 行为一节。记录的TTL可通过节点注解external-dns.kubernetes.io/ttl设置未设置或取值非法时TTL 视为未配置RecordTTL.IsConfigured为 false交由 Provider 使用默认值。TTL 注解的解析实现在 source/annotations/processors.go 的TTLFromAnnotations它支持纯整数秒如600与 Go duration 格式如10m且数值必须在[ttlMinimum, ttlMaximum]范围内否则告警并回退为未配置。单元测试 source/node_test.go 覆盖了未注解 / 非法值 / 合法值三种情况合法值10会正确写入RecordTTL: 10。除 TTL 外节点上还可以使用external-dns.kubernetes.io/target注解手动覆盖记录目标地址——见 source/annotations/annotations.go 中定义的TtlKey、TargetKey、HostnameKey、ControllerKey等注解常量。nodeSource.endpointsForDNSNamessource/node.go会先读取 target 注解只有注解不存在时才回落到nodeAddresses自动解析节点地址测试用例node with target annotationsource/node_test.go验证了注解值203.2.45.7会替代节点真实地址写入记录。不可调度节点的默认排除行为默认情况下被标记为 Unschedulable 的节点会被排除依据 core/v1/NodeSpec 中的Unschedulable字段。因此NotReady、Unhealthy、SchedulingDisabled即被 cordon 的节点不会创建任何 DNS 记录对于之前已经存在、但现在处于上述状态的节点其既有记录也会被移除因为源不再产出对应 endpoint配合--policysync时会被清理。该逻辑直接体现在 source/node.gofor _, node : range nodes { if node.Spec.Unschedulable ns.excludeUnschedulable { log.Debugf(Skipping node %s because it is unschedulable, node.Name) continue } ... }对应的excludeUnschedulable配置项来自--exclude-unschedulable标志默认值为 true定义于 pkg/apis/externaldns/types.go。如果你希望无论节点状态如何都持续暴露其 DNS 记录例如由 ExternalDNS 统一管理每台主机的 DNS 记录可以指定--no-exclude-unschedulable来关闭该默认行为。测试用例unschedulable node return nothing with excludeUnschedulabletrue与unschedulable node returns node with excludeUnschedulablefalsesource/node_test.go分别验证了开启与关闭时的行为并断言了Skipping node ... because it is unschedulable日志的出现与否。IPv6 行为与--expose-internal-ipv6node source 默认暴露节点的 IPv6ExternalIP如果仍需要显式暴露内部 IPv6 地址可追加--expose-internal-ipv6标志。该标志的注册见 pkg/apis/externaldns/types.go帮助信息为When using the node source, expose internal IPv6 addresses (optional, default: false)即当前仓库中该标志默认关闭。其底层决策逻辑在 source/node.go 的nodeAddresses函数中这里对 IPv6 内部地址做了特殊处理相关上下文可参考 docs/proposal/002-internal-ipv6-handling-rollback.md该提案解释了为何内部 IPv6 地址需要独立控制for _, addr : range node.Status.Addresses { // IPv6 InternalIP addresses have special handling. if addr.Type v1.NodeInternalIP endpoint.SuitableType(addr.Address) endpoint.RecordTypeAAAA { internalIpv6Addresses append(internalIpv6Addresses, addr.Address) } addresses[addr.Type] append(addresses[addr.Type], addr.Address) } if len(addresses[v1.NodeExternalIP]) 0 { if ns.exposeInternalIPv6 { return append(addresses[v1.NodeExternalIP], internalIpv6Addresses...), nil } return addresses[v1.NodeExternalIP], nil } if len(addresses[v1.NodeInternalIP]) 0 { return addresses[v1.NodeInternalIP], nil }从源码结构可以归纳出完整的行为矩阵节点地址情况--expose-internal-ipv6关闭默认--expose-internal-ipv6开启仅有内部 IPv4生成 A 记录内部 IPv4生成 A 记录内部 IPv4仅有内部 IPv4 内部 IPv6A AAAA内部 IPv6 仍生成A AAAA内部 IPv6 生成有外部 IPIPv4仅外部 IPv4 生成 A外部 IPv4 生成 A内部 IPv6 额外生成 AAAA有外部 IPv6外部 IPv6 生成 AAAA外部 IPv6 生成 AAAA内部 IPv6 一并生成 AAAA上述行为均由 source/node_test.go 中testNodeEndpointsWithIPv6系列用例逐一验证例如node with both external and internal IPv6与node with both external, internal, and IPv6 IP returns endpoints with external IPs等。最小化示例配置Container Spec下面是一份可直接套用的 Deployment 容器参数片段来自 docs/sources/nodes.mdspec: serviceAccountName: external-dns containers: - name: external-dns image: registry.k8s.io/external-dns/external-dns:v0.23.0 # update this to the desired external-dns version args: - --sourcenode # will use nodes as source - --provideraws - --zone-name-filterexternal-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --domain-filterexternal-dns-test.my-org.com - --aws-zone-typepublic - --registrytxt - --fqdn-template{{.Name}}.external-dns-test.my-org.com - --txt-owner-idmy-identifier - --policysync - --log-leveldebug各参数的作用说明如下--sourcenode启用节点源为核心开关可与其他 source 同时使用如--sourceservice--provideraws指定 DNS Provider示例使用 AWS可替换为任意支持的 Provider--zone-name-filter/--domain-filter将处理范围限定到匹配的托管区与域名省略则处理全部可用托管区--aws-zone-typepublic仅操作 Public 类型托管区AWS 专用参数--registrytxt使用 TXT registry 记录所有权避免与其他控制器冲突--fqdn-template{{.Name}}.external-dns-test.my-org.com将节点名.Name套入模板生成完整域名模板引擎实现在 source/template/engine.go--txt-owner-idmy-identifierTXT 记录的所有者标识--policysync全量同步策略将自动创建、更新并删除记录upsert-only只增不改--log-leveldebug调试日志便于排查节点跳过原因如 unschedulable 日志。FQDN 模板的行为同样有测试覆盖node with fqdn template returns endpoint with expanded hostnamesource/node_test.go验证了节点node1配合模板{{.Name}}.example.org会生成node1.example.org的 A 记录。无 RBAC 集群的部署清单如果集群未启用 RBAC或在已授权的命名空间直接运行可使用如下精简 Deployment。该清单与文档保持一致仅部署控制器本体--- apiVersion: apps/v1 kind: Deployment metadata: name: external-dns spec: strategy: type: Recreate selector: matchLabels: app: external-dns template: metadata: labels: app: external-dns spec: serviceAccountName: external-dns containers: - name: external-dns image: registry.k8s.io/external-dns/external-dns:v0.23.0 args: - --sourcenode # will use nodes as source - --provideraws - --zone-name-filterexternal-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --domain-filterexternal-dns-test.my-org.com - --aws-zone-typepublic - --registrytxt - --fqdn-template{{.Name}}.external-dns-test.my-org.com - --txt-owner-idmy-identifier - --policysync - --log-leveldebug其中strategy: Recreate表示滚动更新时先删除旧 Pod 再创建新 Pod适合需要独占访问 Provider 资源的控制器场景。启用 RBAC 的完整部署清单在启用 RBAC 的集群中node source 需要读取集群级别的Node对象因此必须授予相应权限。完整的 ServiceAccount、ClusterRole、ClusterRoleBinding 与 Deployment 清单如下与 docs/sources/nodes.md 一致apiVersion: v1 kind: ServiceAccount metadata: name: external-dns --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: external-dns rules: - apiGroups: [route.openshift.io] resources: [routes] verbs: [get, watch, list] - apiGroups: [] resources: [services,pods] verbs: [get,watch,list] - apiGroups: [discovery.k8s.io] resources: [endpointslices] verbs: [get,watch,list] - apiGroups: [extensions,networking.k8s.io] resources: [ingresses] verbs: [get,watch,list] - apiGroups: [] resources: [nodes] verbs: [get, watch, list] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: external-dns-viewer roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: external-dns subjects: - kind: ServiceAccount name: external-dns namespace: external-dns --- apiVersion: apps/v1 kind: Deployment metadata: name: external-dns spec: strategy: type: Recreate selector: matchLabels: app: external-dns template: metadata: labels: app: external-dns spec: serviceAccountName: external-dns containers: - name: external-dns image: registry.k8s.io/external-dns/external-dns:v0.23.0 args: - --sourcenode # will use nodes as source - --provideraws - --zone-name-filterexternal-dns-test.my-org.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --domain-filterexternal-dns-test.my-org.com - --aws-zone-typepublic - --registrytxt - --fqdn-template{{.Name}}.external-dns-test.my-org.com - --txt-owner-idmy-identifier - --policysync - --log-leveldebug其中与 node source 直接相关的授权条目为- apiGroups: [] resources: [nodes] verbs: [get, watch, list]缺少该条目时ExternalDNS 将无法通过 Node informer 获取节点列表。注意尽管清单同时授权了 services、pods、ingresses 等资源便于未来扩展其他 source但仅运行--sourcenode时node source 实际只会消费nodes资源的 watch/list 事件。底层实现原理Informer、过滤与索引从源码层面看NewNodeSourcesource/node.go采用 Kubernetes SharedInformer 监听节点变化以resync 周期为 0的方式创建 informer factory意味着只有在节点真实发生增、删、改时才会触发处理避免无意义的重算通过informers.IndexSelectorWithAnnotationFilter、IndexSelectorWithLabelSelector、IndexSelectorWithConditions(annotations.IsControllerMatch)注册索引器分别实现注解过滤配合--annotation-filter按 label selector 语义筛选节点标签过滤配合--label-filter按标签选择器筛选节点控制器归属判断若节点带external-dns.kubernetes.io/controller注解且值不是dns-controller则该节点被忽略见 source/annotations/processors.go 的IsControllerMismatch通过 Transformer 剥离managedFields、last-applied-config注解与status.conditions等与生成 endpoint 无关的字段仅保留地址等必需信息source/node_test.go 中的TestTransformerInNodeSource验证了这一点同时断言Status.Addresses被保留因为它正是记录生成的数据来源。Endpoints()方法source/node.go在每轮同步时从 informer 索引器列出节点逐一跳过不可调度节点、应用 FQDN 模板、读取 TTL 与 target 注解最终通过endpoint.MergeEndpoints合并去重并为每个 endpoint 打上资源标签node/name测试TestResourceLabelIsSetForEachNodeEndpoint与TestProcessEndpoint_Node_RefObjectExist均验证了该标签与引用对象的存在source/node_test.go。此外source/node_test.go 的TestNodeIndexer系列用例系统验证了注解过滤、标签过滤、controller 不匹配排除以及非法过滤器被静默忽略等行为可作为排查节点未生成记录问题时的对照清单。常见问题排查清单节点没有生成任何记录先用--log-leveldebug观察日志中是否有Skipping node ... because it is unschedulable若节点被 cordon 且未指定--no-exclude-unschedulable这是预期行为节点既无 externalIP 也无 internalIPnodeAddresses会返回错误could not find node address for name相应节点被跳过测试node with neither external nor internal IP returns no endpoints覆盖节点名超过 63 字符不会崩溃而是被安全跳过测试node name with a label over 63 characters is skipped instead of panicking覆盖记录了非预期地址检查节点上是否存在external-dns.kubernetes.io/target注解其优先级高于节点自动解析的地址对于 IPv6确认--expose-internal-ipv6是否符合预期默认关闭节点被其他控制器管理确认节点注解external-dns.kubernetes.io/controller的值为dns-controller或未设置否则该节点会被忽略。小结以 Node 作为 source 是 ExternalDNS 面向主机级 DNS 管理的轻量方案无需额外 CRD仅凭节点状态即可维护 A/AAAA 记录并通过--exclude-unschedulable默认开启与--expose-internal-ipv6默认关闭两个开关精确控制记录暴露范围。配合 FQDN 模板、TTL 注解、target 覆盖注解以及 annotation/label 过滤器可以灵活适配各类按节点管理 DNS 的运维场景。部署时务必为 ClusterRole 授予nodes的 get/watch/list 权限并按需决定是否关闭不可调度节点的默认排除行为。如需进一步了解其他数据源Service、Ingress、Gateway 等的配置可参考 docs/sources/index.md 与 docs/sources/about.md完整的启动参数说明见 docs/flags.md。赞分享云原生【免费下载链接】external-dnsConfigure external DNS servers dynamically from Kubernetes resources项目地址https://gitcode.com/gh_mirrors/ex/external-dns点击查看免费下载相关推荐ExternalDNS OpenShift Route Source 实战指南将 OpenShift Route 自动同步为 DNS 记录ExternalDNS OpenShift Route Source 实战指南将 OpenShift Route 自动同步为 DNS 记录 OpenShift云原生终极界面字体解决方案Source Sans 3 专业使用指南终极界面字体解决方案Source Sans 3 专业使用指南 还在为现代用户界面字体选择而烦恼吗面对琳琅满目的字体库你是否曾因字体渲染不清晰、字重选择有限云原生ExternalDNS 与 Myra Security Webhook 集成实战在 Kubernetes 中自动管理 MyraSec DNS 记录ExternalDNS 与 Myra Security Webhook 集成实战在 Kubernetes 中自动管理 MyraSec DNS 记录 本指南面向云原生上一篇AGENTS.md - [你的项目名称]下一篇BloodHound终极指南如何快速发现Active Directory攻击路径的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Cobalt Strike 4.5部署配置与红队实战避坑指南 简介:Cobalt Strike 4.5是面向渗透测试、红队评估与安全研究的C2框架,支持HTTP/HTTPS/DNS/SMB等多种协议上线主机,内置提权、凭据导出、端口转发、Socket代理、Office攻击、文件捆绑、钓鱼等功能,并可调用Mimikatz等外部工具完成内… · 2026/9/25 4:23:35
宇树G1机器人SSH远程连接与网络调试实战指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:23:29
邮件安全Agent隔离部署的得与失:从断网沙箱到白名单出口架构 前阵子有个做企业安全运维的朋友问我:把邮件安全Agent部署到一台禁止外网访问的沙箱里,是不是直接断了后路?就算Agent被攻破,也无法对外弹shell、发数据,这样是不是就等于安全性拉满了?这个问题问得很典型。… · 2026/9/25 4:23:29
Claude Code嵌入式开发实战:权限控制、寄存器配置与Skills技能管理 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:57:22
mage-ai 数据集成实战:Amazon Redshift 数据源(Source)完整配置指南与源码原理解析 数据工程数据编排ETL任务调度批处理流处理数据集成后端 【免费下载链接】mage-ai 🧙 Build, run, and manage data pipelines for integrating and transforming data. 项目地址: https://gitcode.com/gh_mirrors/ma/mage-ai 点击查看 免费下载 Amazon … · 2026/9/25 4:57:16
瓦斯抽采模拟:从渗流机理到工程应用的数值建模全解 1. 从“岩石会呼吸”说起:瓦斯抽采模拟到底在解决什么问题做地下工程的数值模拟这些年,接触过不少课题,但要说哪个最让我觉得有意思,瓦斯抽采模拟绝对排得上号。我第一次听到“岩石会呼吸”这个说法是在一次煤矿井下考察时&#x… · 2026/9/25 4:57:16
从超级个体到超级团队:企业级Agent平台与MCP协议落地实践 1. 从「超级个体」到「超级团队」:企业级 Agent 平台到底在解决什么问题过去一年,我接触过不少团队在内部推 AI 编码助手。一个很典型的现象是:个人开发者用 CodeBuddy 这类工具,效率提升非常明显,一个人能顶过去两三个… · 2026/9/25 4:57:16
I2C通信故障排查全流程:从万用表到示波器与ACK解码 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:56:57
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37