Triển khai AWS X-Ray cho Django trên ECS Fargate – Chia sẻ kinh nghiệm thực tế Chuyên mục Devops 2025-10-29 4 Lượt xem 1 Lượt thích 0 Bình luận
“Bạn sẽ không thể tối ưu thứ bạn không đo lường được.”
— đó là điều tôi rút ra sau nhiều lần phải mày mò debug performance trên hệ thống Django chạy trong ECS Fargate.
Vì sao tôi cần bật X-Ray cho Django?
Trong hệ thống microservice, việc hiểu được request đi qua đâu, truy cập DB thế nào, API nào chậm… là cực kỳ quan trọng.
Trước đây, tôi chỉ dựa vào CloudWatch logs và một vài metric Prometheus, nhưng nó không giúp tôi trả lời được câu hỏi “request này tốn bao nhiêu thời gian ở đâu?”.
Khi dùng AWS ECS (Fargate) cho backend Django, tôi bắt đầu tìm đến AWS X-Ray — công cụ tracing giúp quan sát request, database query, và external call (S3, SES, DynamoDB, v.v.) theo dạng end-to-end tracing.
Kiến trúc tổng quan
Triển khai X-Ray trên ECS gồm hai phần chính:
- 
X-Ray Daemon container (hoặc Agent): chạy cùng task để nhận dữ liệu trace qua UDP 2000/udp.
- 
Django app: được instrument bằng aws-xray-sdkđể gửi trace về daemon.
Cấu hình trong Django
requirements.txt
aws-xray-sdk==2.12.1Tôi tách cấu hình X-Ray riêng thành file xray_config.py, để dễ quản lý và bật/tắt bằng biến môi trường.
Ở đây tôi dùng ENABLE_XRAY để chủ động tắt X-Ray ở local/dev.patch_all() sẽ tự động instrument các thư viện phổ biến như boto3, requests, psycopg2, v.v.
Tích hợp middleware trong Django
Trong config/settings/base.py, tôi thêm middleware X-Ray chỉ khi X-Ray bật:
if os.getenv("ENABLE_XRAY", "false").lower() == "true":
    MIDDLEWARE.append('aws_xray_sdk.ext.django.middleware.XRayMiddleware')
XRAY_RECORDER = {
    'AUTO_INSTRUMENT': True,
    'AWS_XRAY_CONTEXT_MISSING': 'LOG_ERROR',
    'AWS_XRAY_TRACING_NAME': os.getenv("AWS_XRAY_TRACING_NAME", "none"),
    'PLUGINS': ('ECSPlugin', 'RDSPlugin'),
    'DAEMON_ADDRESS': os.getenv("AWS_XRAY_DAEMON_ADDRESS", "127.0.0.1:2000"),
    'STREAM_SQL': True,
}Với cấu hình này, mọi request Django sẽ được gắn trace header (X-Amzn-Trace-Id) và gửi dữ liệu về daemon container.
Import vào Django project
Để mọi thứ load sớm khi app khởi động, tôi import xray_config trong config/__init__.py:
from .celery import app as celery_app
try:
    from core.xray_config.xray_config import *
except ImportError:
    pass
