openova/platform/external-dns/README.md
hatiyildiz f5daac52af refactor(platform): remove k8gb — replaced by PowerDNS lua-records (#171)
PowerDNS lua-records (`ifurlup`, `pickclosest`, `ifportup`) cover everything
k8gb was doing — geo-aware response selection, health-checked failover,
weighted round-robin — at the authoritative DNS layer. Eliminates a
separate K8s controller, CRD set, and CoreDNS plugin from every Sovereign.

Changes:
- platform/k8gb/ deleted (Chart.yaml, values.yaml, blueprint.yaml never
  authored — only README existed)
- products/catalyst/bootstrap/ui/public/component-logos/k8gb.svg deleted
- componentGroups.ts: remove k8gb component (PowerDNS already there)
- componentLogos.tsx: drop logo_k8gb + k8gb map entry
- model.ts DEFAULT_COMPONENT_GROUPS spine: replace k8gb with powerdns
- StepInfrastructure.tsx: copy refers to PowerDNS lua-records, not k8gb
- provision.html: replace k8gb tile and edges with powerdns
- catalog.generated.ts regenerated (now includes bp-powerdns)
- docs sweep — every k8gb reference in PLATFORM-TECH-STACK, NAMING-
  CONVENTION, SOVEREIGN-PROVISIONING, SRE, ARCHITECTURE, GLOSSARY,
  COMPONENT-LOGOS, IMPLEMENTATION-STATUS, BUSINESS-STRATEGY,
  TECHNOLOGY-FORECAST, README, infra/hetzner/README, platform READMEs
  (cilium, external-dns, failover-controller, litmus, flux, opentofu)
  rewritten to point at PowerDNS lua-records / MULTI-REGION-DNS.md.
  Historical entries in VALIDATION-LOG.md preserved as audit trail.
- New docs/MULTI-REGION-DNS.md — canonical reference for the lua-record
  patterns (ifurlup all/pickclosest/pickfirst, ifportup, pickwhashed),
  Application Placement → lua-record selector mapping, when to add a
  second Sovereign region, operational checks.

Closes #171.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 08:51:09 +02:00

141 lines
3.7 KiB
Markdown

# ExternalDNS
DNS synchronization (registers/deletes records via the PowerDNS REST API and external cloud DNS APIs where applicable). Per-host-cluster infrastructure (see [`docs/PLATFORM-TECH-STACK.md`](../../docs/PLATFORM-TECH-STACK.md) §3.1) — runs on every host cluster, primarily on the DMZ block. PowerDNS (see [`docs/PLATFORM-POWERDNS.md`](../../docs/PLATFORM-POWERDNS.md)) is the authoritative server for every Sovereign zone; ExternalDNS uses the `webhook` provider (`external-dns-pdns`) to write A/AAAA/CNAME records into PowerDNS. Health-checked geo-failover lives in PowerDNS lua-records — see [`docs/MULTI-REGION-DNS.md`](../../docs/MULTI-REGION-DNS.md).
**Status:** Accepted | **Updated:** 2026-04-27
---
## Overview
ExternalDNS synchronizes Kubernetes resources (Gateway, Service, Ingress) with external DNS providers, enabling automatic DNS record management.
---
## Architecture
```mermaid
flowchart TB
subgraph K8s["Kubernetes"]
GW[Gateway API]
Svc[Services]
ExtDNS[ExternalDNS]
end
subgraph DNS["DNS Providers"]
PDNS[PowerDNS<br>(authoritative — every Sovereign zone)]
CF[Cloudflare]
R53[Route53]
HDNS[Hetzner DNS]
end
GW --> ExtDNS
Svc --> ExtDNS
ExtDNS --> PDNS
ExtDNS --> CF
ExtDNS --> R53
ExtDNS --> HDNS
```
---
## Supported DNS Providers
| Provider | Availability |
|----------|--------------|
| Cloudflare | Always |
| Hetzner DNS | If Hetzner chosen |
| AWS Route53 | If AWS chosen |
| GCP Cloud DNS | If GCP chosen |
| Azure DNS | If Azure chosen |
---
## Configuration
### ExternalDNS Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
namespace: external-dns
spec:
template:
spec:
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.14.0
args:
- --source=gateway-httproute
- --source=gateway-grpcroute
- --source=service
- --provider=cloudflare
- --cloudflare-proxied
- --txt-owner-id=openova
- --txt-prefix=_externaldns.
env:
- name: CF_API_TOKEN
valueFrom:
secretKeyRef:
name: cloudflare-credentials
key: api-token
```
---
## PowerDNS Integration (geo + health-checked failover)
ExternalDNS writes plain A/AAAA/CNAME records into PowerDNS via the REST API. Geo-aware and health-checked failover responses are owned by PowerDNS lua-records, written by the `catalyst-dns` controller — ExternalDNS does NOT manage lua-record content.
```mermaid
flowchart LR
subgraph Region1["Region 1"]
App1[Application]
ExtDNS1[ExternalDNS]
end
subgraph Region2["Region 2"]
App2[Application]
ExtDNS2[ExternalDNS]
end
subgraph PDNS["PowerDNS Authoritative"]
ZoneAPI[REST API]
Lua[lua-records (ifurlup, pickclosest)]
end
ExtDNS1 -->|"plain A/AAAA"| ZoneAPI
ExtDNS2 -->|"plain A/AAAA"| ZoneAPI
ZoneAPI --- Lua
```
See [`docs/MULTI-REGION-DNS.md`](../../docs/MULTI-REGION-DNS.md) for the lua-record patterns.
---
## Record Types
| Source | Record Type | Example |
|--------|-------------|---------|
| Gateway | A/CNAME | `api.<domain>` |
| Service (LoadBalancer) | A | `svc.<domain>` |
| catalyst-dns (lua-record author) | LUA A | `app.<domain>` (geo + health-checked) |
---
## TXT Registry
ExternalDNS uses TXT records to track ownership:
```
_externaldns.api.<domain> TXT "heritage=external-dns,external-dns/owner=openova"
```
This prevents ExternalDNS from modifying records it doesn't own.
---
*Part of [OpenOva](https://openova.io)*