Giải mã lỗi 503
Bạn truy cập vào URL của ứng dụng, nhưng thay vì thấy giao diện dashboard, bạn lại nhận được một màn hình 503 Service Temporarily Unavailable lạnh lùng. Nếu bạn đang sử dụng NGINX Ingress, nhật ký (logs) của controller thường sẽ hiển thị nguyên nhân cụ thể:
[error] 197#197: *3586884 Service "default/my-service" does not have any active endpoints
Thông báo này thực sự rất hữu ích. Nó cho bạn biết rằng mặc dù Ingress đã tìm thấy Service của bạn, nhưng Service đó lại không tìm thấy bất kỳ Pod nào đang hoạt động tốt để xử lý yêu cầu.
Nguyên nhân gốc rễ
Cơ chế định tuyến của Kubernetes hoạt động như một chuỗi mắt xích: Ingress trỏ đến một Service, và Service đó trỏ đến một tập hợp các Pod. Để cơ chế này hoạt động, Service duy trì một danh sách Endpoints — một danh bạ thời gian thực lưu trữ các địa chỉ IP của những Pod đang hoạt động bình thường.
Lỗi 503 xảy ra khi danh bạ đó trống rỗng. Thông thường, sự cố này bắt nguồn từ việc sai lệch label, kiểm tra sức khỏe (health check) thất bại, hoặc đơn giản là gõ sai số cổng (port).
Các bước xử lý sự cố
1. Kiểm tra tài nguyên Endpoints
Bắt đầu bằng cách xác minh xem kết nối giữa Service và Pod có bị ngắt quãng hay không. Chạy lệnh sau:
kubectl get endpoints my-service -n <your-namespace>
Hãy nhìn vào cột ENDPOINTS. Nếu bạn thấy <none>, nghĩa là lưu lượng truy cập không có nơi nào để đi. Điều này xác nhận rằng vấn đề nằm ở các Pod của bạn hoặc cách Service chọn chúng, chứ không phải do chính Ingress.
2. Tìm kiếm sự sai lệch Label
Label là chất keo kết nối trong Kubernetes. Nếu Service của bạn tìm kiếm app: payment-api nhưng Deployment của bạn lại gán nhãn cho Pod là app: payment-gateway, Service sẽ không bao giờ tìm thấy chúng. Đây là một lỗi sao chép-dán (copy-paste) rất phổ biến.
Kiểm tra xem Service đang tìm kiếm nhãn nào:
kubectl describe svc my-service -n <your-namespace> | grep Selector
Sau đó, liệt kê các nhãn thực tế trên các Pod của bạn:
kubectl get pods -n <your-namespace> --show-labels
Pod phải có tất cả các label được liệt kê trong selector của Service. Nếu Service yêu cầu ba label mà Pod chỉ có hai, nó sẽ không nhận được lưu lượng truy cập.
3. Chẩn đoán lỗi Readiness Probe
Một Pod có thể ở trạng thái "Running" nhưng không phải là "Ready". Nếu readiness probe của nó thất bại, Kubernetes sẽ xóa IP của nó khỏi danh sách Endpoints để tránh gửi lưu lượng truy cập đến một container đang gặp sự cố.
Kiểm tra cột READY cho các Pod của bạn:
kubectl get pods -n <your-namespace>
Nếu bạn thấy 0/1, nghĩa là Pod vẫn sống nhưng không vượt qua được bài kiểm tra sức khỏe. Để biết chi tiết, hãy chạy lệnh kubectl describe pod <pod-name> và kiểm tra phần "Events" ở dưới cùng. Bạn có thể thấy: Readiness probe failed: HTTP probe failed with statuscode: 500. Điều này thường xảy ra nếu một ứng dụng (như Java Spring Boot) mất 45 giây để khởi động, nhưng probe đã bắt đầu kiểm tra chỉ sau 5 giây.
4. Xác minh cấu hình Cổng (Port Mapping)
Gõ sai số cổng là một lỗi âm thầm nhưng tai hại. Nếu container ứng dụng của bạn lắng nghe trên cổng 8080, nhưng Service của bạn lại gửi lưu lượng đến targetPort: 80, kết nối sẽ bị hết thời gian chờ (timeout).
Đảm bảo targetPort của Service khớp với containerPort trong Deployment của bạn:
# Service
ports:
- port: 80
targetPort: 8080 # Phải khớp với bên dưới
# Deployment
containers:
- name: my-app
ports:
- containerPort: 8080 # Phải khớp với bên trên
Xác nhận kết quả sửa lỗi
Sau khi cập nhật label hoặc probe, hãy kiểm tra lại danh sách Endpoints. Bạn sẽ thấy một danh sách các địa chỉ IP nội bộ như 10.244.1.45:8080. Để chắc chắn 100%, hãy chạy một bài kiểm tra kết nối nhanh từ bên trong cluster:
kubectl run curl-test --image=curlimages/curl -i --tty --rm -- curl http://my-service:80
Phản hồi 200 OK có nghĩa là lỗi 503 của bạn đã chính thức được giải quyết.
Các thực hành tốt nhất
- Tiêu chuẩn hóa Label: Sử dụng tiêu chuẩn
app.kubernetes.io/nameđể giữ cho các selector nhất quán giữa các nhóm phát triển. - Trì hoãn Probe hợp lý: Thiết lập
initialDelaySecondskhớp với thời gian khởi động thực tế của ứng dụng. Việc cho một ứng dụng khởi động chậm khoảng 30 giây để "thở" sẽ giúp tránh các lỗi 503 không đáng có. - Cảnh báo tự động: Sử dụng các công cụ như Prometheus để cảnh báo khi chỉ số
kube_endpoint_address_availablegiảm xuống bằng không.

