Lỗi Gặp Phải
Bạn vừa đẩy một phiên bản mới lên Elastic Beanstalk và quá trình triển khai bị thất bại. Bảng điều khiển EB chuyển sang trạng thái Severe, và nhật ký sự kiện hiển thị thông báo tương tự như sau:
ERROR: Your WSGIPath refers to a file that does not exist.
Instance deployment failed. For details, see 'eb-engine.log'.
Environment health has transitioned from Ok to Severe
Thường thì lỗi này đi kèm với các sự cố health check của load balancer — LB liên tục gửi request đến các instance, nhận lại toàn lỗi, và EB đánh dấu chúng là không khỏe mạnh. Môi trường sẽ trượt dần từ Ok → Warning → Severe trong chưa đầy hai phút.
Đây là hai vấn đề riêng biệt nhưng có liên quan đến nhau. Hãy sửa lỗi cấu hình WSGI trước. Các lỗi health check hầu như sẽ tự giải quyết khi ứng dụng khởi động được.
Nguyên Nhân
EB cần biết WSGI callable của bạn nằm ở đâu. Nó tìm kiếm thông tin này qua .ebextensions, một Procfile, hoặc namespace aws:elasticbeanstalk:container:python. Nếu đường dẫn đó không khớp với những gì có trong file zip triển khai, app server — Apache + mod_wsgi trên Amazon Linux 2, hoặc gunicorn trên AL2023 — sẽ không bao giờ khởi động được.
Các nguyên nhân thường gặp:
WSGIPathvẫn trỏ đếnapplication.py, nhưng bạn đã đổi tên hoặc tái cấu trúc project- Project Django được triển khai mà không đặt đường dẫn đến
myproject/wsgi.py .ebignorehoặc.gitignoređang âm thầm loại trừ file wsgi khỏi bundle- Lỗi đóng gói trong CI/CD — file zip tải lên S3 bị thiếu file hoàn toàn
- Đường dẫn health check trả về redirect (301/302) hoặc trang xác thực thay vì 200
Bước 1 — Đọc Log Trước Khi Làm Bất Cứ Điều Gì
Phỏng đoán chỉ tốn thêm lần deploy. Hãy kéo log về trước:
# Via EB CLI
eb logs
# Hoặc xem trực tiếp theo thời gian thực
eb logs --stream
Tập trung vào hai file: eb-engine.log cho biết chính xác đường dẫn nào EB đã cố tải. web.stdout.log cho biết điều gì xảy ra khi app server thực sự cố khởi động — lỗi import, thiếu biến môi trường, và các vấn đề tương tự.
Thích giao diện đồ họa? Vào Environment → Logs → Request Logs → Last 100 Lines trong console.
Bước 2 — Sửa WSGIPath
Kiểm tra đường dẫn mà EB đang được cấu hình để sử dụng:
eb config
Lệnh này sẽ mở cấu hình môi trường trong một trình soạn thảo. Tìm phần này:
aws:elasticbeanstalk:container:python:
WSGIPath: application:application
Định dạng là module_path:callable cho một đối tượng Python, hoặc đường dẫn file đơn giản cho wsgi.py của Django. Đây là giá trị đúng cho các thiết lập phổ biến:
Flask (file đơn)
# application.py chứa: app = Flask(__name__)
aws:elasticbeanstalk:container:python:
WSGIPath: application:app
Django
aws:elasticbeanstalk:container:python:
WSGIPath: myproject/wsgi.py
Thay myproject bằng tên thư mục project Django thực tế của bạn — thư mục chứa settings.py, không phải thư mục gốc của repo.
Cách quản lý gọn nhất là đưa vào version control trong .ebextensions/python.config:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: myproject/wsgi.py
NumProcesses: 1
NumThreads: 15
Như vậy đường dẫn đúng sẽ được đóng gói trong mỗi lần deploy, và bạn không phải phụ thuộc vào cấu hình môi trường mà ai đó có thể vô tình ghi đè.
Với Django, hãy đảm bảo module settings cũng được thiết lập:
eb setenv DJANGO_SETTINGS_MODULE=myproject.settings
Bước 3 — Xác Nhận File Thực Sự Có Trong Bundle Triển Khai
Khi bạn chạy eb deploy, EB sẽ nén project của bạn bằng git — nghĩa là nó tuân theo .gitignore. Nếu file wsgi không được theo dõi, nó sẽ không được đóng gói.
# Kiểm tra những gì EB thực sự đưa vào
git ls-files | grep wsgi
Không có kết quả? File chưa được theo dõi. Hãy commit nó, hoặc ghi đè phần loại trừ bằng .ebignore:
# .ebignore — buộc đưa vào dù .gitignore có loại trừ
!myproject/wsgi.py
Đóng gói zip thủ công trong CI/CD? Hãy xác minh nội dung trực tiếp:
unzip -l deploy.zip | grep wsgi
Lệnh này phát hiện được một lỗi CI khá phổ biến khi bước đóng gói chạy từ sai thư mục và tạo ra một file zip với cấu trúc bên trong không đúng.
Bước 4 — Sửa Đường Dẫn Health Check
Ứng dụng có thể đang chạy bình thường, nhưng load balancer vẫn đánh dấu các instance là không khỏe mạnh. Mặc định, EB gửi request đến / mỗi 30 giây. Nếu đường dẫn đó redirect (chẳng hạn đến trang đăng nhập) hoặc trả về bất cứ thứ gì khác ngoài 2xx, health check sẽ thất bại.
Thêm một endpoint health check đơn giản luôn trả về 200:
# Flask
@app.route('/health')
def health():
return 'OK', 200
# Django (urls.py)
from django.http import HttpResponse
urlpatterns = [
path('health/', lambda request: HttpResponse('OK')),
# ... phần còn lại của urls
]
Sau đó trỏ EB vào đó. Trong console: Configuration → Load Balancer → Processes → Health check path → /health.
Hoặc trong .ebextensions:
option_settings:
aws:elasticbeanstalk:application:
Application Healthcheck URL: /health
Bước 5 — Triển Khai Lại và Theo Dõi
eb deploy --staged
Xem các sự kiện khi quá trình chạy:
eb events -f
Triển khai thành công nhưng health vẫn còn Severe? Hãy chờ — EB yêu cầu một số lần health check thành công liên tiếp (thường là 3 lần, cách nhau khoảng 90 giây) trước khi chuyển lại về Ok.
Xác Nhận Thành Công
Bạn đã hoàn thành khi cả ba điều kiện này đều đúng:
- Console hiển thị Health: Ok (màu xanh)
eb statusbáo cáoHealth: Green- URL ứng dụng phản hồi đúng
eb status
# Kết quả mong đợi:
# Environment details for: your-env-name
# Status: Ready
# Health: Green
curl -I https://your-env.elasticbeanstalk.com/health
# Kết quả mong đợi: HTTP/1.1 200 OK
Tham Khảo Nhanh — Các Giá Trị WSGIPath Thường Gặp
- Flask (application.py → app):
application:app - Flask (application.py → application):
application:application - Django:
myproject/wsgi.py - FastAPI với Mangum:
main:handler(dù FastAPI thường chạy trên Lambda hơn là EB)
Vẫn Thất Bại? SSH Vào Instance
Nếu tất cả những bước trên đã kiểm tra xong mà deploy vẫn chết, hãy vào thẳng instance:
eb ssh
# Kiểm tra tiến trình app server
sudo systemctl status web
# Đọc trực tiếp log của engine
sudo tail -50 /var/log/eb-engine.log
Chín trên mười lần, những gì bạn sẽ tìm thấy là một biến môi trường bị thiếu — SECRET_KEY trong Django là ví dụ điển hình nhất. Ứng dụng bị crash khi khởi động, không phục vụ được một request nào, và EB báo cáo toàn bộ sự việc như là lỗi health check. Lỗi thực sự bị chôn vùi trong web.stdout.log, không phải trong các sự kiện health check.

