Incident review: Service outage on 25 October 2020

Bài tóm tắt GoCardless 2020 3. Quy mô lớn Độ khó: Trung bình

GoCardless · 2020 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc

Bối cảnh

  • GoCardless quản lý secret bằng HashiCorp Vault chạy trên Kubernetes: kỹ sư tự ghi secret (không đọc được), ứng dụng chỉ đọc secret của chính nó theo service account. Vault là phụ thuộc của gần như mọi service production.
  • Chứng chỉ TLS ngắn hạn (Let's Encrypt) được cert-manager tự gia hạn.
  • Secret được nạp vào app qua theatre-envconsul, một lớp bọc envconsul do GoCardless viết. Họ chạy envconsul ở chế độ -once (không daemon) để không restart app khi secret đổi, và đã tắt retry tới Vault vì những vấn đề khác.

Diễn biến

  • 25/10/2020, sập toàn bộ 22 phút (07:32–07:54 GMT): API, dashboard, trang thanh toán.
  • Nguyên nhân gốc rất đơn giản: chứng chỉ TLS của Vault hết hạn. Thực ra cert-manager đã gia hạn, nhưng Vault không tự nạp lại chứng chỉ (cần restart hoặc SIGHUP), và họ chưa có automation cho việc đó.
  • Bộ khuếch đại: dù chạy -once, envconsul vẫn định kỳ gia hạn lease với Vault. Gia hạn thất bại thì nó thoát, kéo theo process app đang khoẻ. Không có retry, nên các pod đang phục vụ traffic chết dần từng cái khi lease hết hạn.
  • Ứng phó:
    • Chẩn đoán sai: tưởng chứng chỉ chưa được gia hạn nên ép cert-manager tạo lại, mất vài phút vì xác thực DNS. Thực ra chỉ cần restart Vault.
    • Sau khi Vault restart, Kubernetes tự hồi phục gần như hoàn toàn. Họ chỉ xoá tay vài pod quan trọng để bỏ qua backoff 5 phút.

Thay đổi

  • Giám sát: đã có cảnh báo hết hạn chứng chỉ cho load balancer tầng 7, nhưng chưa có cho TCP load balancer của Vault. Bổ sung bằng Blackbox exporter.
  • Phòng ngừa: dùng Reloader để rolling restart Vault khi chứng chỉ đổi.
  • Giảm blast radius: envconsul chỉ nạp secret lúc khởi động container, không quản lý process con nữa. Mất kết nối Vault (kể cả network partition) sẽ không giết app đang chạy.

Bài học cho SWE

  • Thành phần ai cũng phụ thuộc là điểm hỏng chung, giống Tenant Service của Cloudflare (Cloudflare 2025). Phụ thuộc lúc khởi động khác hẳn phụ thuộc lúc chạy: chỉ cái sau mới giết được app đang khoẻ.
  • Gia hạn tự động chưa đủ: thành phần dùng chứng chỉ phải nạp lại được; cần đo chứng chỉ thật đang được phục vụ, không chỉ chứng chỉ trong kho.
  • Tắt retry để "dễ đoán" có thể biến lỗi tạm thời thành lỗi chết người.
  • Chẩn đoán vội theo giả định ("chứng chỉ hết hạn thì tạo lại") làm chậm khôi phục (Sự cố và postmortem). Cùng họ sự cố chứng chỉ: Mozilla 2019 (Mozilla 2019).

Liên quan