Skip to main content

Declare the hostnames a data plane serves

Enterprise Tier

From 0.7.0 a data plane declares the hostnames it serves in its own chart, under global.gateway.hostnames, and reports them to the management plane on every configuration poll. The Admin Console lists them read-only. No console page or API call writes a declared hostname: adding or retiring one is a values change followed by tetrate agentrouter dataplane upgrade or helm upgrade.


Persona: Platform operator with access to the data plane's Helm values or tetrate identity file, the DNS zone, and the load balancer in front of the cluster.

Estimated time: 10 minutes for the values change, plus DNS propagation and certificate issuance.

Outcomes​

By the end of this guide:

  • The data plane's serve-helm values list every hostname callers use to reach it, with the name callers should use first.
  • Each declared hostname resolves to the data plane's load balancer, presents a certificate that covers it, and routes to the data plane.
  • The Admin Console lists the hostnames on the data plane's page, and tetrate agentrouter doctor confirms the certificate covers each one.

Prerequisites​

  • A self-hosted data plane on 0.7.0 or later. A data plane before 0.7.0 cannot declare hostnames and keeps the address stored for it through the admin API.
  • Control of the DNS zone for each hostname, and of the certificate the load balancer presents.
  • For a data plane that already serves traffic on a stored address, read Move a data plane to declared hostnames first. A partial list refuses later edits to gateway URLs that are missing from it.

Step 1: list the hostnames​

Add the list to the data plane's serve-helm values:

global:
gateway:
hostnames:
- eu.acme.example.com # first: the address the console prints
- dp.acme.example.com:8443 # a port, for callers that do not use 443

tetrate agentrouter dataplane install takes the same list as a repeatable flag:

# Declare two names at install time.
tetrate agentrouter dataplane install /path/to/data-plane-credentials.json \
--gateway-hostname=eu.acme.example.com \
--gateway-hostname=dp.acme.example.com:8443

# Upgrade and keep the installed list. tetrate agentrouter dataplane upgrade reads it from the release.
tetrate agentrouter dataplane upgrade /path/to/data-plane-credentials.json

# Upgrade and replace the list.
tetrate agentrouter dataplane upgrade /path/to/data-plane-credentials.json --gateway-hostname=eu.acme.example.com

There are 5 rules for the entries:

  1. An entry is a hostname, optionally with a port. The management plane stores the port apart from the name and joins them again when it prints an address. A scheme such as https:// is accepted and dropped.
  2. The first entry is the address the console prints wherever it shows a single address, such as the Base URL panel and the Playground. List the name callers should use first.
  3. Two data planes in one organization may declare the same name, which is how a pair behind a global server load balancer serves one hostname. The console lists both data planes under that name. Two gateways on one data plane still cannot share one.
  4. Leaving the key out declares nothing. The data plane keeps the address stored for it through SetDataplaneURL and answers its readiness probe there. serve-helm leaves the key out by default, so upgrading to 0.7.0 with untouched values changes nothing about where the data plane serves.
  5. An empty list is a declaration. It says the data plane serves no hostname: the management plane retires every name it recorded for the data plane, and the readiness probe stops answering. Write hostnames: [], or run tetrate agentrouter dataplane upgrade with --gateway-hostname="" alone, only to drain a data plane.
An upgrade that passes other values can drop the list

A helm upgrade that passes values without the key, such as a values file rewritten without it, --set flags alone, or --reset-values, drops the key. The readiness probe then falls back to the stored address, while the management plane keeps the names it last recorded and keeps refusing gateway URLs outside them. A helm upgrade that passes no values reuses the release's previous values and keeps the list, and tetrate agentrouter dataplane upgrade carries the installed list forward. Keep the list in the values file applied on every upgrade.

