Access AWS Lambda with a service account
Associate an IAM role with a gateway proxy service account, and configure kgateway to use that service account to access AWS Lambda.
About
Amazon Web Services (AWS) offers the ability to associate an IAM role with a Kubernetes service account, also known as creating an IRSA. Kgateway supports discovering and invoking AWS Lambda functions by using an IRSA. For more information, see the AWS documentation.
In this guide, you follow these steps:
AWS resources:
- Associate your EKS cluster with an IAM OIDC provider
- Create an IAM policy that allows interactions with Lambda functions
- Create an IAM role that associates the IAM policy with the gateway proxy service account (an IRSA)
- Deploy the Amazon EKS Pod Identity Webhook to your cluster
- Create a Lambda function for testing
Kgateway resources:
- Install kgateway
- Annotate the gateway proxy service account with the IRSA
- Set up routing to your function by creating
Upstream
andHTTPRoute
resources
Configure AWS IAM resources
Save your AWS details, and create an IRSA for the gateway proxy pod to use.
-
Save the region where your Lambda functions exist, the region where your EKS cluster exists, your cluster name, and the ID of the AWS account.
export AWS_LAMBDA_REGION=<lambda_function_region> export AWS_CLUSTER_REGION=<cluster_region> export CLUSTER_NAME=<cluster_name> export AWS_ACCOUNT_ID=<account_id>
-
Check whether your EKS cluster has an OIDC provider.
export OIDC_PROVIDER=$(aws eks describe-cluster --name ${CLUSTER_NAME} --region ${AWS_CLUSTER_REGION} --query "cluster.identity.oidc.issuer" --output text | sed -e "s/^https:\/\///") echo $OIDC_PROVIDER
- If an OIDC provider in the format
oidc.eks.<region>.amazonaws.com/id/<cluster_id>
is returned, continue to the next step. - If an OIDC provider is not returned, follow the AWS documentation to Create an IAM OIDC provider for your cluster, and then run this command again to save the OIDC provider in an environment variable.
- If an OIDC provider in the format
-
Create an IAM policy to allow access to the following four Lambda actions. Note that the permissions to discover and invoke functions are listed in the same policy. In a more advanced setup, you might separate discovery and invocation permissions into two IAM policies.
cat >policy.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lambda:ListFunctions", "lambda:InvokeFunction", "lambda:GetFunction", "lambda:InvokeAsync" ], "Resource": "*" } ] } EOF aws iam create-policy --policy-name lambda-policy --policy-document file://policy.json
-
Use an IAM role to associate the policy with the Kubernetes service account for the HTTP gateway proxy, which assumes this role to invoke Lambda functions. For more information about these steps, see the AWS documentation.
- Create the following IAM role. Note that the service account name
http
in thekgateway-system
namespace is specified, because in later steps you create an HTTP gateway namedhttp
.cat >role.json <<EOF { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "${OIDC_PROVIDER}:sub": [ "system:serviceaccount:kgateway-system:http" ] } } } ] } EOF aws iam create-role --role-name lambda-role --assume-role-policy-document file://role.json
- Attach the IAM role to the IAM policy. This IAM role for the service account is known as an IRSA.
aws iam attach-role-policy --role-name lambda-role --policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/lambda-policy
- Verify that the policy is attached to the role.
aws iam list-attached-role-policies --role-name lambda-role
{ "AttachedPolicies": [ { "PolicyName": "lambda-policy", "PolicyArn": "arn:aws:iam::111122223333:policy/lambda-policy" } ] }
- Create the following IAM role. Note that the service account name
Deploy the Amazon EKS Pod Identity Webhook
Before you install kgateway, deploy the Amazon EKS Pod Identity Webhook, which allows pods’ service accounts to use AWS IAM roles. When you create the kgateway proxy in the next section, this webhook mutates the proxy’s service account so that it can assume your IAM role to invoke Lambda functions.
-
In your EKS cluster, install cert-manager, which is a prerequisite for the webhook.
wget https://github.com/cert-manager/cert-manager/releases/download/v1.12.4/cert-manager.yaml kubectl apply -f cert-manager.yaml
-
Verify that all cert-manager pods are running.
kubectl get pods -n cert-manager
-
Deploy the Amazon EKS Pod Identity Webhook.
kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/auth.yaml kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/deployment-base.yaml kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/mutatingwebhook.yaml kubectl apply -f https://raw.githubusercontent.com/solo-io/workshops/refs/heads/master/gloo-gateway/1-18/enterprise/lambda/data/steps/deploy-amazon-pod-identity-webhook/service.yaml
-
Verify that the webhook deployment completes.
kubectl rollout status deploy/pod-identity-webhook
Install kgateway
Be sure that you deployed the Amazon EKS Pod Identity Webhook to your cluster first before you continue to install kgateway.
-
Deploy the Kubernetes Gateway API CRDs.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0 /standard-install.yaml
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0 /experimental-install.yaml
-
Deploy the kgateway CRDs by using Helm.
helm upgrade -i --create-namespace --namespace kgateway-system --version v2.0.4
kgateway-crds oci://cr.kgateway.dev/kgateway-dev/charts/kgateway-crds
- Install kgateway by using Helm. Choose the [data plane gateway proxy](
/docs/2.0.x/about/proxies#supported) that you want to use, such as kgateway for API ingress or agentgateway for AI use cases.
helm upgrade -i --namespace kgateway-system --version v2.0.4
kgateway oci://cr.kgateway.dev/kgateway-dev/charts/kgateway</code></pre></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0">
<button
class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50"
title="Copy code"
>
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
</button>
</div>
</div>
<ol start="4">
<li>
<p>Make sure that <code>kgateway</code> is running.</p>
<div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code">
<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">kubectl get pods -n kgateway-system</span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0">
<button
class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50"
title="Copy code"
>
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
</button>
</div>
</div>
<p>Example output:</p>
<div class="hextra-code-block hx-relative hx-mt-6 first:hx-mt-0 hx-group/code">
<div><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-console" data-lang="console"><span class="line"><span class="cl"><span class="go">NAME READY STATUS RESTARTS AGE
</span></span></span><span class="line"><span class="cl"><span class="go">kgateway-5495d98459-46dpk 1/1 Running 0 19s
</span></span></span></code></pre></div></div><div class="hextra-code-copy-btn-container hx-opacity-0 hx-transition group-hover/code:hx-opacity-100 hx-flex hx-gap-1 hx-absolute hx-m-[11px] hx-right-0 hx-top-0">
<button
class="hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50"
title="Copy code"
>
<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>
</button>
</div>
</div>
</li>
</ol>
## Annotate the gateway proxy service account {#annotate}
1. Create a GatewayParameters resource to specify the `eks.amazonaws.com/role-arn` IRSA annotation for the gateway proxy service account.
```yaml
kubectl apply -f- <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayParameters
metadata:
name: http-lambda
namespace: kgateway-system
spec:
kube:
serviceAccount:
extraAnnotations:
eks.amazonaws.com/role-arn: arn:aws:iam::${AWS_ACCOUNT_ID}:role/lambda-role
EOF
-
Update the http
Gateway resource to add a reference to the http-lambda
GatewayParameters.
kubectl apply -f- <<EOF
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: http
namespace: kgateway-system
annotations:
spec:
gatewayClassName: kgateway
infrastructure:
parametersRef:
name: http-lambda
group: gateway.kgateway.dev
kind: GatewayParameters
listeners:
- protocol: HTTP
port: 8080
name: http
allowedRoutes:
namespaces:
from: All
EOF
-
Check the status of the gateway to make sure that your configuration is accepted. Note that in the output, a NoConflicts
status of False
indicates that the gateway is accepted and does not conflict with other gateway configuration.
kubectl get gateway http -n kgateway-system -o yaml
-
Verify that the http
service account has the eks.amazonaws.com/role-arn: arn:aws:iam::${AWS_ACCOUNT_ID}:role/lambda-role
annotation.
kubectl describe serviceaccount http -n kgateway-system
Create a Lambda function
Create an AWS Lambda function to test kgateway routing.
-
Log in to the AWS console and navigate to the Lambda page.
-
Click the Create Function button.
-
Name the function echo
and click Create function.
-
Replace the default contents of index.mjs
with the following Node.js function, which returns a response body that contains exactly what was sent to the function in the request body.
export const handler = async(event) => {
const response = {
statusCode: 200,
body: `Response from AWS Lambda. Here's the request you just sent me: ${JSON.stringify(event)}`
};
return response;
};
-
Click Deploy.
Set up routing to your function
Create Backend
and HTTPRoute
resources to route requests to the Lambda function.
-
Create a Backend resource that references the AWS region, ID of the account that contains the IAM role, and echo
function that you created.
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: Backend
metadata:
name: lambda
namespace: kgateway-system
spec:
type: AWS
aws:
region: ${AWS_LAMBDA_REGION}
accountId: "${AWS_ACCOUNT_ID}"
lambda:
functionName: echo
EOF
-
Create an HTTPRoute resource that references the lambda
Backend.
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: lambda
namespace: kgateway-system
spec:
parentRefs:
- name: http
namespace: kgateway-system
rules:
- matches:
- path:
type: PathPrefix
value: /echo
backendRefs:
- name: lambda
namespace: kgateway-system
group: gateway.kgateway.dev
kind: Backend
EOF
-
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
kubectl port-forward deployment/http -n kgateway-system 8080:8080
-
Confirm that kgateway correctly routes requests to Lambda by sending a curl request to the echo
function. Note that the first request might take a few seconds to process, because the AWS Security Token Service (STS) credential request must be performed first. However, after the credentials are cached, subsequent requests are processed more quickly.
curl $INGRESS_GW_ADDRESS:8080/echo -d '{"key1":"value1", "key2":"value2"}' -X POST
curl localhost:8080/echo -d '{"key1":"value1", "key2":"value2"}' -X POST
Example response:
{"statusCode":200,"body":"Response from AWS Lambda. Here's the request you just sent me: {\"key1\":\"value1\",\"key2\":\"value2\"}"}%
At this point, kgateway is routing directly to the echo
Lambda function using an IRSA!
Cleanup
You can remove the resources that you created in this guide.
Resources for the echo
function
-
Delete the lambda
HTTPRoute and lambda
Backend.
kubectl delete HTTPRoute lambda -n kgateway-system
kubectl delete Backend lambda -n kgateway-system
-
Use the AWS Lambda console to delete the echo
test function.
IRSA authorization (optional)
If you no longer need to access Lambda functions from kgateway:
-
Delete the GatewayParameters resources.
kubectl delete GatewayParameters http-lambda -n kgateway-system
-
Remove the reference to the http-lambda
GatewayParameters from the http
Gateway.
kubectl apply -f- <<EOF
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: http
namespace: kgateway-system
spec:
gatewayClassName: kgateway
listeners:
- protocol: HTTP
port: 8080
name: http
allowedRoutes:
namespaces:
from: All
EOF
-
Delete the pod identity webhook.
kubectl delete deploy pod-identity-webhook
-
Remove cert-manager.
kubectl delete -f cert-manager.yaml -n cert-manager
kubectl delete ns cert-manager
-
Delete the AWS IAM resources that you created.
aws iam detach-role-policy --role-name lambda-role --policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/lambda-policy
aws iam delete-role --role-name lambda-role
aws iam delete-policy --policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/lambda-policy