Kubernetes: отслеживание запросов с помощью AWS X-Ray и источника данных Grafana
Трассировка позволяет отслеживать запросы между компонентами, то есть, например, при использовании AWS и Kubernetes мы можем проследить весь путь запроса от AWS Load Balancer до Kubernetes Pod и до DynamoDB или RDS.
Это помогает нам как отслеживать проблемы с производительностью - где и какие запросы выполняются долго - так и получать дополнительную информацию при возникновении проблем, например, когда наш API возвращает клиентам 500 ошибок, и нам нужно выяснить, какой именно компонент системы вызывает проблему.
У AWS есть сервис для трассировки под названием X-Ray, где мы можем отправлять данные с помощью AWS X-Ray SDK для Python или AWS Distro для OpenTelemetry Python (или для других языков, но здесь мы будем говорить только о Python).
AWS X-Ray добавляет уникальный идентификатор X-Ray к каждому запросу и позволяет составить представление о полном «маршруте» запроса.
Кроме того, в Kubernetes мы можем отслеживать запросы с помощью таких инструментов, как Jaeger или Zipkin, а затем построить общую картину в Grafana Tempo.
Еще один способ сделать то же самое, а именно использовать X-Ray Daemon, который мы можем запустить в Kubernetes, и добавить плагин X-Ray в Grafana.
Кроме того, AWS Distro for OpenTelemetry также работает с идентификаторами, совместимыми с AWS X-Ray - см. AWS Distro для OpenTelemetry и AWS X-Ray, а также Отслеживание запросов с помощью ADOT.
Однако сегодня мы добавим X-Ray коллектор, который создаст Kubernetes DaemonSet и Kubernetes Service, куда Kubernetes Pods смогут отправлять данные, которые мы затем сможем увидеть либо в AWS X-Ray Console, либо в Grafana.
AWS IAM
Политика IAM
Для того, чтобы получить доступ к AWS API из подов X-Ray Daemon, нам нужно создать IAM-роль, которую мы затем будем использовать в ServiceAccount для X-Ray.
Мы по-прежнему используем старый способ добавления IAM-ролей через ServiceAccounts, хотя AWS недавно анонсировала дополнение Amazon EKS Pod Identity Agent.
Итак, создайте политику IAM с разрешениями на запись в X-Ray:
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow",
"Action": [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords"
], "Resource": [
"*"
] } ] }
Сохраните ее:
Роль IAM
Затем добавьте IAM-роль, которую сможет использовать Kubernetes ServiceAccount.
Найдите поставщика идентификационных данных нашего кластера EKS:
Перейдите в раздел IAM Roles, добавьте новую роль.
В поле Trusted entity type выберите Web Identity, в Web identity выберите Identity provider нашего EKS, а в поле Audience установите конечную точку AWS STS:
Приложите ранее созданную политику IAM:
Сохраните ее:
Запуск X-Ray Daemon в Kubernetes
Предлагаю использовать диаграмму okgolove/aws-xray.
Создадим файл x-ray-values.yaml:
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::492***148:role/XRayAccessRole-test
xray:
region: us-east-1
loglevel: prod
Добавим репозиторий:
$ helm repo add okgolove https://okgolove.github.io/helm-charts/
Установите схему в кластер, что создаст DaemonSet и Service:
$ helm -n ops-monitoring-ns install aws-xray okgolove/aws-xray -f x-ray-values.yaml
Проверим поды:
$ kk get pod -l app.kubernetes.io/name=aws-xray NAME READY STATUS RESTARTS AGE aws-xray-5n2kt 0/1 Pending 0 41s aws-xray-6cwwf 1/1 Running 0 41s aws-xray-7dk67 1/1 Running 0 41s aws-xray-cq7xc 1/1 Running 0 41s aws-xray-cs54v 1/1 Running 0 41s aws-xray-mjxlm 0/1 Pending 0 41s aws-xray-rzcsz 1/1 Running 0 41s aws-xray-x5kb4 1/1 Running 0 41s aws-xray-xm9fk 1/1 Running 0 41s
И работу Kubernetes Service:
$ kk get svc -l app.kubernetes.io/name=aws-xray NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE aws-xray ClusterIP None <none> 2000/UDP,2000/TCP 77s
Проверка и работа с X-Ray
Создание Python Flask HTTP App с помощью X-Ray
Создадим сервис на Python Flask , который ответит на наш HTTP запрос и внесет в журнал X-ray ID (промт ChatGPT— “Создайте простое приложение на Python с помощью AWS X-Ray SDK для Python для запуска в Kubernetes. Добавьте вывод идентификатора X-Ray в запросы”):
from flask import Flask
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.ext.flask.middleware import XRayMiddleware
import logging
app = Flask(__name__) # Configure AWS X-Ray
xray_recorder.configure(service='SimpleApp')
XRayMiddleware(app, xray_recorder) # Set up basic logging
logging.basicConfig(level=logging.INFO) @app.route('/')
def hello():
# Retrieve the current X-Ray segment
segment = xray_recorder.current_segment() # Get the trace ID from the current segment
trace_id = segment.trace_id if segment else 'No segment'
# Log the trace ID
logging.info(f"Responding to request with X-Ray trace ID: {trace_id}")
return f"Hello, X-Ray! Trace ID: {trace_id}\n"
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
Создайте requirements.txt:
flask==2.0.1 werkzeug==2.0.0 aws-xray-sdk==2.7.0
Добавьте Dockerfile:
FROM python:3.8-slim COPY requirements.txt . RUN pip install --force-reinstall -r requirements.txt COPY app.py . CMD ["python", "app.py"]
Создайте образ Docker – в данном случае мы используем репозиторий в AWS ECR:
$ docker build -t 492***148.dkr.ecr.us-east-1.amazonaws.com/x-ray-test .
Войдите в ECR:
$ aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 492***148.dkr.ecr.us-east-1.amazonaws.com
Выполните следующее:
$ docker push 492***148.dkr.ecr.us-east-1.amazonaws.com/x-ray-test
Запуск Flask App в Kubernetes
Создайте манифест с Kubernetes Deployment, Service и Ingress.
Для Ingress включите логирование в ведро AWS S3 - логи будут собираться из него в Grafana Loki.
Для развертывания установите AWS_XRAY_DAEMON_ADDRESS , а также URL Kubernetes Service нашего X-Ray Daemon:
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-app
spec:
replicas: 2
selector:
matchLabels:
app: flask-app
template:
metadata:
labels:
app: flask-app
spec:
containers:
- name: flask-app
image: 492***148.dkr.ecr.us-east-1.amazonaws.com/x-ray-test
ports:
- containerPort: 5000
env:
- name: AWS_XRAY_DAEMON_ADDRESS
value: "aws-xray.ops-monitoring-ns.svc.cluster.local:2000"
- name: AWS_REGION
value: "us-east-1"
---
apiVersion: v1
kind: Service
metadata:
name: flask-app-service
spec:
selector:
app: flask-app
ports:
- protocol: TCP
port: 80
targetPort: 5000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flask-app-ingress
annotations:
alb.ingress.kubernetes.io/scheme: "internet-facing"
alb.ingress.kubernetes.io/target-type: "ip"
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]'
alb.ingress.kubernetes.io/load-balancer-attributes: access_logs.s3.enabled=true,access_logs.s3.bucket=ops-1-28-devops-monitoring-ops-alb-logs
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: flask-app-service
port:
number: 80
Разверните его и проверьте Ingress/ALB:
$ kk get ingress NAME CLASS HOSTS ADDRESS PORTS AGE flask-app-ingress alb * k8s-default-flaskapp-25042181e0-298318111.us-east-1.elb.amazonaws.com 80 10m
Выполните запрос к конечной точке:
$ curl k8s-default-flaskapp-25042181e0-298318111.us-east-1.elb.amazonaws.com Hello, X-Ray! Trace ID: 1-65e1d287-5fc6f0f34b4fb2120da8bbec
И вот, наконец, мы видим идентификатор X-Ray.
Мы также можем увидеть его в журналах доступа к балансировщику нагрузки:
И в самом X-Ray
Хотя я ожидал, что балансировщик нагрузки тоже будет в карте запросов, но его там не было.
Источник данных Grafana X-Ray
Добавьте новый источник данных:
Настройте доступ к AWS - здесь все просто с ключами ACCESS и SECRET
Теперь в Explore у нас есть новый источник данных:
И новый тип визуализации — треки:
















