---
id: case-502
title: "API trả 502 sau deploy"
shortTitle: "502 sau deploy"
track: cases
trackTitle: "Tình huống vận hành"
order: 1
level: core
status: published
estimatedMinutes: 35
prerequisites:
  - networking-nginx-reverse-proxy
  - logs-files
next: case-cert
reviewedAgainst: 2026-10-12
sources:
  - title: "ngx_http_proxy_module"
    url: https://nginx.org/en/docs/http/ngx_http_proxy_module.html
  - title: "Deployment rolling update"
    url: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-update-deployment
---

# API trả 502 sau deploy

502 nghĩa là proxy đã nhận request nhưng không lấy được response hợp lệ từ upstream. Lúc đó app có thể đang chết, đang restart, hoặc proxy đang trỏ nhầm chỗ. Đây không phải lỗi DNS phía client, vì request đã tới được proxy và proxy đã trả lời.

## Để làm gì

Trong mười phút đầu, bạn cần khoanh được tầng nào đang gãy và quyết định rollback hay sửa tiếp. Đừng restart lần lượt mọi thứ, vì mỗi lần restart lại xóa thêm một phần bằng chứng.

## Gồm những gì

- Cách phân biệt 502, 504 và 500.
- Thứ tự điều tra: một request mẫu, log của proxy, process upstream, rồi cửa sổ deploy.
- Khi nào nên rollback trước khi đọc diff.

Bài không viết lại cấu hình Nginx, phần đó đã có ở bài Nginx. Bài này dành cho lúc user đang bị lỗi thật.

## Dùng khi nào

Monitor hoặc một user báo API chết ngay sau khi pipeline xanh. Cũng có thể chỉ một path chết, còn trang tĩnh vẫn mở bình thường.

Nếu trình duyệt báo lỗi certificate, hãy chuyển sang bài tiếp theo. Nếu `curl` treo mà không trả về status nào, vấn đề nằm ở mạng hoặc firewall, request còn chưa tới proxy.

## Kiến thức cốt lõi

Suốt sự cố, hãy giữ một câu hỏi: lỗi bắt đầu từ lúc nào, và trong khoảng đó có deploy nào không. Ghi giờ theo UTC hoặc theo giờ trong log, đừng ghi "lúc nãy", vì sau này bạn phải đối chiếu giờ đó với log và lịch sử rollout.

Bước đầu tiên là gửi một request mẫu, lưu lại status và vài dòng body. Request này cho bạn mã lỗi chính xác, và mã lỗi quyết định bạn nhìn vào tầng nào:

- Nginx trả 502 khi upstream đóng kết nối sớm, từ chối kết nối, hoặc reset. Docs của `ngx_http_proxy_module` mô tả 502 cho trường hợp lấy response từ upstream thất bại.
- 504 nghĩa là proxy đã chờ quá `proxy_read_timeout`.
- 500 nghĩa là upstream đã trả về lỗi của chính nó.

Ba mã này chỉ về ba chỗ khác nhau. Sau khi đã có request mẫu, điều tra theo thứ tự:

1. Đọc error log của proxy ở đúng timestamp đó. Tìm `connect() failed`, `upstream prematurely closed`, `no live upstreams`. Log proxy đứng đầu vì nó cho biết proxy gặp chuyện gì khi gọi upstream, mà đọc log thì không làm thay đổi hệ thống.
2. Kiểm tra upstream: process còn chạy không, có listen đúng port không. Trên Kubernetes, xem Pod đang Ready hay CrashLoop, và Service có endpoint không. Bước này đứng sau bước 1 vì log proxy đã khoanh được hướng, ví dụ `connect() failed` thì nhìn ngay process và port.
3. So giờ bắt đầu 502 với giờ rollout, dùng `kubectl rollout history` và event của Deployment. Nếu hai mốc trùng nhau, bản mới là nghi phạm số một.

