Skip to content

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Page as Markdown

    

AWS EC2

Route traffic directly to AWS EC2 instances that the gateway proxy discovers dynamically by using tag-based filters. Endpoints are refreshed periodically and served to Envoy through EDS (Endpoint Discovery Service), so your routing stays up to date as instances start and stop.

Before you begin

  1. Follow the Get started guide to install kgateway.

  2. Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.

  3. Get the external address of the gateway and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  

Step 1: Enable EC2 discovery

Enable EC2 discovery by setting the controller.enableAwsEc2Discovery Helm value to true in your kgateway Helm chart.

  1. Optional: Get the values of your current installation.

    helm get values kgateway -n kgateway-system -o yaml > values.yaml
    open values.yaml
  2. Enable EC2 discovery by setting the controller.enableAwsEc2Discovery Helm value to true. The --reuse-values setting re-applies any Helm values that you previously set.

    helm upgrade -i kgateway oci://cr.kgateway.dev/kgateway-dev/charts/kgateway \
      --namespace kgateway-system \
      --reuse-values \
      --version v2.4.0-main \
      --set controller.enableAwsEc2Discovery=true
  3. Verify that the control plane pods are up and running.

    kubectl get pods -n kgateway-system

Step 2: Create an AWS EC2 instance

  1. Follow the AWS documentation to launch an EC2 instance with the following settings:

    • Use an Amazon Linux image.
    • Allow inbound HTTP traffic on port 80 in the instance’s security group.
    • Add at least one tag that you later use to discover the instance, for example app: payments.
    • Create a key file so that you can later connect to your instance by using SSH.
  2. Save the AWS region that your EC2 instance is created in as an environment variable. Make sure to use the region name (for example, us-east-1), not an availability zone (for example, us-east-1b).

    export AWS_REGION=<aws-region>
  3. Connect to your EC2 instance.

  4. Start an HTTP server on the EC2 instance. You can use the HTTP server that is built into Python by default.

    sudo python3 -m http.server 80 &
  5. Verify that you can send requests to the local HTTP server.

    curl http://localhost/

    Example output:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Directory listing for /</title>
    </head>
    <body>
    <h1>Directory listing for /</h1>
    <hr>
    <ul>
    <li><a href=".bash_logout">.bash_logout</a></li>
    <li><a href=".bash_profile">.bash_profile</a></li>
    <li><a href=".bashrc">.bashrc</a></li>
    <li><a href=".ssh/">.ssh/</a></li>
    </ul>
    <hr>
    </body>
    </html>
    

Step 3: Configure AWS credentials

For the gateway proxy to discover and route traffic to the EC2 instance, you must configure the proxy with the required AWS credentials. You can choose between the following authentication methods:

  • Static AWS credentials: Store your AWS access key ID and secret access key in a Kubernetes secret.
  • Role assumption: Configure an IAM role that the gateway proxy assumes to get temporary credentials.

For static credentials, the IAM user must have at least ec2:DescribeInstances permissions. For role assumption, the IAM user must have sts:AssumeRole permissions and the role must have at least ec2:DescribeInstances permissions.

Use this method when your IAM user and EC2 instances are in the same AWS account and you want a simple setup. The ec2:DescribeInstances permission is attached directly to your IAM user, and the gateway proxy uses those credentials as-is to discover EC2 instances.

  1. Create the policy document and save the ARN in an environment variable. At a minimum, you must assign the ec2:DescribeInstances permission.

    export POLICY_ARN=$(aws iam create-policy \
      --policy-name kgateway-ec2-discovery \
      --policy-document '{
        "Version": "2012-10-17",
        "Statement": [
          {
            "Effect": "Allow",
            "Action": "ec2:DescribeInstances",
            "Resource": "*"
          }
        ]
      }' \
      --query 'Policy.Arn' \
      --output text)
    
    echo $POLICY_ARN
  2. Get your IAM username and attach the policy directly to your IAM user.

    export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
    export IAM_USERNAME=$(aws sts get-caller-identity --query 'Arn' --output text | cut -d'/' -f2)
    
    aws iam attach-user-policy \
      --user-name ${IAM_USERNAME} \
      --policy-arn $POLICY_ARN
  3. Create permanent AWS credentials for your user.

    eval $(aws iam create-access-key --user-name ${IAM_USERNAME} \
      --query 'AccessKey.[AccessKeyId,SecretAccessKey]' \
      --output text | \
      awk '{print "export AWS_ACCESS_KEY_ID="$1"\nexport AWS_SECRET_ACCESS_KEY="$2}')
    
    echo "AWS_ACCESS_KEY_ID $AWS_ACCESS_KEY_ID"
    echo "AWS_SECRET_ACCESS_KEY $AWS_SECRET_ACCESS_KEY"
  4. Create a Kubernetes secret that holds the credentials.

    kubectl apply -n kgateway-system -f - <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: aws-creds
    type: Opaque
    stringData:
      accessKey: "${AWS_ACCESS_KEY_ID}"
      secretKey: "${AWS_SECRET_ACCESS_KEY}"
    EOF

