Please note that this workshop has been archived and is not actively maintained. On September 30, 2026, AWS will discontinue support for AWS App Mesh. For more information, visit this blog post.
So first thing we need to do is to edit our K8S Namespace to include a label that is used by the Virtual Gateway we are about to create.
kubectl label namespace appmesh-workshop-ns gateway=ingress-gw
Let’s now create our Virtual Gateway manifest file
# Create Virtual Service yaml file
cat <<EOF > ~/environment/eks-scripts/app-mesh-virtual-gateway.yml
---
apiVersion: v1
kind: Service
metadata:
name: ingress-gw
namespace: appmesh-workshop-ns
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-internal: (http://service.beta.kubernetes.io/aws-load-balancer-internal:) "true"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8088
name: http
selector:
app: ingress-gw
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-gw
namespace: appmesh-workshop-ns
spec:
replicas: 2
selector:
matchLabels:
app: ingress-gw
template:
metadata:
labels:
app: ingress-gw
spec:
containers:
- name: envoy
image: 840364872350.dkr.ecr.$AWS_REGION.amazonaws.com/aws-appmesh-envoy:v1.16.1.1-prod
ports:
- containerPort: 8088
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: VirtualGateway
metadata:
name: ingress-gw
namespace: appmesh-workshop-ns
spec:
namespaceSelector:
matchLabels:
gateway: ingress-gw
podSelector:
matchLabels:
app: ingress-gw
listeners:
- portMapping:
port: 8088
protocol: http
---
apiVersion: appmesh.k8s.aws/v1beta2
kind: GatewayRoute
metadata:
name: gateway-route-eks
namespace: appmesh-workshop-ns
spec:
httpRoute:
match:
prefix: "/eks/"
action:
target:
virtualService:
virtualServiceRef:
name: nodejs
---
EOF
If you take a close look at the previous manifest file, you will notice we added one GatewayRoute with a single route for path /eks. In practical terms this means any requests that arrive at the NLB with path /eks will get rerouted to the Virtual Service nodeJS.
Let’s see if it works! We have an EC2 instance sitting inside our VPC but is not part of our EKS cluster.
Connect to the EC2 instance in order to test reachability from external requests to the mesh using the virtual gateway ingress
EXTERNAL_EC2=$(aws ec2 describe-instances --filters Name=tag:Usage,Values=ExternalEC2Instance | jq -r '.Reservations[].Instances[].InstanceId')
aws ssm start-session --target $EXTERNAL_EC2
Starting session with SessionId: xxxxx-03f74a1b6fabf65d4
We add the Kube context for EKS connectivity
aws eks --region us-west-2 update-kubeconfig --name appmesh-workshop
Added new context arn:aws:eks:xxxxx:xxxxxxx:cluster/appmesh-workshop to /home/ssm-user/.kube/config
And finally, let’s get the FQDN of the NLB that was created as part of the K8s Service of type LoadBalancer.
NLB_ENDPOINT=$(kubectl get service -n appmesh-workshop-ns -o json | jq -r ".items[].status.loadBalancer.ingress[].hostname")
Let’s try to connect
curl -v $NLB_ENDPOINT/eks/
You should receive a response similar to the one below:
* Trying 10.0.101.45...
* TCP_NODELAY set
* Connected to a9919a32f014444d2bc66103e18ee816-8e1fb5e7a8e603d3.elb.us-west-2.amazonaws.com (10.0.101.45) port 80 (#0)
> GET /eks/ HTTP/1.1
> Host: a9919a32f014444d2bc66103e18ee816-8e1fb5e7a8e603d3.elb.us-west-2.amazonaws.com
> User-Agent: curl/7.61.1
> Accept: */*
>
< HTTP/1.1 200 OK
< x-powered-by: Express
< content-type: text/plain; charset=utf-8
< content-length: 64
< etag: W/"40-usK7ZSptGiNHjPKT0n79jNRx8l8"
< date: Mon, 10 May 2021 16:57:06 GMT
< x-envoy-upstream-service-time: 3
< server: envoy
<
Node.js backend: Hello! from 10.0.101.93 in AZ-b commit c61db33
* Connection #0 to host a9919a32f014444d2bc66103e18ee816-8e1fb5e7a8e603d3.elb.us-west-2.amazonaws.com left intact