AKS: health-gated, region-aware services
This page composes shipped DTM features into a reference architecture for multi-region AKS services: ExternalDNS publishes per-region service hostnames into a shadow subdomain, and one DTM record wraps them into a single stable name that returns only healthy, preferably-local answers, entirely on private IPs.
The shape
Section titled “The shape”Each regional cluster runs its own ExternalDNS instance publishing into a shadow subdomain, exactly as on the ExternalDNS page:
web-eastus.svc.aks.internal.examplefrom the East US clusterweb-westus.svc.aks.internal.examplefrom the West US cluster
Clients never use those names. Instead, a single DTM record, web.app.internal,
wraps both. DTM resolves the shadow hostnames, health-checks the addresses
behind them, applies a region-aware (or failover) policy, and answers each
client with the best healthy private IP. When a region’s service degrades or
its address changes, the stable name follows automatically and nobody edits a
record.
Why this matters
Section titled “Why this matters”Azure Private DNS records are static: there is no health awareness, so a dead backend keeps resolving. Azure Traffic Manager is health-aware but probes public endpoints. For private AKS services there is a real gap: server-side, health-gated, region-aware answers on private IPs. That is exactly what this composition provides, with failover decided centrally by DTM rather than by each client.
Choose a wrap: ALIAS or override
Section titled “Choose a wrap: ALIAS or override”There are two ways to build the stable name; pick one.
Option A: an ALIAS record over the shadow hostnames
Section titled “Option A: an ALIAS record over the shadow hostnames”An ALIAS record in a DTM zone points at the shadow
hostnames. DTM keeps them resolved, health-checks the resolved addresses, and
returns flattened A records.
curl -X POST https://<dtm>/api/v1/zones/<zone-id>/records \ -H "Authorization: Bearer <token>" \ -H "X-DTM-CSRF: 1" \ -H "Content-Type: application/json" \ -d '{ "name": "web", "type": "ALIAS", "ttl": 30, "values": [ { "value": "web-eastus.svc.aks.internal.example", "region": "eastus" }, { "value": "web-westus.svc.aks.internal.example", "region": "westus" } ], "lb_policy": { "method": "region" }, "health_check_template": { "protocol": "https", "port": 443, "path": "/healthz", "interval_seconds": 5 } }'lb_policy:regionsteers each client to its own region and fails over across regions when one goes unhealthy.failovergives you an active/standby shape, andweightedsupports canary-style splits.health_check_template: template-created checks probe every resolved address with an interval of at least5seconds (default15), marking a target down after3consecutive failures and up again after2consecutive successes.
Option B: a static-mode override record plus a reconciler
Section titled “Option B: a static-mode override record plus a reconciler”If you prefer not to host a zone for the stable name, use a static-mode override record instead. A small reconciler you run (for example, a controller watching the two regional services) writes the services’ current IPs into the override; DTM’s probes target those IPs directly, and no forwarder is involved:
curl -X POST https://<dtm>/api/v1/overrides \ -H "Authorization: Bearer <token>" \ -H "X-DTM-CSRF: 1" \ -H "Content-Type: application/json" \ -d '{ "fqdn": "web.app.internal.", "type": "A", "target_mode": "static", "ttl": 30, "values": [ { "value": "10.10.0.20", "region": "eastus" }, { "value": "10.20.0.20", "region": "westus" } ], "lb_policy": { "method": "region" }, "health_check_template": { "protocol": "https", "port": 443, "path": "/healthz", "interval_seconds": 5 } }'The trade-off is ownership: with Option A, DTM follows address changes automatically; with Option B, your reconciler must update the override whenever a service’s IP changes, but the resolution path is simpler and fully under your control.
Failure behavior to expect
Section titled “Failure behavior to expect”- A pod or backend fails its probe: that region’s address is dropped from
the answer after
3failed probes; clients land on the remaining healthy region. - A whole region goes down: with
method: region, clients in the failed region are served the other region’s healthy address automatically. - The region recovers: after
2consecutive successful probes the address returns to answers, and region-local clients drift back on the record’s TTL (30seconds above).
Good to know
Section titled “Good to know”- Terraform: the wrap record works as code too:
dtm_recordsupportstype = "ALIAS", and override records are available asdtm_override_record; see ALIAS, GSLB and overrides. - Regions: the
regiontags on values drive theregionpolicy; see regions and subnet mappings for how DTM decides which region a client is in. - One stable name per service: repeat the wrap per service (
web,api, and so on); each gets its own policy and health template.
Need a hand? Email [email protected].