Skip to main content

Gateway API & TLS

Purpose: For application developers, shows how to configure HTTPS routing with Gateway listeners, HTTPRoutes, and cert-manager certificates.

Task Summary

This guide covers configuring HTTPS access for your application using Gateway API for routing and cert-manager for automated TLS certificates. The platform provides a shared Gateway; application teams create HTTPRoutes that attach to it.

Prerequisites

  • An openCenter cluster with Gateway API CRDs installed
  • cert-manager deployed as a platform service
  • A shared Gateway resource in gateway-system namespace (managed by the platform team)
  • DNS configured to point your hostname to the Gateway's external IP

Steps

1. Understand the Gateway Architecture

The platform team manages the Gateway resource. Application teams create HTTPRoutes that reference it:

2. Create an HTTPRoute

Define an HTTPRoute in your application namespace:

# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app
namespace: my-app
spec:
parentRefs:
- name: platform-gateway
namespace: gateway-system
hostnames:
- "my-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: my-app
port: 80

The parentRefs field attaches this route to the platform Gateway. The Gateway must have a listener that accepts routes from your namespace (configured by the platform team via allowedRoutes).

3. Request a TLS Certificate (Custom Domain)

If your application uses a hostname outside the platform's wildcard certificate, request a dedicated certificate using cert-manager:

# certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-app-tls
namespace: gateway-system
spec:
secretName: my-app-tls-secret
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer
dnsNames:
- "my-app.custom-domain.com"

The platform team then references this secret in a Gateway listener:

# Gateway listener addition (managed by platform team)
listeners:
- name: my-app-custom
protocol: HTTPS
port: 443
hostname: "my-app.custom-domain.com"
tls:
mode: Terminate
certificateRefs:
- name: my-app-tls-secret
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: "true"

4. Configure Path-Based Routing

For applications with multiple backends behind a single hostname:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app-routes
namespace: my-app
spec:
parentRefs:
- name: platform-gateway
namespace: gateway-system
hostnames:
- "my-app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend-service
port: 3000

Rules are evaluated in order. Place more specific paths first.

Verification

Check the HTTPRoute is accepted by the Gateway:

kubectl get httproute -n my-app my-app -o jsonpath='{.status.parents[0].conditions}'
# Look for: type=Accepted, status=True

Test HTTPS connectivity:

curl -v https://my-app.example.com/healthz
# Verify TLS handshake succeeds and returns 200

Check certificate status (if using a custom cert):

kubectl get certificate -n gateway-system my-app-tls
# Expected: READY=True

Troubleshooting

SymptomCauseFix
HTTPRoute status shows NotAcceptedGateway doesn't allow routes from your namespaceAsk platform team to add your namespace label to allowedRoutes
TLS handshake failsCertificate not yet issued or wrong hostnameCheck kubectl describe certificate for ACME errors
404 on valid pathPath matching order or missing backendRefVerify Service name and port match; check path ordering
Certificate stuck in "Issuing"DNS not pointing to Gateway IP or ACME challenge failingVerify DNS resolution: dig my-app.custom-domain.com

Further Reading