Skip to main content
logoTetrate Enterprise Envoy Gateway (TEG)Version: v0.1.0

Exposing an Application using Tetrate Enterprise Envoy Gateway (TEG)

With Tetrate Enterprise Envoy Gateway (TEG) installed, we can now expose an application to the outside world. This means that requests to our application should be sent to Tetrate Enterprise Envoy Gateway (TEG), which will forward them to our application. Our application is not directly exposed to the outside world, and all requests to it will be subject to processing by TEG, e.g. enforcing authentication or a ratelimit.

  1. Deploy Test Application

    If you don't have an application in your cluster ready to use with Tetrate Enterprise Envoy Gateway (TEG), you can deploy a demo application, httpbin, instead:

    kubectl create namespace httpbin
    kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml
    note

    We need somewhere for TEG to send traffic. In addition to Pods, the above file also deployed a Service called httpbin which listens on port 8000. If you're using your own app, be sure it has a Kubernetes Service deployed in the default namespace, and that you know that Service's name and port.

  2. Deploy Envoy Proxies

    Requests destined for our application will be handled by a set of Envoy proxies at the edge of our cluster's network. They listen for incoming requests from the outside world and forward them on to our app; sitting between it and its clients. They perform the same job that you might be familiar with nginx, haproxy, or other ingress controllers doing.

    However when you install TEG, you only deploy a piece of software that manages Envoy proxies, not any proxies themselves. Our first job is to arrange for a set of proxies to be deployed to handle our traffic.

    info

    The deployment style we're using here is dedicated gateways. For more information, read about the difference between dedicated gateways and shared gateways.

    This is done with the Gateway resource as follows:

    dedicated-gateway.yaml
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: Gateway
    metadata:
    name: dedicated-gateway
    namespace: httpbin
    spec:
    gatewayClassName: teg
    listeners:
    - name: http
    protocol: HTTP
    port: 80

    With the above Gateway configuration applied, you'll see the dedicated Envoy Gateway will be deployed in the envoy-gateway-system namespace. There'll likely only be one for now as load is low; they'll autoscale up if more are needed.

    kubectl get pods -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=httpbin
    NAME                                                        READY   STATUS    RESTARTS   AGE
    envoy-httpbin-dedicated-gateway-c4239473-687774796c-w4ckf 1/1 Running 0 95s

    The gateway is listening for traffic coming from outside the cluster, on port 80.

    kubectl get gateway -n httpbin
    NAME                CLASS   ADDRESS           PROGRAMMED   AGE
    dedicated-gateway teg 104.196.111.251 True 2m42s
    kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=httpbin
    NAME                                       TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
    envoy-httpbin-dedicated-gateway-c4239473 LoadBalancer 10.103.247.77 104.196.111.251 80:31942/TCP 2m24s
  3. Routing Traffic to our App

    The proxies are running and listening on port 80; they receive traffic bound for services in our cluster. Next we need to tell TEG which apps (ie Pods, microservices) to send which requests to.

    info

    We can match different requests based on any HTTP attribute they possess, but the most common to use are the HTTP host and the path. You're probably familiar with routing traffic on path, and on the host header, aka vHosting. To avoid things getting too complicated with DNS, we'll differentiate our traffic on its path, mounting our httpbin example app under /httpbin/.

    For this we use an HTTPRoute resource. There are different types of Route resource for different protocols, allowing us to route on protocol-specific attributes, e.g. HTTPRoute can talk about paths, which are not present in TCP.

    Apply the following resource. Since it's a little longer, we'll examine it section-by-section afterwards.

    note

    If you're using your own app, rather than the example httpbin, change the details in the backendRefs section.

    httpbin-httproute.yaml
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
    name: httpbin
    namespace: httpbin
    spec:
    parentRefs:
    - group: gateway.networking.k8s.io
    kind: Gateway
    name: dedicated-gateway
    rules:
    - matches:
    - path:
    type: PathPrefix
    value: /httpbin/
    filters:
    - type: URLRewrite
    urlRewrite:
    path:
    type: ReplacePrefixMatch
    replacePrefixMatch: /
    backendRefs:
    - group: ""
    kind: Service
    name: httpbin
    port: 8000

    The notable sections of this config are:

    • parentRefs: the HTTPRoute attaches to the Gateway from earlier; this means its rules apply to traffic that hits the physical proxies deployed by that Gateway
    • matches: this section identifies which requests we want this resource to process. In this case, we're matching requests on their path, specifically any path that starts with /httpbin/
    • filters: filters let us perform basic processing on the request before sending it on. In our case, the user will request httpbin endpoints as e.g. /httpbin/get, but httpbin doesn't know about the TEG layer in front of it, so is just expecting requests for /get. Thus we remove the prefix that we matched before passing the request on.
    • backendRefs: the place to forward matching requests to. We're forwarding to a Kubernetes Service, in the same namespace as our HTTPRoute resource, called httpbin, and we know it listens on port 8000.
  4. Make a Request to httpbin

    Now we can make a test request to our app, via TEG. Without making assumptions about your cluster and environment, the only way to address the apps gateway we deployed is by its IP address. The IP we want is the external one, ie the one available outside the cluster. We can find that and store it in a shell variable thus:

    export DEDICATED_GATEWAY_IP=$(kubectl get service -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=httpbin -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
    note

    If you're using a cluster in AWS, you'll need to use the Gateway's name instead: .status.loadBalancer.ingress[0].hostname.

    We can then make a request:

    curl -i http://${DEDICATED_GATEWAY_IP}/httpbin/get

    You should see output like:

    HTTP/1.1 200 OK
    server: envoy
    date: Mon, 04 Sep 2023 15:15:32 GMT
    content-type: application/json
    content-length: 339
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 3
    {
    "args": {},
    "headers": {
    "Accept": "*/*",
    "Host": "104.196.111.251",
    "User-Agent": "curl/8.1.2",
    "X-Envoy-Expected-Rq-Timeout-Ms": "15000",
    "X-Envoy-External-Address": "99.254.151.222",
    "X-Envoy-Original-Path": "/httpbin/get"
    },
    "origin": "99.254.151.222",
    "url": "http://104.196.111.251/get"
    }

    Congratulations on the successful deployment of your first Tetrate Enterprise Envoy Gateway (TEG) instance!

Next Steps

  1. Point DNS at the Tetrate Enterprise Envoy Gateway (TEG) External IP (technically: the IP of the cloud LoadBalancer made for the Gateway Service). Tetrate Enterprise Envoy Gateway (TEG) is then available by name rather than IP, and you can filter/route on hostname using the listener.hostname fields in Gateway and the hostnames field in HTTPRoute.
  2. configure & test rate limiting for your app
  3. configure & test authentication for your app
  4. Enable TLS
  5. If you're on AWS, use an NLB rather than CLB to front TEG's Envoys. Watch the Tetrate site for a how-to blog on this soon!