Containers

Introducing Ingress support in AWS App Mesh

AWS App Mesh is a fully managed service mesh that provides application-level networking to make it easy for your services to communicate with each other across multiple types of compute infrastructure. App Mesh standardizes how your services communicate, giving you end-to-end visibility and ensuring high availability for your applications.

Until now, App Mesh features have been applied to inter-service communications, or what is sometimes referred to as east-west traffic within your mesh. With the introduction of ingress support in App Mesh, you can now extend the configuration of App Mesh features to the north-south traffic coming into your mesh.

App Mesh enables a suite of capabilities vital to running services at scale, including intelligent traffic routing, security automation, enhanced resilience configuration, and observability solutions. App Mesh provides a fully managed control plane that you interact with to express configuration choices. It deploys a managed data plane alongside your application, which enforces that configuration. App Mesh uses the open source Envoy proxy to create this data plane, and exposes its rich feature set as part of its overall capabilities.

With its suite of features, App Mesh makes it easier to run services at scale by providing consistent visibility and network traffic controls. It removes the need to update service code to alter the flow of traffic through your application. The data plane can be easily configured to export metrics and tracing data to a wide variety of observability solutions.

Ingress Support in AWS App Mesh

If you are new to App Mesh, it may be helpful to review the User Guide with regard to its use and the various constructs which provide configuration for your mesh, such as virtual nodes and virtual services.

Ingress within App Mesh is configured through two new constructs in App Mesh, Virtual Gateways and Gateway Routes.

  • Virtual Gateways provide access for resources outside your mesh to resources inside your mesh
  • Gateway Routes specify the routing rules for inbound traffic to virtual services within your mesh

These constructs are the basic building blocks for establishing sophisticated ingress configuration for your service meshes. A virtual gateway is affiliated with a specific mesh, and each virtual gateway can have one or more gateway routes associated with it.

The diagram below depicts the logical flow of traffic through the mesh with a virtual gateway and two gateway routes defined. Traffic is configured to route to one of two virtual services through the gateway routes, and eventually on to virtual nodes. These virtual nodes represent your application services.

Drilling down into this example, traffic flows on the wire from the internet-facing load balancer and into the Envoy proxy acting as the gateway. From there it’s routed through the mesh (optionally including virtual services and virtual routers) to a destination virtual node, landing with your application services based upon your configuration.

Working with Ingress Gateways in AWS App Mesh

Above you see a visualization of the new App Mesh virtual gateway and gateway route constructs. In this section, we’ll describe the elements that go into its configuration.

The virtual gateway configuration specifies listeners for the expected inbound traffic. For example, assume that the application is configured such that the virtual gateway is listening on port 9080. The traffic from outside the mesh is intercepted by an Envoy instance running at port 9080 in the virtual gateway, and upon receiving a request it forwards traffic further into the mesh. Where traffic is forwarded is based upon the configuration of one or more gateway routes.

Gateway routes are affiliated with virtual gateways in a mesh. They contain route configuration elements, similar to App Mesh virtual routers. Gateway routes can be configured for HTTP, HTTP2, or gRPC traffic, and the routes are specified using match criteria. This criteria is path-based for HTTP and HTTP2 traffic, or service name-based for gRPC.

Using gateway route specifications you describe the logical traffic flow into and through your application in the mesh. Gateway routes specify which virtual service traffic should be sent to based upon their matching criteria. In turn, virtual services logically forward traffic to virtual routers, which contain route elements to drive traffic toward the correct virtual node and eventually your application endpoints within your cluster.

For example, an application may have different services deployed as part of a RESTful API backend, each one corresponding to a specific path. HTTP traffic destined for /paths/foo would arrive at the virtual gateway and be routed through an HTTP gateway route to a virtual service. That virtual service would contain a virtual router with additional HTTP path-based routes configured, ultimately sending traffic to a foo virtual node representing a backend service deployed in your cluster.

In the following sections, we will show the specific details of this configuration using Amazon ECS and Amazon EKS. We also include one of the App Mesh features referenced above, encryption with TLS. This can be configured very simply in AWS App Mesh, either through its integration with AWS Certificate Manager (ACM) or manually. When configured, the proxies will negotiate and terminate TLS for your application services. We show this integration only in the Amazon ECS walkthrough for overall brevity, but it’s equally supported with Amazon EKS. For more information on App Mesh and TLS support, see the App Mesh documentation.

