DEV Community

Cover image for Deploying Gateway API with TLS Encryption on Kubernetes
Sanskriti Harmukh for Vultr

Posted on with Aashish Chaurasiya Originally published at docs.vultr.com

Deploying Gateway API with TLS Encryption on Kubernetes

The Kubernetes Gateway API is the successor to Ingress, a more expressive, role-oriented resource model (GatewayClass, Gateway, HTTPRoute) for advanced traffic routing and cross-namespace connectivity. This guide installs Envoy Gateway as the controller, configures cert-manager for automated Let's Encrypt TLS, and routes HTTPS traffic to a sample app.

Prerequisites: a Kubernetes cluster, kubectl and helm configured against it, and a domain name (e.g. app.example.com).


Install Envoy Gateway

Envoy Gateway translates Gateway API resources into Envoy Proxy configuration.

1. Install the CRDs and controller:

$ helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.6.1 -n envoy-gateway-system --create-namespace
$ kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=Available
Enter fullscreen mode Exit fullscreen mode

2. Register a GatewayClass:

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

Install cert-manager

Deploy cert-manager with the Gateway API feature gate on, so it can route Let's Encrypt HTTP-01 validation traffic through the Gateway.

$ 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
$ kubectl wait --for=condition=Ready pods --all -n cert-manager
Enter fullscreen mode Exit fullscreen mode

Configure a ClusterIssuer

Registers the cluster with Let's Encrypt so it can issue certificates cluster-wide, using the HTTP-01 solver via the Gateway.

$ nano cluster-issuer.yaml
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
$ kubectl apply -f cluster-issuer.yaml
Enter fullscreen mode Exit fullscreen mode

Deploy a Sample App

$ kubectl create deployment web-app --image=nginxdemos/hello --replicas=2
$ kubectl expose deployment web-app --port=80 --target-port=80
Enter fullscreen mode Exit fullscreen mode

Initialize the Gateway

The Gateway resource provisions a cloud LoadBalancer and public IP, and defines HTTP/HTTPS listeners for your domain.

$ nano gateway.yaml
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
$ kubectl apply -f gateway.yaml
$ kubectl get gateway web-gateway
Enter fullscreen mode Exit fullscreen mode

Point your domain's DNS A record at the returned external IP, then check the certificate:

$ kubectl get certificate
Enter fullscreen mode Exit fullscreen mode

It may take a few minutes to flip to True.


Configure Secure Routing

Attach an HTTPRoute to the HTTPS listener only, so the app is unreachable over plain HTTP.

$ nano http-route.yaml
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
$ kubectl apply -f http-route.yaml
Enter fullscreen mode Exit fullscreen mode

Visit https://app.example.com. You should see a valid-certificate padlock and the sample app.


Next Steps

Envoy Gateway is routing HTTPS traffic via the Gateway API, with cert-manager handling certificate lifecycle automatically. From here:

  • Add more HTTPRoute rules for path/header-based routing to additional backends
  • Move the ClusterIssuer to the Let's Encrypt staging endpoint while testing to avoid rate limits
  • Explore GRPCRoute and TCPRoute for non-HTTP traffic through the same Gateway

For the full guide, visit the original article on Vultr Docs.

Top comments (0)