Repository navigation
Gateway API
For operators who run Titanium behind Kubernetes Gateway API resources. The full guide, with every option, is on the website.
titanium-gateway is a leader-elected controller that turns GatewayClass, Gateway, HTTPRoute, and ReferenceGrant resources (Gateway API standard channel v1.2.1, HTTP core) into the twp.yaml the Titanium data plane runs, and writes status back. The chart is deploy/helm/titanium-gateway; the controller image is ghcr.io/justcoding121/titanium-gateway for linux/amd64 and linux/arm64.
helm install titanium-gateway ./deploy/helm/titanium-gateway --namespace gateway-system --create-namespace| Step | Behavior |
|---|---|
| Watch | Informers for GatewayClass, Gateway, HTTPRoute, ReferenceGrant, Namespace, Service, EndpointSlice, and kubernetes.io/tls Secrets. |
| Render | One pure function turns the cluster state into a config and status. A coalesced loop runs it at most once every 500 ms. |
| Write | Only the Lease leader writes the data-plane ConfigMap, the converted-certificate Secret, and status. A follower takes over within 15 s. |
| Reload | Routes, clusters, and certificates reload in place. A change of the listener set rolls the data-plane Deployment. |
| Confirm |
Programmed is True only when every ready data-plane pod reports the rendered config's hash on /version. |
-
Gateway:
HTTPandHTTPS(Terminate) listeners,hostname,allowedRoutes,certificateRefs(a cross-namespace Secret needs aReferenceGrant),attachedRoutes, addresses from the data-plane Service. -
HTTPRoute: path
Exact,PathPrefix,RegularExpression; headerExact; query parameterExactandRegularExpression;method; Gateway API precedence. -
Backends:
Servicebackends withweight, from readyEndpointSliceendpoints only. -
Filters:
RequestHeaderModifier,ResponseHeaderModifier,URLRewrite,RequestRedirect,RequestMirror;timeouts.requestandtimeouts.backendRequest.
-
GRPCRoute,TCPRoute,UDPRoute,TLSRoute,BackendTLSPolicy, TLSPassthrough, andGateway.spec.addressesare not handled. - A rule that uses an unsupported value (header regular expression,
ReplacePrefixMatchredirect, a redirect status other than 301 and 302, a second mirror) answers500, and the reason is in the route status. - Routes are global across listeners: the data plane does not scope a route to a listener port. Gateways of one class share one data plane, and their listeners on one port merge. A request no route matches answers
404. - A header modifier
addappends to a value that is already there, joined with,(Set-Cookiekeeps one line per cookie). - A rule that mixes usable and unusable backends answers
503for the unusable share, where the specification says500. - Header values match case-insensitively.
ResponseHeaderModifieradd acts as set. - Gateway ports
80and443are bound as8080and8443because the data plane is non-root (dataPlane.ports).
tools/gateway-conformance/run.sh runs the upstream Gateway API conformance suite (v1.2.1, GATEWAY-HTTP) against the controller in a kind cluster; .github/workflows/gateway-conformance.yml runs it on Linux and uploads the report. It needs Linux, Docker, kind, kubectl, and Helm, and does not run on a Windows host (use WSL 2). Only implemented features are claimed. The last run (before the data-plane header-append and SNI-handshake fixes) passed 31 of 33 core tests; it has not been re-run since. The first runs report only; setting the repository variable GATEWAY_CONFORMANCE_ENFORCE to true makes a failing suite fail the workflow.
The controller also serves networking.k8s.io/v1 Ingress resources of its IngressClass (titanium.io/ingress-controller). Hosts and paths (Exact, Prefix, ImplementationSpecific), defaultBackend, tls, and Service backends are translated; backend.resource is rejected with an event. titanium.io/ annotations map to existing data-plane features (rewrite, timeout, body size, backend protocol, affinity, load balancing, allow list, rate limit, CORS preflight, external auth, canary, upstream TLS); an unknown or invalid annotation raises a warning event and is never ignored silently. kubernetes.io/ingress.class is honored only with --watch-legacy-annotation. The Ingress gets status.loadBalancer from the data-plane Service. The full annotation table is in the website guide.
RBAC is least privilege: reads on the watched kinds, status writes, and update and patch by name on the data-plane ConfigMap, certificate Secret, Deployment, and Lease, plus patch on pods in the release namespace so a config change reaches the pods in seconds. Reading TLS Secrets is cluster-wide by default; set controller.secretNamespaces to narrow it. Private keys stay in the controller's memory. Both images run as UID 1654, read-only, with no capabilities.