Note when using ACM, certificates that are nearing the end of their validity are automatically renewed, and App Mesh will automatically distribute the renewed certificates. This removes the burden of monitoring certificate lifecycles and can help prevent potential outages. See managed renewal and deployment in the ACM documentation for more information.

Walkthrough demo application overview

Color App is the demo application we use below. It is very simple by design, with the goal of showing you how to use App Mesh by example without the application itself becoming a distraction. It is used throughout the AWS App Mesh Examples GitHub repository, so you can explore the content there and maintain context with these demos. In fact, the following walkthroughs are already in the examples repo for your reference.

Color App returns a color name as a string, based upon a color value set in the request header. It consists of two services, a frontend gateway service that accepts inbound traffic from a Network Load Balancer, in turn routing the traffic to one of any number of backend colorteller instances. Each colorteller instance is configured to return a specific color string.

Below you can see Color App deployed with App Mesh. With this configuration, you are able to take advantage of App Mesh features including Ingress support. Here, a gateway route is defined to match on header values and route traffic accordingly, as the application currently does. In addition, a gateway route is defined which matches on path values as well. Not only was it very simple to add this feature without needing a new version of the frontend service, we’re also able to deprecate the frontend and remove it altogether.

Hands-on walkthrough

The following walkthroughs deploy Color App to a cluster running within AWS along with the required objects to run the application within AWS App Mesh. You can choose between using Amazon ECS or Amazon EKS, or run through both.

As part of the application deployment, a virtual gateway is configured as described above along with virtual nodes, virtual services, and virtual routers. Gateway routes are specified for HTTP traffic routing based upon path values. This allows us to remove the frontend gateway service and leverage the ingress configuration to get requests to the right backend services.

These walkthroughs can be found in the App Mesh examples repository on GitHub. Start by cloning a local copy of the repository.

git clone https://github.com/aws/aws-app-mesh-examples.git
cd aws-app-mesh-examples

To get started with either walkthrough, you’ll also need:

  • An AWS account, your account ID, and the aws CLI installed and configured for use in your development environment.
  • A Docker development environment and familiarity with using Docker.

ECS technical walkthrough

The following is a modified version of the “Configuring Ingress Gateway” walkthrough for Amazon ECS from the App Mesh Examples repo. Change directory into the walkthrough to get started.

cd walkthroughs/howto-ingress-gateway

In addition to the requirements above, you’ll also need jq installed. It can be installed from here.

The walkthrough uses AWS CloudFormation and is scripted for convenience. To facilitate the scripts, export these environment variables that will be used in the following steps to deploy your application and mesh.

Note you will need a keypair stored in AWS. You can use an existing key, or create one expressly for this walkthrough:

aws ec2 create-key-pair --key-name color-app | jq -r .KeyMaterial > ~/.ssh/color-app.pem
chmod go-r ~/.ssh/color-app.pem
 export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')
export AWS_DEFAULT_REGION=<AWS region where you wish to deploy the demo, e.g. us-west-2>
export KEY_PAIR_NAME=<color-app or your SSH key pair stored in AWS>
export ENVIRONMENT_NAME=AppMeshIngressExample
export MESH_NAME=ColorApp-Ingress
export ENVOY_IMAGE=<get the latest from https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html>
export SERVICES_DOMAIN="default.svc.cluster.local"
export COLOR_TELLER_IMAGE_NAME="howto-ingress/colorteller"

As mentioned above, this walkthrough includes AWS App Mesh’s integration with ACM. Before adding the TLS configuration during mesh creation, you will need to generate a certificate. To do this, follow the Step 3 instructions in the example repo, then return here and continue. Note, there is a monthly fee associated with AWS Certificate Manager Private Certificate Authority. Only use this integration if you would like to explore this feature and are sure of its cost. For more information, see AWS Certificate Manager Pricing.

Now you can request a certificate for App Mesh to use. Do this using the aws CLI and export the resource name in an environment variable. This will get picked up by the scripts in the next steps.

export CERTIFICATE_ARN=`aws acm request-certificate --domain-name "*.${SERVICES_DOMAIN}" --certificate-authority-arn ${ROOT_CA_ARN} --query CertificateArn --output text`     

Create the Color App infrastructure

