AWS ALB

In this guide you explore how to expose the kgateway proxy with an AWS application load balancer (ALB).

⚠️
The AWS Load Balancer Controller only supports the creation of an ALB through an Ingress Controller and not through the Kubernetes Gateway API. Because of this, you must create the ALB separately through an Ingress resource that connects it to the service that exposes your gateway proxy.

Before you begin

  1. Create or use an existing AWS account.
  2. Follow the Get started guide to install kgateway. You do not need to set up a Gateway as you create a custom Gateway as part of this guide.
  3. Follow the Sample app guide to deploy the httpbin sample app.

Step 1: Deploy gateway proxy resources

  1. Create a Gateway resource with an HTTP listener. You later pair this Gateway with an AWS ALB.

    kubectl apply -n kgateway-system -f- <<EOF
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: alb
    spec:
      gatewayClassName: kgateway
      listeners:
      - protocol: HTTP
        port: 8080
        name: http
        allowedRoutes:
          namespaces:
            from: All
    EOF
  2. Create DirectResponse and HTTPRoute resources to configure a custom healthcheck path on the gateway. In this example, you expose the /healthz path and configure it to always return a 200 HTTP response code by using the DirectResponse. Later, you configure the ALB to perform the health check against the /healthz path to determine if the Gateway is healthy.

    kubectl apply -f- <<EOF
    apiVersion: gateway.kgateway.dev/v1alpha1
    kind: DirectResponse
    metadata:
      name: httpbin-healthcheck-dr
      namespace: httpbin
    spec:
      status: 200
    ---
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-healthcheck
      namespace: httpbin
      labels:
        example: httpbin-route
    spec:
      parentRefs:
        - name: alb
          namespace: kgateway-system
      rules:
      - matches:
        - path:
            type: Exact
            value: /healthz
        filters:
        - type: ExtensionRef
          extensionRef:
           name: httpbin-healthcheck-dr
           group: gateway.kgateway.dev
           kind: DirectResponse
    EOF
  3. Create another HTTPRoute resource to expose the httpbin app on the albtest.com domain.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-alb
      namespace: httpbin
      labels:
        example: httpbin-route
    spec:
      parentRefs:
        - name: alb
          namespace: kgateway-system
      hostnames:
        - "albtest.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: httpbin
          port: 8000
    EOF

Step 2: Create an ALB with the AWS Load Balancer controller

  1. Save the name and region of your AWS EKS cluster and your AWS account ID in environment variables.

    export CLUSTER_NAME="<cluster-name>"
    export REGION="<region>"
    export AWS_ACCOUNT_ID=<aws-account-ID>
    export IAM_POLICY_NAME=AWSLoadBalancerControllerIAMPolicyNew
    export IAM_SA=aws-load-balancer-controller
  2. Create an AWS IAM policy and bind it to a Kubernetes service account.

    # Set up an IAM OIDC provider for a cluster to enable IAM roles for pods
    eksctl utils associate-iam-oidc-provider \
     --region ${REGION} \
     --cluster ${CLUSTER_NAME} \
     --approve
    
    # Fetch the IAM policy that is required for the Kubernetes service account
    curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.3/docs/install/iam_policy.json
    
    # Create the IAM policy
    aws iam create-policy \
     --policy-name ${IAM_POLICY_NAME} \
     --policy-document file://iam-policy.json
    
    # Create the Kubernetes service account
    eksctl create iamserviceaccount \
     --cluster=${CLUSTER_NAME} \
     --namespace=kube-system \
     --name=${IAM_SA} \
     --attach-policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${IAM_POLICY_NAME} \
     --override-existing-serviceaccounts \
     --approve \
     --region ${REGION}
  3. Verify that the service account is created in your cluster.

    kubectl -n kube-system get sa aws-load-balancer-controller -o yaml
  4. Deploy the AWS Load Balancer Controller.

    kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller/crds?ref=master"
    
    helm repo add eks https://aws.github.io/eks-charts
    helm repo update
    helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
      -n kube-system \
      --set clusterName=${CLUSTER_NAME} \
      --set serviceAccount.create=false \
      --set serviceAccount.name=${IAM_SA}
  1. Use an Ingress resource to define your ALB. When you apply this resource, the AWS Load Balancer Controller creates the ALB in your account.

    kubectl apply -f- <<EOF
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      namespace: kgateway-system
      name: alb
      annotations:
        alb.ingress.kubernetes.io/scheme: internet-facing
        alb.ingress.kubernetes.io/target-type: instance
        alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
        alb.ingress.kubernetes.io/healthcheck-path: "/healthz"
    spec:
      ingressClassName: alb
      rules:
        - http:
            paths:
            - path: /
              pathType: Prefix
              backend:
                service:
                  name: alb
                  port:
                    number: 8080
    EOF
    ℹ️
    If you later change your Ingress resource configuration, you might need to delete and re-create your Ingress resource for AWS to pick up the changes.
  2. Review the load balancer in the AWS EC2 dashboard.

    1. Go to the AWS EC2 dashboard.
    2. In the left navigation, go to Load Balancing > Load Balancers.
    3. Find and open the ALB that was created for you, with a name such as k8s-gateway-alb-<hash>. Note that it might take a few minutes for the ALB to provision.
    4. On the Resource map tab, verify that the load balancer points to healthy EC2 targets in your cluster. For example, you can click on the target EC2 name to verify that the instance summary lists your cluster name.

Step 3: Test the ALB

  1. In the Details pane of the ALB, get the DNS name that was assigned to your ALB and save it as an environment variable.

    export INGRESS_GW_ADDRESS=<alb-dns-name>
  2. Send a request to the httpbin app. Verify that you get back a 200 HTTP response code.

    curl -vi http://$INGRESS_GW_ADDRESS:80/headers -H "host: albtest.com:80"

    Example output:

    ...
    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    

Cleanup

You can remove the resources that you created in this guide.
  1. Delete the Ingress, HTTPRoute, DirectResponse, and Gateway resources.

    kubectl delete ingress alb -n kgateway-system
    kubectl delete httproute httpbin-alb -n httpbin
    kubectl delete httproute httpbin-healthcheck -n httpbin
    kubectl delete directresponse httpbin-healthcheck-dr -n httpbin
    kubectl delete gateway alb -n kgateway-system
  2. Delete the AWS IAM resources that you created.

    aws iam delete-policy --policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${IAM_POLICY_NAME}
    eksctl delete iamserviceaccount --name=${IAM_SA} --cluster=${CLUSTER_NAME}
  3. Uninstall the Helm release for the aws-load-balancer-controller.

    helm uninstall aws-load-balancer-controller -n kube-system