How to Deploy Gateway API with TLS Encryption on Kubernetes

Updated on 15 January, 2026
Configure Kubernetes Gateway API with Envoy Gateway and cert-manager for HTTPS traffic routing.
How to Deploy Gateway API with TLS Encryption on Kubernetes header image

The Kubernetes Gateway API is a standard interface for managing service networking within Kubernetes clusters. It succeeds the Ingress API by offering a more expressive and extensible resource model (comprising GatewayClass, Gateway, and HTTPRoute) to handle advanced traffic routing, role-oriented management, and cross-namespace connectivity natively.

This article outlines the process of exposing a web application securely using the Gateway API. It covers the installation of Envoy Gateway as the controller and configuration of cert-manager for automated TLS certificate provisioning from Let's Encrypt.

Prerequisites

Before you begin, you need to:

Install Envoy Gateway

The Gateway API requires an implementation controller to function. Envoy Gateway translates Gateway API resources into configuration for the Envoy Proxy data plane.

  1. Install the Gateway API CRDs and the Envoy Gateway controller using the OCI Helm registry.

    console
    $ helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.6.1 -n envoy-gateway-system --create-namespace
    
  2. Wait for the controller to report as available.

    console
    $ kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available
    
  3. Create the GatewayClass resource to register the Envoy Gateway controller.

    console
    $ kubectl apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: GatewayClass
    metadata:
      name: eg
    spec:
      controllerName: gateway.envoyproxy.io/gatewayclass-controller
    EOF
    

Install cert-manager

Deploy the cert-manager operator with the Gateway API feature gate enabled. This configuration ensures the certificate controller can communicate with the Gateway API to route Let's Encrypt validation traffic correctly.

  1. Install the cert-manager Helm chart with Gateway API support enabled.

    console
    $ helm upgrade --install cert-manager oci://quay.io/jetstack/charts/cert-manager \
        --namespace cert-manager \
        --create-namespace \
        --version v1.19.2 \
        --set config.apiVersion=controller.config.cert-manager.io/v1alpha1 \
        --set config.kind=ControllerConfiguration \
        --set config.enableGatewayAPI=true \
        --set crds.enabled=true
    
  2. Verify that the cert-manager pods enter the Running state.

    console
    $ kubectl wait --for=condition=Ready pods --all -n cert-manager
    

Configure the ClusterIssuer

A ClusterIssuer represents a certificate authority capable of issuing TLS certificates cluster-wide. Register the cluster with Let's Encrypt to automate certificate management. This ClusterIssuer configuration enables the ACME HTTP-01 solver, which allows cert-manager to prove domain ownership.

  1. Create a ClusterIssuer manifest.

    console
    $ nano cluster-issuer.yaml
    
  2. Add the following configuration. Replace admin@example.com with your valid email address.

    yaml
    apiVersion: cert-manager.io/v1
    kind: ClusterIssuer
    metadata:
      name: letsencrypt-prod
    spec:
      acme:
        server: https://acme-v02.api.letsencrypt.org/directory
        email: admin@example.com
        privateKeySecretRef:
          name: letsencrypt-prod
        solvers:
          - http01:
              gatewayHTTPRoute:
                parentRefs:
                  - name: web-gateway
                    kind: Gateway
    

    Save and close the file.

  3. Apply the ClusterIssuer manifest.

    console
    $ kubectl apply -f cluster-issuer.yaml
    

Deploy a Sample Web Application

To verify traffic routing, deploy a simple web application using the nginxdemos/hello image.

  1. Create a deployment for the web application.

    console
    $ kubectl create deployment web-app --image=nginxdemos/hello --replicas=2
    
  2. Expose the deployment internally as a Service.

    console
    $ kubectl expose deployment web-app --port=80 --target-port=80
    

Initialize the Gateway

Deploy the Gateway resource to provision a cloud LoadBalancer and assign a public IP address. This resource defines how the cluster handles traffic for your domain.

  1. Create the Gateway manifest file.

    console
    $ nano gateway.yaml
    
  2. Add the following configuration. Replace app.example.com with your actual domain name.

    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: web-gateway
      annotations:
        cert-manager.io/cluster-issuer: letsencrypt-prod
    spec:
      gatewayClassName: eg
      listeners:
        - name: http
          protocol: HTTP
          port: 80
          hostname: "app.example.com"
          allowedRoutes:
            namespaces:
              from: Same
        - name: https
          protocol: HTTPS
          port: 443
          hostname: "app.example.com"
          tls:
            mode: Terminate
            certificateRefs:
              - kind: Secret
                name: web-app-tls-secret
          allowedRoutes:
            namespaces:
              from: Same
    

    Save and close the file.

  3. Apply the Gateway manifest.

    console
    $ kubectl apply -f gateway.yaml
    
  4. Retrieve the Gateway external IP address.

    console
    $ kubectl get gateway web-gateway
    
  5. Update your domain’s DNS A record to point to the assigned IP address.

  6. Verify the TLS certificate status.

    console
    $ kubectl get certificate
    

    The certificate may take a few minutes to update to True.

Configure Secure Application Routing

Define the routing rules to direct traffic from the Gateway to your backend service. Attach this route exclusively to the HTTPS listener to enforce encryption and prevent insecure access.

  1. Create the HTTPRoute manifest file.

    console
    $ nano http-route.yaml
    
  2. Add the following configuration:

    yaml
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: web-app-route
    spec:
      parentRefs:
        - name: web-gateway
          sectionName: https
      hostnames:
        - "app.example.com"
      rules:
        - backendRefs:
            - name: web-app
              port: 80
    

    Save and close the file.

  3. Apply the HTTPRoute manifest.

    console
    $ kubectl apply -f http-route.yaml
    
  4. Open a web browser and navigate to your domain name https://app.example.com. Verify that the browser displays a padlock icon next to the URL, indicating a valid certificate, and loads the application successfully.

Conclusion

You have deployed a Gateway API setup with Envoy Gateway and cert-manager. The web application is now secure and accessible via HTTPS using the Gateway API. Envoy Gateway manages the traffic routing, while cert-manager automates the lifecycle of Let's Encrypt certificates. Refer to the official Gateway API documentation for advanced routing and traffic management features.

Comments