Containers

Enabling AWS X-Ray tracing for AWS App Runner service using AWS Copilot CLI

AWS Copilot CLI is an open-source command line interface that makes it easy for developers to build, release, and operate production-ready containerized workloads on AWS App Runner, Amazon Elastic Container Service (Amazon ECS), and AWS Fargate. Under the hood, Copilot uses AWS CloudFormation for provisioning and managing the underlying infrastructures on your behalf so that you can focus on your business logic and the architecture of your application.

AWS App Runner recently announced AWS X-Ray support as part of its observability suite. For more information, visit AWS Blog | Tracing an AWS App Runner service using AWS X-Ray with OpenTelemetry. With this release, you can send traces from your App Runner services without having to set up the required sidecars or agents yourself. You can trace your containerized applications in X-Ray by instrumenting applications with the AWS Distro for OpenTelemetry (ADOT).

AWS Copilot supports this feature from the day of launch. You can easily deploy an App Runner service with X-Ray tracing enabled by using Copilot CLI. If you are not yet familiar with AWS Copilot, there is a small section in step 1 that briefly introduces some Copilot terminologies. To learn more, you can also check out this introduction to AWS Copilot and, of course, the official Copilot documentation.

Solution overview

The following walkthrough demonstrates how to use AWS Copilot CLI to enable X-Ray tracing for App Runner services:

  • We will use an existing REST API application that interacts with an Amazon DynamoDB table as our example workload.
  • We will describe how you can deploy the application as an App Runner service through Copilot CLI, using a single command copilot init.
  • We will enable tracing on the service by simply adding two lines to your Copilot service manifest.

At the end of the following tutorial, you’ll get an architecture like the following diagram.

Prerequisites

Build and deploy a Python application on App Runner using Copilot CLI

1. Clone GitHub repo

$ git clone https://github.com/Lou1415926/movies-app

$ cd movies-app

In addition to the application code, the repository contains a copilot/ directory. In this folder, you can find:

  • copilot/api-svc/manifest.yml, a declarative infrastructure-as-code file that configures the service  “api-svc”.
  • copilot/api-svc/addons/moviesTable.yml: an AWS CloudFormation template that defines your DynamoDB table and its supporting resources.

If you are new to Copilot, the following are some of the terminologies to get familiar with.  Otherwise, feel free to skip to 2. Deploy a Copilot application.

  • Application: A group of related microservices, environments, and pipelines.
  • Service: A service can be an Amazon Elastic Container Service (Amazon ECS) service or, in today’s example, an App Runner service, and the surrounding resources to support it, such as an AWS Identify and Access Management (IAM) role for App Runner service to connect with the DynamoDB table and X-Ray.
  • Manifest: A declarative infrastructure-as-code file to configure the service that is stored in copilot/<service>.

In this walkthrough, we will use Copilot to build and push an image based on a prepared Dockerfile. The Dockerfile enables AWS Distro for OpenTelemetry auto instrumentation for the application. To learn more about how to instrument your own application, you can view documentation and examples provided by AWS Distro for OpenTelemetry.

The following is a snippet of the copilot/api-svc/manifest.yml:

# Your service name will be used in naming your resources like log groups, App Runner services, etc.
name: api-svc
# The "architecture" of the service you're running.
type: Request-Driven Web Service

image:
  # The name of the Docker image.
  build: Dockerfile
  # Port exposed through your container to route traffic to it.
  port: 8080

# http:
#   healthcheck:
#     path: /
#     healthy_threshold: 3
#     unhealthy_threshold: 5
#     interval: 10s
#     timeout: 5s

# Number of CPU units for the task.
cpu: 1024
# Amount of memory in MiB used by the task.
memory: 2048

# # Connect your App Runner service to your environment's VPC.
# network:
#   vpc:
#     placement: private

# NOTE: Uncomment this to enable tracing.
# observability:
#  tracing: awsxray

Note: X-Ray tracing configuration is commented out at this moment.

The DynamoDB table is configured in copilot/api-svc/addons/moviesTable.yml. When Copilot deploys a service, it picks up the CloudFormation templates from the addons/ folder and deploys those resources alongside the service.

2. Deploy a Copilot application

Note: If the Copilot binary is missing or is outdated, follow the Copilot installation guides to install or update it.