__all__ = ("celery_app",)Cấu hình ECS Task Definition
Trong ECS, tôi chạy hai container trong cùng một task:
- 
my-project-api: container Django
- 
xray-daemon: container daemon của AWS
Phần quan trọng nhất là các biến môi trường và cổng UDP 2000:
💡 Lưu ý:
AWS_XRAY_DAEMON_ADDRESSphải trỏ đến127.0.0.1:2000vì daemon và app chạy chung task.
Đừng quên mở port UDP 2000 trong cấu hình container.
Nên bật CloudWatch Logs cho cả hai container để dễ debug daemon.
Task Role (IAM)
Để X-Ray Daemon có thể gửi dữ liệu tracing lên AWS X-Ray Service, Task Role của ECS Task cần có quyền sau:
| Policy | Quyền Hạn | 
| AWSXRayDaemonWriteAccess | Cho phép gửi dữ liệu (segments) lên X-Ray. | 
Kết quả
Sau khi deploy, bạn có thể vào AWS X-Ray console → Service Map và sẽ thấy một sơ đồ các segment như thế này:
Từng request sẽ hiển thị trace ID, thời gian xử lý từng thành phần, và cả exception nếu có.
Lưu ý lớn: stream_sql và psycopg2
Một điểm tôi nhận ra khi bật stream_sql=True là Django dùng psycopg2 (PostgreSQL driver thuần Python) không được X-Ray hiển thị raw SQL query.
AWS chỉ hỗ trợ SQL tracing đầy đủ với Flask SQLAlchemy qua sqlalchemy plugin.
Vì vậy nếu bạn đang kỳ vọng thấy query trong X-Ray segment, sẽ chỉ thấy “execute” chứ không có text query — hoàn toàn bình thường.
Vấn đề thời gian tới: AWS X-Ray sẽ End-of-Support năm 2027
Đây là thông báo chính thức của AWS:
🕓 End-of-support notice – February 25, 2027
AWS X-Ray sẽ ngừng hỗ trợ các SDK và daemon. Sau ngày này, bạn sẽ không còn nhận được update, fix, hoặc release mới.
👉 AWS khuyến nghị chuyển sang OpenTelemetry.Xem chi tiết tại: Migrating from X-Ray instrumentation to OpenTelemetry instrumentation
Điều này có nghĩa là:
- 
Các hệ thống hiện dùng aws-xray-sdknhư Django, Flask, Node.js, Java sẽ vẫn chạy, nhưng không được update.
- 
Trong 2025–2026, nên lên kế hoạch chuyển sang OpenTelemetry Collector + AWS Distro for OpenTelemetry (ADOT). 
Gợi ý hướng chuyển sang OpenTelemetry (OTel)
Nếu bạn triển khai mới hoặc có kế hoạch dài hạn, hãy cân nhắc:
- 
Dùng OpenTelemetry SDK cho Python ( opentelemetry-sdk,opentelemetry-instrumentation-django).
- 
Dữ liệu trace có thể gửi đến: - 
AWS X-Ray backend (qua ADOT Collector), hoặc 
- 
Amazon CloudWatch Application Signals, Grafana Tempo, Datadog, v.v. 
 
- 
Cách chuyển dần: chạy song song OTel và X-Ray để so sánh trace trong thời gian đầu.
Bài học rút ra sau khi triển khai
- 
Đặt X-Ray daemon cùng task ECS giúp giảm độ trễ gửi trace và đơn giản network. 
- 
Không bật X-Ray ở dev/local, vì SDK sẽ log rất nhiều và làm chậm request. 
- 
Dùng biến môi trường ( ENABLE_XRAY,AWS_XRAY_TRACING_NAME) để bật/tắt linh hoạt giữa các môi trường.
- 
Không kỳ vọng thấy raw SQL khi dùng psycopg2, đây là giới hạn SDK. 
- 
Bắt đầu chuyển sang OpenTelemetry càng sớm càng tốt, vì sau 2027 X-Ray SDK sẽ không còn duy trì. 
Kết luận
Việc bật AWS X-Ray cho Django chạy trên ECS Fargate giúp tôi “mở mắt” về cách hệ thống vận hành thật sự.
Tôi nhìn thấy bottleneck, thấy service nào gọi quá nhiều API, thấy transaction chậm vì truy vấn DB nào.
Nhưng quan trọng hơn cả — tôi học được rằng mọi công cụ đều có vòng đời của nó.
X-Ray rất hữu ích, nhưng tương lai sẽ là OpenTelemetry – tiêu chuẩn mở, linh hoạt hơn nhiều.
Nếu bạn đang vận hành hệ thống tương tự, hãy tận dụng X-Ray trong hiện tại, và bắt đầu chuẩn bị cho hành trình OTel ngay từ hôm nay.
✍️ Tác giả: Một DevOps engineer từng mất cả ngày chỉ để tìm vì sao request /api/users/ mất 2 giây trên ECS.
Nếu bạn đang triển khai tracing cho Django trên ECS, hy vọng bài viết này giúp bạn tiết kiệm ít nhất… vài giờ debug 😄
Bạn có muốn tôi tạo thêm bản mở rộng phần “Migration sang OpenTelemetry (OTel)” (gồm ví dụ cấu hình Django + ECS Collector) để bạn đăng thành phần 2 của series blog không?
Nếu bạn đồng ý, tôi có thể viết tiếp phần đó ngay, để bạn có “blog tiếp nối” khi nói về việc rời X-Ray.
 
                        
                                         
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                     
                                                    
Bình luận (0)