Step 4: Set up EC2 routing

Create a Backend resource that represents your EC2 instance and an HTTPRoute to route requests to it.

  1. Create a Backend resource that represents the EC2 instance. Set the tag that you added to your EC2 instance earlier in the ec2.filters field so that the gateway proxy can discover the instance. You can also choose to route traffic to the instance’s public or private IP address by using the addressType field. Note that if you choose a private address, your cluster must be in the same private network as the EC2 instance, such as in the same VPC.

    kubectl apply -n kgateway-system -f - <<EOF
    apiVersion: gateway.kgateway.dev/v1alpha1
    kind: Backend
    metadata:
      name: ec2-backend
    spec:
      type: AWS
      aws:
        region: ${AWS_REGION}
        auth:
          type: Secret
          secretRef:
            name: aws-creds
        ec2:
          port: 80
          addressType: PublicIP
          filters:
          - keyValue:
              key: app
              value: payments
    EOF
    Field Description
    ec2.portThe port on the EC2 instance to route to.
    ec2.addressTypePublicIP to route to the public IP address; PrivateIP to route to the private IP address.
    ec2.roleArnThe ARN of the IAM role to assume before listing instances. Required only when using role assumption.
    ec2.filtersTag-based filters to select EC2 instances. Only running instances that match all filters are included as endpoints.
  2. Create an HTTPRoute resource that references the ec2-backend Backend.

    kubectl apply -n kgateway-system -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: ec2-route
    spec:
      parentRefs:
      - name: http
        namespace: kgateway-system
      hostnames:
      - ec2.example
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: ec2-backend
          group: gateway.kgateway.dev
          kind: Backend
    EOF
  3. Verify that the Backend endpoint is discovered. The gateway proxy periodically calls ec2:DescribeInstances to refresh the list of running instances that match your filters.

    kubectl get backend ec2-backend -n kgateway-system -o yaml
  4. Send a request to the EC2 instance through the gateway proxy. Verify that the output equals the output that you saw earlier when you sent a request to the EC2 directly.

    curl http://$INGRESS_GW_ADDRESS:8080/ -H "host: ec2.example"

    Example output:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Directory listing for /</title>
    </head>
    <body>
    <h1>Directory listing for /</h1>
    <hr>
    <ul>
    <li><a href=".bash_logout">.bash_logout</a></li>
    <li><a href=".bash_profile">.bash_profile</a></li>
    <li><a href=".bashrc">.bashrc</a></li>
    <li><a href=".ssh/">.ssh/</a></li>
    </ul>
    <hr>
    </body>
    </html>
    

Cleanup

You can remove the resources that you created in this guide.

  1. Delete the HTTPRoute and Backend.

    kubectl delete httproute ec2-route -n kgateway-system
    kubectl delete backend ec2-backend -n kgateway-system
  2. Delete the AWS credentials secret.

    kubectl delete secret aws-creds -n kgateway-system
  3. Clean up the AWS IAM resources.

    aws iam detach-user-policy --user-name ${IAM_USERNAME} --policy-arn ${POLICY_ARN}
    aws iam delete-policy --policy-arn ${POLICY_ARN}
  4. Terminate the EC2 instance from the AWS console.

Was this page helpful?