external-dns
external-dns watches Kubernetes resources and writes the DNS records their hostnames need into a DNS provider. The GCP Web App Blueprint runs two releases per stage cluster, one for the stage's public zone and one for the internal zone, so no record of the application is written by hand.
What it does
external-dns reads hostnames from sources such as Services, Ingresses and Gateway API HTTPRoutes, and creates matching records pointing at the addresses those resources receive. A domain filter limits it to one zone's names. A TXT registry records which records each instance owns, under an owner ID, so it never touches records it did not create. With the sync policy it also deletes records whose source is gone; upsert-only never deletes.
How BuiltForProd uses it
| Release | Unit | Zone | Writes |
|---|---|---|---|
external-dns | external-dns | The stage's public zone, such as prod.company.com, in acme-core-dns | blueprint-api.<stage>.company.com from the chart's HTTPRoute |
ext-dns-int | external-dns-internal | internal.company.com in acme-core-network | argocd.<stage>.internal.company.com from the ArgoCD HTTPRoute |
Both use chart 1.23.0 in kube-system on the tainted system pool, watch service, ingress and gateway-httproute sources every minute, run the sync policy and register ownership with the owner ID <prefix>-gke-<release>. An @optional line in the public unit switches it to upsert-only. The zone name and project come from the landing-zone contract.
One zone each. Each release's Kubernetes service account is bound through Workload Identity Federation for GKE, directly as an IAM principal, to roles/dns.admin on its own zone only. The stage deployer writes that binding, which it can do because the Baseline made it roles/dns.admin of exactly those two zones; see Cloud DNS. Listing a project's zones is a project-level permission that zone IAM cannot grant, so the Baseline also gives each release roles/dns.reader on acme-core-dns or acme-core-network, for every stage listed in webapp_gke_stages of environments/plat/plat.hcl.
What it does not write. The SPA's A record and the Certificate Manager DNS authorization records are written by OpenTofu in the frontend-service and api-gateway units, not by external-dns; see Certificate Manager.
Terms you will see
| Term | Meaning |
|---|---|
| Source | A Kubernetes resource type external-dns reads hostnames from. |
| Domain filter | The zone name a release is limited to. |
| TXT registry | TXT records that mark which records a release owns. |
sync policy | Create, update and delete the release's records to match the sources. |
ext-dns-int | The release that writes the internal zone. |
Where to read more
- GCP Web App Blueprint overview for the hostnames.
- Cloud DNS for the zones and their IAM.
- GKE Gateway for the routes it reads.