Chào anh em mình là Hiếu. Tiếp tục issue thực tế mà mình đã gặp (chia sẻ kiểu này cuốn quá nhiều anh em hưởng ứng học ra nhiều cái hay) mình có đăng trong group DevOps VietNam để hỏi ý kiến anh em rồi học hỏi thêm các cách fix tối ưu hơn nữa và cập nhật lại bài viết vừa có một nơi lưu trữ tập trung vừa có thể giúp được anh em vì không phải ai cũng có thể trải qua hết các usecase giúp người, giúp ta cả nhà đều vui (intro quen thuộc😀)
Nội dung
Hệ thống CI/CD bị nghẽn toàn bộ do lỗi trong cơ chế pipeline orchestration và quản lý metadata
Bài toán
Hệ thống CI/CD trên nền Kubernetes có khoảng 100 pipelines chạy song song trong giờ cao điểm. Dữ liệu build metadata của từng pipeline được lưu trên một PostgreSQL cluster và mỗi pipeline sử dụng các GitLab Runners trên cluster để build và deploy.
Biểu hiện
- Các pipelines bị treo khi chạy các stage build Docker image hoặc deploy Helm charts.
- PostgreSQL gặp deadlock liên tục, CPU load lên đến 90% (Tí ngỏm), không thể xử lý được các truy vấn từ GitLab Runners.
- Các pods của GitLab Runner bị crashloop do memory leak trong container runtime.
- API server của Kubernetes bắt đầu timeout khi chạy các lệnh kubectl.
Nguyên nhân
- Pipeline orchestration overload, các GitLab Runners liên tục ghi metadata build (trạng thái, logs) vào PostgreSQL, gây ra contention cao trên bảng lưu trạng thái pipeline.
- Metadata bloat, một số pipelines chạy các job với output log lớn (~1GB/job), và toàn bộ dữ liệu được lưu trên PostgreSQL mà không có cơ chế cleanup hiệu quả.
- Memory leak trong container runtime, Runner containers sử dụng một phiên bản lỗi của containerd, khiến memory không được giải phóng sau khi job kết thúc.
- Kubernetes control plane bị nghẽn: Số lượng requests từ kubelet (do crashloop) và runners gây quá tải trên API server.
Biện pháp
Các giải pháp fix cũng là kinh nghiệm cá nhân nha (update: mình đã thêm các giải pháp dựa trên ý kiến đóng góp của anh em trên group DevOps VietNam ở bài viết: tại đây nha)
- Tách metadata pipeline ra khỏi PostgreSQL, chuyển sang lưu trên Redis với TTL (time-to-live) để giảm tải truy vấn.
- Dùng cơ chế log aggregation riêng (ELK stack) để lưu logs thay vì lưu logs trong metadata pipeline.
- Tạo health check script giám sát Runners, tự động xoá và restart nếu memory usage vượt quá threshold.
- Thay vì lưu metadata ngay lập tức, cấu hình batch writing để PostgreSQL xử lý truy vấn một cách tuần tự thay vì tranh chấp.
- Dùng tool như kube-burner để test giới hạn control plane, đảm bảo hệ thống chịu được peak load.
Giải pháp của anh em góp ý:
Bác Meme Nguyen
“Mình thấy nguyên nhân chính là do con gitlab server IO bound cao dẫn đến bottleneck impact đến pipeline task runner. Mình thấy gitlab nó có bài gitlab scalability https://docs.gitlab.com/ee/development/scalability.html“
Bác Ciscocert Conquer
– Lead dev phải review sát sao những api , chứ giao junior/fresher code thì sau này thế nào cũng dính chưởng.”
Kết quả
- ostgreSQL CPU giảm từ 90% xuống còn dưới 20% ngay cả trong giờ cao điểm.
- Thời gian chạy pipeline giảm từ khoảng 30 phút xuống còn khoảng 10 phút nhờ cơ chế batch writing và Redis caching.
- Crashloop GitLab Runner giảm hoàn toàn.