<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>external-dns on </title>
    <link>/tags/external-dns/</link>
    <description>Recent content in external-dns on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Tue, 08 Sep 2026 23:11:52 +0800</lastBuildDate><atom:link href="/tags/external-dns/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>用 external-dns 自动创建 DNS 记录：source、target、所有权登记，以及两个偏危险的默认值</title>
      <link>/posts/external-dns-sources-target-owner/</link>
      <pubDate>Tue, 08 Sep 2026 23:11:52 +0800</pubDate>
      
      <guid>/posts/external-dns-sources-target-owner/</guid>
      <description>一个服务要能被公网访问，DNS 那条记录总得有人建。手工建的麻烦不在于费事，在于它和集群状态会分家：hostname 已经写在 Ingress 或 HTTPRoute 里了，去 DNS 那边再抄一遍，就多出一份必须同步维护的副本。
漏掉一边的表现还挺讨厌。只建了 DNS 记录，流量能进来但集群不知道往哪路由；只加了路由，集群能路由但公网查不到这个名字。两种都是「半通」，而且不会有任何告警告诉你漏了。我在自己的 homelab 上按这个流程加过十几个子域名，每次都得翻以前的 commit 照抄。
external-dns 收掉的就是这份副本。它是个 controller，watch 你指定的那类资源，把上面的 hostname 当作 DNS 的期望状态，周期性地和 DNS provider 对齐。
版本会影响下面每一条注解怎么写。我写这篇时（2026-09-08），官方 Helm 仓库里最新的 chart 是 1.21.1（2026-04-30 发布，appVersion: 0.21.0），而二进制最新是 v0.22.0（2026-08-20 发布）。v0.22.0 把默认注解前缀从 external-dns.alpha.kubernetes.io/ 换成 external-dns.kubernetes.io/（去掉 alpha）且不再回退，发布说明原话是「This change can delete all your DNS records」。下面统一按 chart 装出来的 v0.21.0 写，也就是带 alpha 的那个前缀。
手工建的那条记录，是集群状态的副本 值得先想清楚这活为什么该交出去，因为答案决定了交给谁。
我原来那两步里，DNS 那一半不产生任何新信息：HTTPRoute 的 spec.hostnames 已经写了 llm.meirong.dev，Terraform 变量里再写一遍 llm，只是把同一个事实抄到第二个地方。凡是能从现有状态推导出来的东西，让人来抄就迟早会漂移。
那为什么不是「把 gateway.yaml 也塞进 Terraform」，让一个工具管两头？因为 Terraform 不感知集群运行态，它不会去 watch HTTPRoute。无论怎么合并，加一个子域名仍然是人去改 Terraform 的输入。方向得反过来：让集群成为真相源，DNS 跟着集群走。这才是 controller 这个形态解决的问题：它在集群里，能 watch，能在资源变化后自己去对齐。</description>
    </item>
    
    <item>
      <title>用 external-dns 接管 homelab 的子域名 DNS</title>
      <link>/posts/external-dns-httproute-cloudflare-homelab/</link>
      <pubDate>Sat, 22 Aug 2026 17:09:00 +0800</pubDate>
      
      <guid>/posts/external-dns-httproute-cloudflare-homelab/</guid>
      <description>背景 这套 homelab 有两个 K3s 集群，对外服务都挂在 meirong.dev 的子域名下，从 Cloudflare Tunnel 进来。2026 年 7 月之前，加一个新子域名固定是两步手改：
改 cloudflare/terraform/terraform.tfvars 里的 ingress_rules，terraform apply 建一条指向 tunnel 的 CNAME； 改集群里的 gateway.yaml，加一条 HTTPRoute 把 hostname 指到 Service。 两处分属不同工具、不同目录，必须同步改。漏一处就是半通：只改 tfvars，流量能转发进来但集群不知道往哪路由；只改 gateway，集群能路由但公网查不到这个名字。当时也没有任何告警会告诉我漏了，我每次都得翻以前的 commit 照抄。
DNS 那一半本来就是冗余的：HTTPRoute 里已经写了 hostname，再去 tfvars 抄一遍不产生任何新信息。既然能从集群状态推出来，就不该让人抄。external-dns 就是干这个的。
external-dns 在做什么 它是一个 controller，把集群里某些资源当作 DNS 的期望状态，按固定周期算出差异，写进 DNS provider。配置上绕不开 source、provider、registry 这三项。
source 是从哪读期望状态，可以是 Service、Ingress，也可以是 Gateway API 的那几种 route（gateway-httproute、gateway-grpcroute、gateway-tlsroute 等）。provider 是往哪写，Cloudflare、Route 53、Google Cloud DNS 之类。
registry 容易被当成可选项跳过。它管的是「这条记录是我建的」这个登记：默认值 txt 会给每条它管的记录额外写一条 TXT，内容形如 heritage=external-dns,external-dns/owner=&amp;lt;owner-id&amp;gt;,external-dns/resource=&amp;lt;source&amp;gt;。没有这层登记，它分不清 zone 里哪些记录归自己管，后面共存和迁移都谈不上。</description>
    </item>
    
  </channel>
</rss>