Step 2: apply and confirm the declaration​

  1. Run tetrate agentrouter dataplane upgrade or helm upgrade with the new values.

  2. Read what the chart rendered. The chart writes the list into the tars-gateway-declaration ConfigMap:

    kubectl -n tars-system get configmap tars-gateway-declaration -o jsonpath='{.data.gateway-hostnames}'
    ["eu.acme.example.com","dp.acme.example.com:8443"]

    An empty list renders []. A chart with the key left out renders no gateway-hostnames field at all, which the management plane reads as "declares nothing" rather than as an empty list.

  3. In the Admin Console, open Directory → Data Planes and select the data plane. The hostnames appear on its page once the data plane polls for configuration. A row tagged set through the management plane is a stored address, which means the chart still declares nothing.

Step 3: make each name serve​

Declaring a name tells the management plane that the data plane serves it. The chart creates no DNS record, certificate, or load balancer route. There are 3 things each declared name needs before a caller reaches it:

  1. A DNS record that points the name at the data plane's load balancer.
  2. A certificate on the load balancer, or on the cluster's own listener, that covers the name.
  3. A route at the load balancer that sends requests for the name to the data plane. Without it the TLS handshake succeeds and the request answers 404.

GKE with the gateway-serve-helm chart​

The gateway-serve-helm chart does not read global.gateway.hostnames. Pass the same names to it as gatewayHostnames, so its HTTPRoute matches each one beside serveUrl:

# gateway-serve-helm values (gateway.yaml)
customer: acme
serveUrl: proxy.acme.example.com
certificateMap:
name: acme-serve-certmap
gatewayHostnames:
- eu.acme.example.com
- dp.acme.example.com

The chart drops a port, a scheme, and a path from each entry, because a Gateway API hostname carries no port. Confirm the route after the upgrade:

kubectl -n tars-gateway get httproute proxy-route -o jsonpath='{.spec.hostnames}'

The chart names the certificate map and never creates its entries. tetrate agentrouter dataplane ingress install creates one map entry, for the serve host only. Create a certificate and a map entry for every further name:

HOST=eu.acme.example.com
SLUG=$(echo "$HOST" | tr . -)
MAP=acme-serve-certmap

gcloud certificate-manager dns-authorizations create "$SLUG-dns-auth" --domain="$HOST"
# Publish the CNAME this prints in the zone that holds $HOST.
gcloud certificate-manager dns-authorizations describe "$SLUG-dns-auth" --format='value(dnsResourceRecord)'

gcloud certificate-manager certificates create "$SLUG" \
--domains="$HOST" --dns-authorizations="$SLUG-dns-auth"
gcloud certificate-manager maps entries create "$SLUG-entry" \
--map="$MAP" --certificates="$SLUG" --hostname="$HOST"

The certificate stays PROVISIONING until the DNS authorization record is published. Point the name's A record at the Gateway's address once the certificate is ACTIVE.

TLS on the data plane​

From 0.8.0 a declared name can be published on 443 by the data plane itself: list it under egressResources.egress.gateway.httpsListeners with the Secret that holds its certificate, and egress-lb passes 443 through to it. The data plane presents the certificate and routes the name, so only the DNS record is left to the operator. Publication is per hostname: a name listed there is published for every project the data plane serves, and a declared name left out of the list gets no listener on 443. See Terminate TLS on the data plane.

AWS, Azure, and other load balancers​

No chart provisions the edge on AWS or Azure. The DNS record, the certificate (an ACM certificate on an ALB or NLB, or a Key Vault certificate on an Application Gateway), and the listener or Ingress rule for each name are the operator's own. Where the Ingress or listener uses host-based rules, add a rule for each declared name. See Gateway installation on EKS and Gateway installation on AKS.

Step 4: check the certificate the data plane reads​

A data plane on 0.7.0 or later reads the certificate serving each declared name and reports it beside the name: the subject alternative names, the issuer, the fingerprint, the validity window, the address the handshake reached, and where the reading was taken from. By default it dials each declared name over HTTPS, honouring HTTPS_PROXY and NO_PROXY, so it reads what a load balancer in front of the cluster presents as well as a certificate on the cluster's own listener.

