= Using AWS X-Ray to analyze and debug applications :toc: This chapter will explain how to use https://aws.amazon.com/xray/[AWS X-Ray] to perform distribute tracing on the applications deployed on Kubernetes. AWS X-Ray helps developers analyze and debug production, distributed applications, such as those built using a microservices architecture. With X-Ray, you can understand how your application and its underlying services are performing to identify and troubleshoot the root cause of performance issues and errors. We will also be using https://aws.amazon.com/ecr/[Amazon EC2 Container Registry] to store our Docker container images. ECR is a fully-managed Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images. == Pre-requisites In order to perform exercises in this chapter, you’ll need to deploy configurations to a Kubernetes cluster. To create an EKS-based Kubernetes cluster, use the link:/01-path-basics/102-your-first-cluster#create-a-kubernetes-cluster-with-eks[AWS CLI] (recommended). If you wish to create a Kubernetes cluster without EKS, you can instead use link:/01-path-basics/102-your-first-cluster#alternative-create-a-kubernetes-cluster-with-kops[kops]. You will need AWS CLI and Docker installed on your desktop. The AWS Region where you deployed Kubernetes must have the following services: * AWS X-Ray * Amazon EC2 Container Registry All application code and configuration files for this chapter are in the `x-ray-ecr` directory. == IAM Roles for Kubernetes worker nodes We need the following `AWS managed policy` for the worker nodes: * **AWSXrayWriteOnlyAccess** (To allow AWS X-Ray daemon running inside Kubernetes worker nodes send traces to AWS X-ray) * **AmazonEC2ContainerRegistryReadOnly** (To pull Docker images from ECR) Navigate to the EC2 Console, select any of the worker nodes, under the `Description` tab, click on the link to `IAM role`. image::images/ec2-iamrole.png[ec2-iamrole, 800] This will bring you to the IAM console. Under the `Permissions` tab, click on `Attach policy` and add the following 2 policies: * AWSXrayWriteOnlyAccess * AmazonEC2ContainerRegistryReadOnly image::images/iamrole.png[iamrole, 800] == Build the AWS X-Ray Daemon . Login to Amazon ECR using AWS CLI. $ `aws ecr get-login --no-include-email` . Create a private Docker repository for our X-Ray daemon $ aws ecr create-repository --repository-name xraydaemon { "repository": { "repositoryArn": "arn:aws:ecr:ap-southeast-1::repository/xraydaemon", "registryId": "", "repositoryName": "xraydaemon", "repositoryUri": ".dkr.ecr.ap-southeast-1.amazonaws.com/xraydaemon", "createdAt": 1510724710.0 } } The **repositoryUri** is the URI of our newly created Docker image repository, it has the format of *_.dkr.ecr..amazonaws.com/_*. . Build the AWS X-ray daemon docker image locally on your laptop. Replace **repositoryUri** with the value of the output from the last command. $ cd x-ray-daemon && docker build -t :v1 . . Push the xraydaemon docker image to ECR: $ docker push :v1 === Edit templates/daemonsetxray.yaml Replace line 14 and change *image: .dkr.ecr..amazonaws.com/xraydaemon:v1* to your xraydaemon repositoryUri. . Deploy AWS X-Ray as DaemonSet $ cd .. && kubectl create -f templates/daemonsetxray.yaml == Build a Simple Python Flask Application . Create a ECR repository for the Python Flask application: $ aws ecr create-repository --repository-name flaskxray . Build the Docker image for Python Flask application: $ cd python-flask-app && docker build -t .dkr.ecr..amazonaws.com/flaskxray:v1 . . Test the docker image locally, you should get a reply when you `curl http://0.0.0.0:5000` : $ docker run -p 5000:5000 -it .dkr.ecr..amazonaws.com/flaskxray:v1 Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) . Push the docker image to ECR: $ docker push .dkr.ecr..amazonaws.com/flaskxray:latest === Edit templates/flaskyxray-deployment.yaml Replace line 15 and change `image: .dkr.ecr..amazonaws.com/xraydaemon:v1` to your flaskxray repositoryUri. . Deploy the Python Flask Application $ kubectl create -f templates/flaskyxray-deployment.yaml $ kubectl create -f templates/flaskyxray-service.yaml . Access the Python Flask web service $ kubectl get svc -owide # look for the DNS name of the Load Balancer for **flaskxray-service** under the column **EXTERNAL-IP** $ curl http:// Hello Flask . Navigate to AWS X-Ray Console to see your traces image::images/flaskxray.png[flaskxray, 700] == Tracing multiple services : A Node Express example We will modify the Node Express applications https://github.com/arun-gupta/container-service-discovery[found here] for this exercise. We will create our ECR docker image repositories. Next, we will build and push each of the 3 services to the ECR repository. (Note: You need **jq** https://stedolan.github.io/jq/download/[installed]) . Login to ECR $ `aws ecr get-login --no-include-email` . Build and push the `Greeter` service $ cd nodejs-microservices $ export greeter_repo=$(aws ecr create-repository --repository-name greeter| jq -r '.repository.repositoryUri') $ cd greeter && docker build -t $greeter_repo:v1 . $ docker push $greeter_repo:v1 && cd .. . Build and push the `Name` service $ export name_repo=$(aws ecr create-repository --repository-name name| jq -r '.repository.repositoryUri') $ cd name && docker build -t $name_repo:v1 . $ docker push $name_repo:v1 && cd .. . Build and push the `Webapp` service $ export webapp_repo=$(aws ecr create-repository --repository-name webapp| jq -r '.repository.repositoryUri') $ cd webapp && docker build -t $webapp_repo:v1 . $ docker push $webapp_repo:v1 && cd .. . Deploy the 3 services to Kubernetes $ cd .. $ sed -ie 's, '""','" $name_repo:v1"',' templates/nodejs-microservices.yaml $ sed -ie 's, '""','" $greeter_repo:v1"',' templates/nodejs-microservices.yaml $ sed -ie 's, '""','" $webapp_repo:v1"',' templates/nodejs-microservices.yaml $ kubectl create -f templates/nodejs-microservices.yaml --record . Access the web service $ kubectl get svc -owide # look for the DNS name of the Load Balancer for **webapp-service** under the column **EXTERNAL-IP** $ curl http:// . Navigate to AWS X-Ray Console to see your traces. You can see the time taken for `webapp` service to make the 2 calls to `greeter` and `name` services. image::images/xray1.png[xray, 700] image::images/xraytrace.png[xraytrace, 700] == Delete all Kubernetes deployment and services $ kubectl delete -f templates/flaskyxray-deployment.yaml $ kubectl delete -f templates/flaskyxray-service.yaml $ kubectl delete -f templates/nodejs-microservices.yaml $ kubectl delete -f templates/daemonsetxray.yaml == Delete images in ECR $ for n in webapp name greeter flaskxray xraydaemon do aws ecr delete-repository --repository-name $n --force done