# Ensure you're in the root directory of the cloned repository
$ ls
CODE_OF_CONDUCT.md Config             LICENSE            app.py             load-data-script   templates
CONTRIBUTING.md    Dockerfile         README.md          copilot            requirements.txt

# Ensure you have v1.17.0 or later
$ copilot --version 
copilot version: v1.17.0

# Create a Copilot app and service.
$ copilot init --app movies-app --name api-svc --type "Request-Driven Web Service" --deploy

Copilot will deploy the application "movies-app", provision a "test" environment, and deploy the service "api-svc" of "movies-app" to the "test" environment. While deploying the resources, Copilot shows the progress on your terminal to keep you updated:

Manifest file for service api-svc already exists. Skipping configuration.
Ok great, we'll set up a Request-Driven Web Service named api-svc in application movies-app.

✔ Created the infrastructure to manage services and jobs under application movies-app.

✔ The directory copilot will hold service manifests for application movies-app.

✔ Manifest file for service api already exists at copilot/api-svc/manifest.yml, skipping writing it.
Your manifest contains configurations like your container size and port.

✔ Created ECR repositories for service api-svc.

✔ Linked account <Your AWS account ID> and region <Your AWS region> to application movies-app.

✔ Proposing infrastructure changes for the movies-app-test environment.
- Creating the infrastructure for the movies-app-test environment.            [create complete]  [90.5s]
  - An IAM Role for AWS CloudFormation to manage resources                    [create complete]  [16.4s]

✔ Created environment test in region us-east-1 under application movies-app.
Building your container image: docker build -t ...

# ~ snip ~

✔ Proposing infrastructure changes for stack movies-app-test-api-svc
- Creating the infrastructure for stack movies-app-test-api-svc                   [create complete]  [409.5s]
  - An IAM Role for App Runner to use on your behalf to pull your image from ECR  [create complete]  [14.6s]
  - An Addons CloudFormation Stack for your additional AWS resources              [create complete]  [67.8s]
    - An IAM ManagedPolicy for your service to access the moviesTable db          [create complete]  [12.5s]
    - An Amazon DynamoDB table for moviesTable                                    [create complete]  [33.4s]
  - An IAM role to control permissions for the containers in your service         [create complete]  [16.7s]
  - An App Runner service to run and manage your containers                       [create complete]  [311.7s]
✔ Deployed service api-svc.
Recommended follow-up action:
  - You can access your service at https://<Random string>.<Your AWS region>.awsapprunner.com over the internet.

After the deployment, you should be able to access the URL shown in the output.

Note: The X-Ray tracing is not enabled yet. We will do that later!

3. Check out the resources (optional)

Copilot provisioned all resources through CloudFormation, including the necessary IAM roles, the DynamoDB table, as well as the App Runner service named movies-app-test-api-svc.

From the App Runner console in your Region, you should be able to confirm that the service was created:

You can also go to the CloudFormation console to check out the resources that Copilot has provisioned:

To easily view the summary of your "api-svc" service’s configurations, use  copilot svc show:

$ copilot svc show --app movies-app --name api-svc
About

 Application movies-app
 Name api
 Type Request-Driven Web Service

Configurations

 Environment CPU (vCPU) Memory (MiB) Port
 ----------- ---------- ------------ ----
 test 1 2048 8080

Routes

 Environment URL
 ----------- ---
 test https://<Random string>.<Your AWS region>.awsapprunner.com

Variables

 Name Environment Value
 ---- ----------- -----
 COPILOT_APPLICATION_NAME test movies-app
 COPILOT_ENVIRONMENT_NAME " test
 COPILOT_SERVICE_NAME " api
 MOVIES_TABLE_NAME " movies-app-test-api-moviesTable

Enable X-Ray tracing for App Runner service

At this point, we have successfully deployed a working web application with AWS CoPilot running on AWS AppRunner. Now is the exciting time to enable X-Ray tracing!

1. Enable tracing from the manifest file

Open your local copilot/api/manifest.yml file:

# Enter the root directory of the cloned repository
$ cd movies-app

# Ensure you're in the root directory of the cloned repository
$ ls
CODE_OF_CONDUCT.md Config             LICENSE            app.py             load-data-script   templates
CONTRIBUTING.md    Dockerfile         README.md          copilot            requirements.txt