global.gateway.certificateProbe changes where the data plane dials. There are 3 shapes:

  1. A private load balancer the cluster reaches but cannot resolve by name. Name its address, and optionally a port, an SNI, and a CA bundle that decides whether the chain reads as trusted:

    global:
    gateway:
    certificateProbe:
    address: dp-internal.eu-west-1.elb.amazonaws.com
    port: 8443
    sni: eu.acme.example.com # defaults to each declared name
  2. A GKE global external load balancer. Name the forwarding rule's address and leave sni out, so each declared name is sent in turn and the certificate map answers with the certificate it holds for that name:

    global:
    gateway:
    certificateProbe:
    address: 34.120.0.1
  3. An endpoint nothing inside the trust boundary can reach, such as a DMZ appliance or a CDN whose origin is unroutable. Turn the dial off:

    global:
    gateway:
    certificateProbe:
    enabled: false

    Every address then reads as not observed and says the chart disabled the probe. The data plane stays healthy.

certificateProbe says where to look. Nothing in it changes what the certificate says, so an expired certificate never reads as healthy.

Run the same reading from the command line:

tetrate agentrouter doctor /path/to/data-plane-credentials.json --only gateway

tetrate agentrouter doctor reads the listener certificate where a listener carries one, and otherwise dials each declared address the same way the data plane does, honouring certificateProbe. It reports:

ReadingSeverity
The certificate does not cover a declared nameWARN, naming the hostname
The certificate has expired, or is not valid yetERROR, with the time validity starts or ended. A not-yet-valid certificate points at the cluster clock or the issuing CA
The certificate expires soonReported with the time left
The address could not be reachedINFO, with the openssl s_client command to read it by hand. The data plane stays healthy

Troubleshooting​

SymptomCauseFix
A declared name appears in the console but requests to it answer 404The load balancer has no route for the name. TLS completes, then nothing matchesAdd the name to the load balancer's routes. On GKE, add it to gatewayHostnames on gateway-serve-helm
The GKE certificate for a new name stays PROVISIONINGThe DNS authorization record is not publishedPublish the record that gcloud certificate-manager dns-authorizations describe prints, then wait for ACTIVE
CreateProjectGateway, UpdateProjectGateway, or SetProjectGatewayURL fails with FailedPrecondition and data plane <id> does not declare "<hostname>", including a console edit that resends an unchanged URLThe data plane declares hostnames, and the URL's hostname is not one of themAdd the hostname to the list and upgrade the chart. See Move a data plane to declared hostnames
/healthz/membership answers 404 on one declared name while others answer 200The name is missing from the rendered ConfigMap, or the request's Host carries a non-standard portRead tars-gateway-declaration as in Step 2. The probe answers on port 443 only
After an upgrade, /healthz/membership stops answering on some declared names while the console still lists themThe upgrade passed values without global.gateway.hostnames, so the key was dropped and the probe fell back to the stored addressRe-run the upgrade with the values file that carries the list, or use tetrate agentrouter dataplane upgrade, which carries the list forward
tetrate agentrouter doctor warns that the certificate does not cover a nameThe certificate's subject alternative names lack the declared nameReissue the certificate with the name, or remove the name from the list
From 0.8.0, GetDataplaneURL and ListDataplaneURLs return no URL for the data plane, or Prompt is refusedAnother organization uses the same data plane ID, and this data plane declares no hostnames. For a data plane whose ID is shared, the inference API returns only the first hostname the data plane declares, and never the URL stored under the shared IDList the data plane's hostnames under global.gateway.hostnames and upgrade the chart, as in Step 1
From 0.8.0, SetDataplaneURL or SetWorkspaceURL fails with FailedPrecondition, or CreateServiceAccount with a serve URL is refusedAnother organization uses the same data plane ID. The URL is stored under the ID alone, so the write would also change the other organization's data plane. CreateServiceAccount is refused only while no URL is stored for that IDInstall the data plane under an ID no other organization uses, then repeat the request for the new ID. The URL stored under the shared ID stays as it is, because it serves the other organization too