Files
home-network-k3s-impl/platform/externaldns/helmrelease.yaml
T
jakman85andClaude Opus 4.8 20de78f5eb feat(conformance): author R-TLS + R-DNS L2 tests; fix ExternalDNS zone filter
Phase-2 exit tests (were Phase-0 scaffolds), authored against the live platform:
- trusted-tls (R-TLS-01/03): in-cluster probe dials the gateway Service (env-agnostic
  via --connect-to) with wildcard SNI and verifies the served cert CHAINS TO THE LE
  STAGING ROOT (operator decision A; dev uses LE-staging per ADR-0006). Fixture embeds
  the '(STAGING) Pretend Pear X1' root. Probes public + internal-only hostnames (R-TLS-03).
  PASSES.
- dns-exposure (R-DNS-02): a LoadBalancer Service with an external-dns hostname; polls
  public DNS until ExternalDNS auto-publishes the record; teardown + policy=sync removes it.

ExternalDNS fix (root cause of the DNS test): domain-filter was the platform SUBDOMAIN
home.keithjackson.dev, which filters OUT the actual Cloudflare zone keithjackson.dev
('no hosted zone matching record DNS Name' — record generated but skipped). Add a
DNS_ZONE cluster-var (keithjackson.dev) and set domainFilters to it. policy=sync +
txt-registry still only manage ExternalDNS-owned records (the pre-existing wildcard is
untouched). Resolves the file's WS-NET R-DNS-02 TODO.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-17 08:24:51 -05:00

52 lines
2.2 KiB
YAML

---
# ExternalDNS — publishes public DNS records for `public` services automatically (docs/09, R-DNS-02).
# Watches Gateway/HTTPRoute (+Service); manages records in Cloudflare. Phase 0 STUB.
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: external-dns
namespace: external-dns
spec:
interval: 30m
chart:
spec:
chart: external-dns
version: ">=1.15.0 <1.16.0" # TODO(WS-NET): pin at bring-up; Renovate maintains
sourceRef:
kind: HelmRepository
name: external-dns
namespace: external-dns
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
values:
provider:
name: cloudflare
# Watch Gateway API routes (Cilium Gateway) + Services. docs/09: records rendered from intent.
sources:
- gateway-httproute
- service
# domain-filter MUST be the actual Cloudflare ZONE (keithjackson.dev), not the platform subdomain
# (home.keithjackson.dev) — ExternalDNS filters the account's zones by this value, and a subdomain
# filter drops the parent zone → "no hosted zone matching record DNS Name" and nothing is created.
# Scope stays effectively home.keithjackson.dev because that's the only suffix services request;
# policy=sync + registry=txt only ever touch ExternalDNS-OWNED records, never the pre-existing
# wildcard or other keithjackson.dev records. (docs/09; resolves the WS-NET TODO below.)
domainFilters:
- "${DNS_ZONE}"
policy: sync # create + update + delete records as services come and go
# Cloudflare API token: SOPS-encrypted secret, referenced BY NAME only (OQ-4, ADR-0007).
env:
- name: CF_API_TOKEN
valueFrom:
secretKeyRef:
name: cloudflare-api-token
key: api-token
# R-DNS-02 PROVEN via the `service` source: the conformance/l2-behavioral/dns-exposure test
# creates a LoadBalancer Service with an external-dns hostname and asserts the record auto-appears
# in public DNS (then teardown + policy=sync removes it). gateway-httproute source wiring is the
# same provider/zone path; a route-based test can follow when app routes exist.