Rollback khi hội đủ ba điều kiện: bản vừa deploy là thay đổi duy nhất trong cửa sổ đó, lỗi bắt đầu đúng theo nó, và bản trước đó từng chạy ổn. Nếu bạn sửa code trên production trong lúc user vẫn đang ăn 502, incident sẽ kéo dài thêm. Hãy đưa user về bản cũ trước, rồi mới đọc diff.

Đừng rollback khi lỗi đã có từ trước lúc deploy, hoặc khi bản mới đã ghi dữ liệu mà bản cũ không đọc được. Trong trường hợp đó, rollback sẽ làm hỏng dữ liệu. Hãy dừng ghi, giữ lại một replica để lấy log, rồi mới quyết định.

Sau khi rollback, gửi lại đúng request mẫu ban đầu. Nếu request trả về 200 và tỉ lệ 502 trên monitor giảm về mức trước deploy, phần cứu user đã xong. Nếu vẫn 502, nguyên nhân không nằm ở bản deploy; quay lại bước 1 và 2 để tìm tầng khác.

## Lệnh và code mẫu

Gửi một request, không lặp hàng trăm lần:

```bash
curl -sS -D - -o /tmp/body.txt --max-time 10 https://api.example.com/health
```

Trên server proxy:

```bash
sudo tail -n 50 /var/log/nginx/error.log
```

Trên cluster, sau khi chắc chắn đang ở đúng context:

```bash
kubectl rollout history deploy/api
kubectl get pods -l app=api
kubectl describe deploy/api | sed -n '/Events/,$p'
```

`kubectl rollout undo deploy/api` đưa Deployment về revision trước. Chỉ chạy lệnh này khi bạn đã xác nhận revision đó từng phục vụ user ổn định.

## Thực hành

Bạn không cần production. Hãy dùng một lần gặp 502 mà bạn còn nhớ, hoặc dựng tình huống trên giấy.

1. Viết ra thứ bạn sẽ thấy nếu process app chưa listen: Nginx trả 502, error log có connection refused.
2. Viết ra thứ bạn sẽ thấy nếu app đã nhận request rồi ném exception: status 500, body do app trả về, error log của proxy không có `connect() failed`.
3. Viết một câu điều kiện để rollback, ví dụ: deploy cách đây 8 phút, 502 bắt đầu đúng lúc Pod mới Ready, revision trước vẫn còn trong history.

## Kết quả mong đợi

Bạn tách được 502 của proxy với 500 của app. Bạn có một điều kiện rollback cụ thể, không phải kiểu "thấy lỗi là undo".

## Checklist

- [ ] Lưu một request mẫu kèm status và giờ.
- [ ] Đọc error log của proxy trước khi restart upstream.
- [ ] Đối chiếu giờ lỗi với giờ deploy.
- [ ] Chỉ rollback khi bản trước còn dùng được và dữ liệu không bị kẹt ở schema mới.
- [ ] Sau rollback, gửi lại đúng request mẫu và xem tỉ lệ 502 có giảm không.

## Lỗi thường gặp

**Restart Nginx vì thấy 502.** Proxy vẫn đang làm đúng việc của nó. Nếu upstream chết, restart proxy cũng không tạo ra process app. Hãy xem upstream trước.

**Scale thêm Pod trong lúc Pod đang CrashLoop.** Số Pod tăng thì số bản lỗi cũng tăng. Hãy đọc log của một Pod trước, rồi mới tính chuyện scale.

**Chạy `rollout undo` khi migration đã chạy.** Bản cũ không đọc được cột mới, nên user hết 502 nhưng bắt đầu gặp lỗi dữ liệu. Với thay đổi schema, hãy dừng traffic và sửa tiến, đừng undo mù.

## Nguồn

1. [ngx_http_proxy_module](https://nginx.org/en/docs/http/ngx_http_proxy_module.html) — proxy và lỗi khi nói chuyện với upstream.
2. [Rolling update](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-update-deployment) — revision và rollback của Deployment.

## Tiếp theo

[Trình duyệt báo certificate](./02-cert.md)
