---
id: case-rollback
title: "Rollback sau deploy"
shortTitle: "Rollback"
track: cases
trackTitle: "Tình huống vận hành"
order: 7
level: core
status: published
estimatedMinutes: 30
prerequisites:
  - case-502
  - kubernetes-kubectl
next: case-docker-image
reviewedAgainst: 2026-10-12
sources:
  - title: "Rolling back a Deployment"
    url: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment
  - title: "Deployment status"
    url: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#deployment-status
---

# Rollback sau deploy

Rollback là đưa user về bản đã từng chạy ổn, không phải là đi tìm cho ra bug. Bug để đọc sau, khi lỗi đã ngừng tăng. Và cũng cần nhớ: bản ngay trước không phải lúc nào cũng là bản an toàn.

## Để làm gì

Bạn cần quyết định undo hay sửa tiến, chỉ làm đúng một thay đổi, rồi chứng minh user đã về bản cũ. Đừng undo hai lần liên tiếp chỉ vì sốt ruột.

## Gồm những gì

- Điều kiện để được rollback.
- `kubectl rollout undo` và các bước kiểm tra sau khi undo.
- Trường hợp schema database và job nền không lùi theo web.

Bài không bàn chuyện viết test mới; việc đó để sau khi incident kết thúc.

## Dùng khi nào

502, tỉ lệ 5xx hoặc latency tăng đúng trong cửa sổ của một lần deploy, và revision trước vẫn còn trong history. Bài 502 đã nói khi nào không nên undo. Bài này đi qua các bước khi bạn đã chọn undo.

Đừng rollback một thay đổi đã chạy trên production hai ngày chỉ vì hôm nay có lỗi. Trong hai ngày đó đã có nhiều commit chồng lên, và undo về revision ngay trước sẽ gỡ luôn những bản sửa đúng ở giữa. Lúc đó hãy chọn một image sha đã biết là tốt, đừng chọn "cái ngay trước".

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

Thứ tự các bước, và lý do của từng bước:

1. **Ghi lại ba thứ trước khi undo:** revision đang chạy, revision sẽ quay về, và một metric dùng để chứng minh. Metric đó là tỉ lệ 5xx hoặc một request mẫu, đúng thứ bạn đã dùng lúc phát hiện lỗi. Bước này phải làm trước, vì không có số trước thì sau khi undo bạn không có gì để so sánh.
2. **Đọc changelog của chính lần deploy đó.** Bước này đứng trước lệnh undo vì `rollout undo` không đảo được migration trong database. Nếu deploy chỉ thêm cột và code mới ghi vào cột đó, code cũ bỏ qua cột mới và thường vẫn chạy được. Nếu deploy đã xóa một cột mà code cũ cần, undo sẽ làm web lỗi theo một kiểu khác. Không có changelog thì hỏi người đã merge; mất một phút vẫn rẻ hơn nhiều so với khôi phục dữ liệu.
3. **Xem worker có đi cùng web không.** Worker và web chạy lệch version là trạng thái xấu. Nếu cả hai cùng đổi một contract, phải rollback cả hai. Chỉ rollback web thì job mới vẫn ghi ra dữ liệu mà web cũ không đọc được.
4. **Undo một lần.** Kubernetes giữ các ReplicaSet cũ. `kubectl rollout undo deploy/api` quay về revision ngay trước. `kubectl rollout undo deploy/api --to-revision=3` quay về đúng revision bạn đã thấy trong `rollout history`. Docs Deployment mô tả undo là cách quay về cấu hình trước, nhưng nó không đảo migration.
5. **Xác nhận.** Đợi `kubectl rollout status` báo xong và image trên Pod khớp với bản cũ. Sau đó lặp lại đúng request mẫu hoặc đúng biểu thức Prometheus đã ghi ở bước 1.

Tiêu chí để đi tiếp: nếu tỉ lệ lỗi giảm về mức trước deploy, phần cứu user đã xong. Nếu lỗi không giảm, bản vừa deploy không phải nguyên nhân. Đừng undo thêm lần nữa; hãy quay lại bài 502 và tìm ở tầng khác.

## Lệnh và code mẫu

Chỉ chạy trên cluster lab, sau khi đã xem history:

```bash
kubectl rollout history deploy/api
kubectl rollout undo deploy/api --to-revision=<so>
kubectl rollout status deploy/api
kubectl get pods -l app=api -o jsonpath='{range .items[*]}{.spec.containers[0].image}{"\n"}{end}'
```

Thay `<so>` bằng revision bạn đã ghi ở bước trước. Nếu history chỉ có một revision thì không có gì để quay về, đừng chạy undo.

## Thực hành

1. Viết ba thứ bạn sẽ ghi lại trước khi undo: revision hiện tại, revision đích, và metric.
2. Một lần deploy đã chạy `DROP COLUMN email`. Giải thích vì sao undo image là chưa đủ.
3. Không chạy undo trên cluster dùng chung.

## Kết quả mong đợi

Bạn có một vòng xử lý rõ ràng: ghi số, undo một lần, đo lại bằng cùng metric. Bạn dừng lại nếu số không cải thiện.

## Checklist

- [ ] Có một revision đích cụ thể, không phải "undo cho tới khi hết lỗi".
- [ ] `rollout status` đã xong và image trên Pod khớp với bản cũ.
- [ ] Đo lại bằng đúng request hoặc biểu thức đã dùng lúc lỗi bắt đầu.
- [ ] Schema và worker được xem xét riêng, không giả định image web là toàn bộ hệ thống.

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

**Undo xong lại sửa luôn bản mới và deploy tiếp trong cùng một giờ.** Hai thay đổi chồng lên nhau. Nếu lỗi vẫn còn, bạn không biết là undo chưa có tác dụng hay bản sửa lại hỏng tiếp. Hãy để bản cũ chạy ổn định trước, rồi mới đưa lên một thay đổi mới.

**Tin vào pipeline rollback xanh.** Pipeline xanh chỉ nói lệnh đã chạy xong. User hết lỗi hay chưa thì phải nhìn metric.

## Nguồn

1. [Rolling back a Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rolling-back-a-deployment) — `rollout undo` và revision.
2. [Deployment status](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#deployment-status) — khi nào rollout được coi là xong.

## Tiếp theo

[Docker image từ hàng trăm MB xuống vài chục MB](./08-docker-image.md)
