Skip to content

Gateway Chaining

Gateway Chaining

Introduction

Gateway chaining involves forwarding traffic from one gateway listener directly to another gateway listener. Specifically, the LBC allows you to configure an NLB gateway listener and point it to an ALB gateway listener. Under the hood, this is implemented by using ALB target of NLB.

Using a chaining setup provides multiple benefits:

  • You can use the HTTP request-based routing features of the Application Load Balancer in combination with features that the Network Load Balancer supports.
  • Use of endpoint services (AWS PrivateLink)
  • Static IP for Application Load Balancer.
  • Serve TCP and HTTP traffic from a single endpoint.

Set up

This guide will walk you through setting up a chained Gateway.

ALB Setup

In the YAML below, we set up an ALB Gateway with an HTTP listener on port 80 and an HTTPS listener on port 443. These listeners forward traffic to an arbitrary backend service. It's important to note that the ALB Gateway is configured as an internal load balancer. Clients that wish to connect to the ALB Gateway must do so via the NLB Gateway we will set up next. While it's possible to use an internet-facing ALB Gateway where clients could communicate directly, in a chained setup the NLB Gateway always uses private IP addresses to communicate with the ALB Gateway.

# alb-gatewayclass.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: aws-alb-gateway-class
spec:
  controllerName: gateway.k8s.aws/alb
---
# my-alb-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: my-alb-gateway
  namespace: example-ns
spec:
  gatewayClassName: aws-alb-gateway-class
  infrastructure:
    parametersRef:
      kind: LoadBalancerConfiguration
      name: alb-lb-config
      group: gateway.k8s.aws
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
  - name: https
    protocol: HTTPS
    port: 443
    allowedRoutes:
      namespaces:
        from: Same
---
# lbconfig.yaml
apiVersion: gateway.k8s.aws/v1beta1
kind: LoadBalancerConfiguration
metadata:
  name: alb-lb-config
  namespace: example-ns
spec:
  listenerConfigurations:
    - protocolPort: HTTPS:443
      defaultCertificate: <my cert arn>
---
# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: my-http-app-route
  namespace: example-ns
spec:
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: my-alb-gateway
    sectionName: http
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: my-alb-gateway
    sectionName: https
  rules:
  - backendRefs:
    - name: echoserver
      port: 80

NLB Setup

In the YAML below, we set up an NLB Gateway with TCP listeners on ports 80 and 443. These listeners forward traffic to the ALB Gateway configured above. The NLB Gateway is configured as internet-facing to allow external clients to connect. The NLB will route traffic to the internal ALB using private IP addresses.

# nlb-gatewayclass.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: aws-nlb-gateway-class
spec:
  controllerName: gateway.k8s.aws/nlb
---
# my-nlb-gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: my-tcp-gateway
  namespace: example-ns
spec:
  gatewayClassName: aws-nlb-gateway-class
  infrastructure:
    parametersRef:
      group: gateway.k8s.aws
      kind: LoadBalancerConfiguration
      name: nlb-lb-config
  listeners:
  - name: unsecure
    protocol: TCP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
  - name: secure
    protocol: TCP
    port: 443
    allowedRoutes:
      namespaces:
        from: Same
---
# lbconfig.yaml
apiVersion: gateway.k8s.aws/v1beta1
kind: LoadBalancerConfiguration
metadata:
  name: nlb-lb-config
  namespace: example-ns
spec:
  scheme: internet-facing
---
# my-unsecure-tcproute.yaml
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: my-unsecure-app-route
  namespace: example-ns
spec:
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: my-tcp-gateway
    sectionName: unsecure
  rules:
  - backendRefs:
    - name: my-alb-gateway
      kind: Gateway
      port: 80
---
# my-secure-tcproute.yaml
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: my-secure-app-route
  namespace: example-ns
spec:
  parentRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: my-tcp-gateway
      sectionName: secure
  rules:
    - backendRefs:
        - name: my-alb-gateway
          kind: Gateway
          port: 443
---
# tg-configuration.yaml
apiVersion: gateway.k8s.aws/v1beta1
kind: TargetGroupConfiguration
metadata:
  name: example-tg-config
  namespace: example-ns
spec:
  targetReference:
    name: my-alb-gateway
    kind: Gateway
  routeConfigurations:
    - routeIdentifier:
        kind: TCPRoute
        namespace: example-ns
        name: my-unsecure-app-route
      targetGroupProps:
        healthCheckConfig:  
          healthCheckProtocol: HTTP
    - routeIdentifier:
        kind: TCPRoute
        namespace: example-ns
        name: my-secure-app-route
      targetGroupProps:
        healthCheckConfig:  
          healthCheckProtocol: HTTPS

Customizing the ALB Gateway target settings

Customizing the ALB Gateway, in the context as a target, works exactly the same way as customizing a Target Group based on a Kubernetes Service. The only caveat is that target groups of type ALB do not support attribute customization, this is an AWS limitation and not one imposed within the controller. For more information about customization, see the TargetGroupConfiguration CRD documentation.

In the example presented above, we have customized the target group that points to the ALB listener port on 443. In our example, this is required when forwarding traffic from the NLB to the ALB on listener port 443 as the ALB listener is expecting HTTPS traffic; even for health check traffic.

apiVersion: gateway.k8s.aws/v1beta1
kind: TargetGroupConfiguration
metadata:
  name: example-tg-config
  namespace: example-ns
spec:
  targetReference:
    name: my-alb-gateway
    kind: Gateway
  routeConfigurations:
    - routeIdentifier:
        kind: TCPRoute
        namespace: example-ns
        name: my-unsecure-app-route
      targetGroupProps:
        healthCheckConfig:  
          healthCheckProtocol: HTTP
    - routeIdentifier:
        kind: TCPRoute
        namespace: example-ns
        name: my-secure-app-route
      targetGroupProps:
        healthCheckConfig:  
          healthCheckProtocol: HTTPS

Cross namespace access

Chained Gateways support Reference Grants to support chaining Gateways in different namespaces. The Reference Grant must exist within the namespace of the ALB Gateway. The same semantics used for routes and reference grants apply to Gateway-based reference grants.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: example-reference-grant
  namespace: alb-gw-ns
spec:
  from:
  - group: gateway.networking.k8s.io
    kind: TCPRoute
    namespace: nlb-gw-ns
  to:
  - group: gateway.networking.k8s.io
    kind: Gateway

In this example, we are establishing a reference grant that allows TCPRoutes from the nlb-gw-ns namespace to attach any ALB Gateway in the alb-gw-ns namespace.