# Ensure you have v1.17.0 or later
$ copilot --version 
copilot version: v1.17.0

# Open the manifest file for your "api-svc" service
$ vi copilot/api-svc/manifest.yml

Uncomment these two lines in your copilot/api-svc/manifest.yml file:

observability:
    tracing: awsxray

so that a part of your manifest looks like this:

# Number of CPU units for the task.
cpu: 1024
# Amount of memory in MiB used by the task.
memory: 2048

# # Connect your App Runner service to your environment's VPC.
# network:
#   vpc:
#     placement: private

# NOTE: Uncomment this to enable tracing.
observability:      # <<< Uncomment this line.
 tracing: awsxray   # <<< Uncomment this line.

2. Deploy your service with the tracing configuration

$ copilot deploy --app movies-app --name api-svc

Only found one environment, defaulting to: test
Environment test is already on the latest version v1.8.0, skip upgrade.

# ~ snip ~

✔ Proposing infrastructure changes for stack movies-app-test-api-svc
- Updating the infrastructure for stack movies-app-test-api-svc            [update complete]  [240.3s]
  - An IAM role to control permissions for the containers in your service  [update complete]  [23.5s]
  - An App Runner service to run and manage your containers                [update complete]  [196.8s]
✔ Deployed service api-svc.
Recommended follow-up action:
  - You can access your service at https://<Random string>.<Your AWS region>.awsapprunner.com over the internet.

Copilot will update your service with the new configuration in your manifest, enabling X-Ray tracing for "api-svc" service through CloudFormation. You can check out the template in the CloudFormation console in your Region. You will be able to confirm the CloudFormation template that contains App Runner ObservabilityConfiguration resources setup:

The ObservabiltyConfiguration resource is a new top-level configuration introduced by App Runner to support tracing. For more information about observability configuration, see Configuring observability for your service in the AWS App Runner Developer Guide.

In your template, you should now see a new ObservabilityConfiguration configuration for your App Runner service with ObservabilityEnabled set to true. The ObservabilityConfigurationArn is set to the default observability configuration that enables X-Ray tracing.

3. Check out your App Runner resource (optional)

You can go to the App Runner console in your Region and check out the updated service. The tracing configuration is now enabled for "api-svc".

At this point, X-Ray tracing has been enabled for your App Runner service successfully!

4. View tracing data in CloudWatch

  1. Hit the endpoint that Copilot gives you in its output. You can also refer to copilot svc show to find the URL. This will generate traffic to your application, and create traces.
while true
do
   curl -o /dev/null -s -w "%{http_code}\n" https://<Random string>.<Your AWS region>.awsapprunner.com
   sleep 2
done

The snippet shown will generate traces that involve an App Runner service only. This means you will see only the “AppRunner Service” node in CloudWatch’s service map in step 3. This is because the root endpoint does not need to connect to the DynamoDB table.

To generate traces that involve your DynamoDB table, follow these instructions to populate your DynamoDB, and then hit https://<Random string>.<Your AWS region>.awsapprunner.com/api/movie?year={int}&title={string}. For example:

curl -o /dev/null -s -w "%{http_code}\n" https://<Random string>.<Your AWS region>.awsapprunner.com/api/movie?year=2009&title=Ameli
  1. Go to the App Runner console. Go to the Observability tab and choose View service map. You will be redirected to the  CloudWatch console.
  2. From the CloudWatch console, you can view the service map generated by the traffic you just created. Select the AppRunner Service node on the map; it will show you the service metrics, including Latency, Requests, and Faults.

  1. Select View traces to go to the CloudWatch Traces You can choose Trace ID to further investigate the details of each request.

Congratulations! By running two simple Copilot CLI commands, you’ve successfully deployed an App Runner service with X-Ray tracing enabled!

Conclusion

With AWS Copilot CLI, you can enable or disable X-Ray tracing for your App Runner service simply by toggling two lines in your service manifest. AWS Copilot is an open-source tool, and you can check out our incremental features on our sprint board.  We encourage you to get involved by creating GitHub issues or joining the conversation on Gitter!

There are more resources to learn about AWS App Runner X-Ray integration and AWS Copilot CLI. We encourage you to check these out!

Happy reading!