With the environment variables all set up, you can run the series of scripts to build out the environment. These scripts use CloudFormation templates, which are dynamically populated with the environment variables exported above. These are used to create resources such as a VPC, an ECS Cluster, and an ECR Repository. The final step is to build the container image locally and push it to Amazon ECR.

If you’d like to review the CloudFormation templates being used, you will find them along with the scripts in the walkthroughs/howto-ingress-gateway/infrastructure directory within the examples repository.

# Create the VPC, ECS Cluster and ECR repositories
./infrastructure/vpc.sh
# Deploy ECS Cluster and ECR repositories
./infrastructure/ecs-cluster.sh
./infrastructure/ecr-repositories.sh
# Build and push the colorteller container image
GO_PROXY=direct ./src/colorteller/deploy.sh

Review mesh components

Now that your environment is built, the next step is to create the mesh and its components. The Color App has four colorteller services which return their respective colors (black, red, white, blue). Each of these four services are represented in the mesh as virtual nodes. Two virtual services are defined to provide access to the virtual nodes based upon routing criteria. The virtual services receive external traffic via the virtual gateway and its gateway routes.

The virtual gateway spec contains configuration for listeners as well as TLS.

{
    "spec": {
      "listeners": [
        {
          "portMapping": {
            "port": 9080,
            "protocol": "http"
          },
          "tls": {
              "mode": "STRICT",
              "certificate": {
                  "acm": {
                      "certificateArn": $CERTIFICATE_ARN
                  }
              }
          }
        }
      ]
    }
}

The gateway routes specify match criteria based on the prefixes of /color1 and /color2. The configuration includes the route prefix and the virtual service target action. Here is a an example of the /color1 gateway route spec:

{
"spec": {
    "httpRoute" : {
        "match" : {
            "prefix" : "/color1"
        },
        "action" : {
            "target" : {
                "virtualService": {
                    "virtualServiceName": $VIRTUALSERVICE_NAME
                }
            }
        }
    }
}
}

Each of the virtual services mentioned above send traffic on to virtual routers, which in turn route the traffic matching on the prefix /tell to the virtual nodes (the color teller ECS services).

{
    "spec": {
        "httpRoute": {
            "action": {
                "weightedTargets": [
                    {
                        "virtualNode": "colorteller-white-vn",
                        "weight": 1
                    },
                    {
                        "virtualNode": "colorteller-blue-vn",
                        "weight": 1
                    }
                ]
            },
            "match": {
                "prefix": "/tell"
            }
        }
    }
}

For the purposes of demonstration, these routes are configured with weighted targets to return the color values equally in a round-robin fashion. You may use the same mechanism for controlled deployments (e.g. blue/green deployment), or to otherwise easily control the flow of traffic to your backend services.

Create the mesh and deploy services

With the configuration in place from the virtual gateway all the way through to the virtual nodes (which represent the deployed ECS services), you can now create the mesh and deploy all of its components.

# Create and deploy the mesh
./mesh/mesh.sh up

Once the mesh is created along with its application components, you can now deploy the ECS colorteller services. These services will be deployed in the ECS cluster that was built earlier. To register the task definitions used when deploying these services, the ProxyConfiguration property is set to type ‘APPMESH’ and environment variables are set to identify the mesh.

Here is a snippet of what those values look like:

      ProxyConfiguration:
        Type: 'APPMESH'
        ContainerName: 'envoy'
       Environment:
            - Name: 'APPMESH_VIRTUAL_NODE_NAME'
              Value: !Sub 'mesh/${AppMeshMeshName}/virtualNode/colorteller-red-vn'

Now that we’ve briefly explained how ECS services deploys into the mesh, it’s time to deploy. When the script completes, it will print out the endpoint for access to the deployed application.

# Deploy the ecs colorteller services
./infrastructure/ecs-service.sh

After a few minutes, the applications will be deployed to ECS and registered in the mesh. Store the endpoint of the virtual gateway’s Network Load Balancer in an environment variable named COLORAPP_ENDPOINT.

export COLORAPP_ENDPOINT=<your_https_colorApp_endpoint e.g. https://howto-Publi-55555555.us-west-2.elb.amazonaws.com>

With everything up and running, you can test out the application by sending requests to the color1 endpoint. The response will contain either ‘white’ or ‘blue’, as these are the virtual nodes that are the targets for the colorteller-1 virtual service. Run a few curls and test it.

curl -k "${COLORAPP_ENDPOINT}/color1/tell"

Next, issue requests to the color2 endpoint and verify you receive either ‘red’ or ‘black’ as the response.

curl -k "${COLORAPP_ENDPOINT}/color2/tell"

When you’re done testing the demo environment, it can be cleaned up by issuing the following commands.

Delete the CloudFormation stacks:

aws cloudformation delete-stack --stack-name $ENVIRONMENT_NAME-ecs-service
aws cloudformation delete-stack --stack-name $ENVIRONMENT_NAME-ecs-cluster
aws ecr delete-repository --force --repository-name $COLOR_TELLER_IMAGE_NAME
aws cloudformation delete-stack --stack-name $ENVIRONMENT_NAME-ecr-repositories
aws cloudformation delete-stack --stack-name $ENVIRONMENT_NAME-vpc

Delete the mesh:

./mesh/mesh.sh down

And finally delete the certificates.

aws acm delete-certificate --certificate-arn $CERTIFICATE_ARN
aws acm-pca update-certificate-authority --certificate-authority-arn $ROOT_CA_ARN --status DISABLED
aws acm-pca delete-certificate-authority --certificate-authority-arn $ROOT_CA_ARN

EKS technical walkthrough

The following is a modified version of the “Configuring Ingress Gateway” walkthrough for Kubernetes from the App Mesh examples repo. Change directory into the walkthrough to get started.

cd walkthroughs/howto-k8s-ingress-gateway

The walkthrough is also scripted for convenience. To facilitate the scripts, export these environment variables that will be used in the following steps to deploy your application and mesh.

export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')
export AWS_DEFAULT_REGION=<AWS region where you wish to deploy the demo, e.g. us-west-2>
export ENVOY_IMAGE=<get the latest from https://docs.aws.amazon.com/app-mesh/latest/userguide/envoy.html>

As part of the application deployment, a virtual gateway is configured as described above, with gateway routes specifying HTTP traffic routing based upon path values to one of two virtual services. The virtual services, in turn, send application traffic along to be routed based upon either header- or path-based values.

In addition to the requirements above, you’ll also need:

  • kubectl, helm, and eksctl installed

For information on setting up an Amazon EKS cluster, see the EKS getting started guide. There are also some notes on software installation.

Regardless of other configuration options, ensure that you create your cluster with the appMesh add-on policy. For example:

cat <<-EOF > ~/demo-cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
    name: demo-cluster
    region: ${AWS_DEFAULT_REGION}
    version: '1.16'

managedNodeGroups:
  - name: demo-mng-small
    instanceType: t3.small
    minSize: 2
    maxSize: 4
    desiredCapacity: 3
    labels: {role: worker}
    iam:
      withAddonPolicies:
        appMesh: true
EOF
        
eksctl create cluster -f ~/demo-cluster.yaml

Once your cluster is created, install the AWS App Mesh Controller for Kubernetes. This is an open source Kubernetes controller that helps manage App Mesh resources within Kubernetes. The controller monitors your cluster for changes in custom resources which it provides, and reflects those changes in the App Mesh service within AWS.

Using the App Mesh controller greatly simplifies App Mesh use in Kubernetes, allowing you to work with App Mesh resources the same way you work with native Kubernetes objects such as Deployments and Services. Additionally, the controller will automatically inject the required Envoy proxy containers in your pods, making the App Mesh configuration in your clusters seamless.

To install the App Mesh Controller, use the Helm chart provided by EKS Charts. For detailed App Mesh controller installation instructions for a variety of environments, see the App Mesh controller’s chart documentation. In this example, we’re following the instructions for using a cluster in Amazon EKS with IAM Roles for Service Accounts (IRSA).

First create the IRSA for appmesh-controller. To learn more about IRSA, see the Amazon EKS documentation.

export CLUSTER_NAME=<eks-cluster-name, e.g. demo-cluster>
export AWS_REGION=<aws-region e.g. us-west-2>

eksctl utils associate-iam-oidc-provider --region=$AWS_REGION \
    --cluster=$CLUSTER_NAME \
    --approve

eksctl create iamserviceaccount --cluster $CLUSTER_NAME \
    --namespace appmesh-system \
    --name appmesh-controller \
    --attach-policy-arn  arn:aws:iam::aws:policy/AWSCloudMapFullAccess,arn:aws:iam::aws:policy/AWSAppMeshFullAccess \
    --override-existing-serviceaccounts \
    --approve

Next, create the namespace for the controller and install the Helm chart.

kubectl create ns appmesh-system

helm repo add eks https://aws.github.io/eks-charts

helm upgrade -i appmesh-controller eks/appmesh-controller \
    --namespace appmesh-system \
    --set region=$AWS_REGION \
    --set serviceAccount.create=false \
    --set serviceAccount.name=appmesh-controller

You will see output regarding the Helm chart installation. Check the version of the controller to ensure installation was successful.

kubectl get deployment -n appmesh-system appmesh-controller -o json | jq -r ".spec.template.spec.containers[].image" | cut -f2 -d ':'|tail -n1

You should see a version of v1.0.0 or higher. You can examine the objects in the appmesh-system namespace and observe the small set of App Mesh custom resource definitions (CRDs).

kubectl get all -n appmesh-system
kubectl get crds | grep appmesh

From here, the demo deployment is scripted for you. The deploy.sh script will build the colorapp container image locally, tag the image, and push it to Amazon ECR. It will then deploy the application along with the App Mesh configuration to your cluster in a new howto-k8s-ingress-gateway namespace.

Above, you set a few environment variables which the deployment script requires. This includes the Envoy container image. The App Mesh controller will automatically inject Envoy proxy instances and manage them for you, but the container image needs to be specified. See the App Mesh user guide for further information.

Invoke the deployment script to build the colorteller image locally, push it to Amazon ECR, and deploy the mesh and application to your cluster.

./deploy.sh

You’ll see the output of the container image build and the deployment. When it’s complete, you can observe the objects that were created including those representing the App Mesh configuration constructs in the howto-k8s-ingress-gateway namespace.

kubectl get all -n howto-k8s-ingress-gateway

You can also walk through the various App Mesh resources that were created by the controller, either in the console or by using the aws CLI.

aws appmesh list-meshes
aws appmesh list-virtual-gateways --mesh-name howto-k8s-ingress-gateway
aws appmesh list-gateway-routes --mesh-name howto-k8s-ingress-gateway \
    --virtual-gateway-name ingress-gw_howto-k8s-ingress-gateway

To verify the application is deployed and App Mesh Ingress is working as configured, retrieve the gateway’s Network Load Balancer address and test it. This may take a few minutes to become fully available. Note you can either include the color in the header, or use the new path-based functionality.

GW_ENDPOINT=$(kubectl get svc ingress-gw -n howto-k8s-ingress-gateway --output jsonpath='{.status.loadBalancer.ingress[0].hostname}')

curl -H "color_header: red" ${GW_ENDPOINT}/headers ; echo;

curl -H "color_header: blue" ${GW_ENDPOINT}/headers ; echo;

curl ${GW_ENDPOINT}/paths/red ; echo;

curl ${GW_ENDPOINT}/paths/blue ; echo;

Invoke the following to clean up the demonstration resources.

kubectl delete -f _output

Next steps

From the above walkthroughs, you can see that adding a few simple elements to your App Mesh configuration provides robust and secure ingress routing to your application. These examples are fairly basic and we hope that you use them as a starting point for your own solutions.

Configuring your inbound application traffic with App Mesh virtual gateways and gateway routes enables a number of features for your entire in-cluster application stack. These include intelligent routing techniques, configuration to increase the scope of your application’s observability, and the application of resilience, security, and policy management features. For more hands-on examples of working with App Mesh, check out our examples project on Github.

Also, be sure to check out the AWS App Mesh documentation for details on working with the service as well as the App Mesh user guide, which provides sections on Getting Started, Best Practices, and Troubleshooting.

You can let us know what you think of this feature, review our roadmaps, and suggest new features on the AWS App Mesh Roadmap and the AWS Containers Roadmap, also hosted on GitHub.

Jesse Butler

Jesse Butler

Jesse is a Developer Advocate on the AWS Container Services team working on EKS, App Mesh and anything that can help successfully run software at scale. You can find him on Twitter at @jlb13.

Adam Keller

Adam Keller

Adam is a Developer Advocate on the AWS Container Services team working on all things containers. Reach out to him on twitter @realadamjkeller.