Giữa “chạy được trên máy tôi” và “chạy được trên production” luôn có một khoảng cách, và hệ thống giám sát lẽ ra phải lấp được khoảng cách đó. Nhưng phần lớn thời gian nó không làm được, vì người ta xây nó như một công cụ cho đội vận hành, chứ không phải thứ lập trình viên tìm tới khi có gì đó hỏng.
Tôi vừa chuyển sang làm việc tự do (freelance) mảng DevOps và hạ tầng, và ở bất cứ nơi nào tôi đặt chân tới, hệ thống giám sát luôn là một trong những thứ đầu tiên tôi xem xét — nó cho bạn biết về một đội còn nhiều hơn cả tệp README. Kiểu thất bại gần như lúc nào cũng giống nhau: công cụ thì có đủ, nhưng chẳng khớp gì với cách lập trình viên thật sự làm việc. Có người mất ba tiếng cho một lỗi mà nếu xem nhật ký (log) trên production thì năm phút là xong. Sự cố được phát hiện qua phiếu yêu cầu hỗ trợ (ticket) thay vì qua cảnh báo. Hoặc ngược lại: mỗi ngày có tới 200 cảnh báo, phần lớn là nhiễu, nên ai cũng phớt lờ tất cả, và nửa tiếng đầu của mỗi sự cố chỉ để tìm xem cái gì bị hỏng, thay vì bắt tay vào sửa.
Chỉ số (metric), nhật ký và truy vết (trace) — không liên kết với nhau thì cũng vô dụng#
Chỉ số cho bạn biết có gì đó không ổn (tỷ lệ lỗi tăng vọt, độ trễ nhảy lên). Nhật ký cho bạn biết chuyện gì đã xảy ra (stack trace, dữ liệu mà yêu cầu gửi kèm, thông báo lỗi). Truy vết cho bạn biết lỗi nằm ở đâu (dịch vụ nào, endpoint nào, câu truy vấn cơ sở dữ liệu nào). Mấy điều này chẳng có gì mới. Điều quan trọng là chúng có được liên kết với nhau hay không: khi một cảnh báo bắn ra, bạn phải bấm được từ chỉ số sang đúng đoạn nhật ký liên quan, rồi từ đó sang dữ liệu truy vết. Nếu lập trình viên vẫn phải tự dò khớp dấu thời gian giữa ba công cụ khác nhau, thì hệ thống đó đã thất bại, cho dù trên giấy tờ từng công cụ trông tốt đến đâu.
Bảng điều khiển (dashboard) cũng phải qua bài kiểm tra tương tự. CPU, bộ nhớ và I/O ổ đĩa quan trọng khi lên kế hoạch dung lượng, nhưng chẳng giúp ai gỡ lỗi một phản hồi 500. Những bảng điều khiển mà mọi người tự nguyện mở ra thường đặt chỉ số kinh doanh cạnh chỉ số kỹ thuật (số lượt đăng ký mỗi giờ bên cạnh tỷ lệ lỗi), đánh dấu các lần triển khai gần đây lên dòng thời gian, liệt kê năm lỗi xuất hiện nhiều nhất trong giờ vừa qua kèm liên kết tới nhật ký, và hiển thị độ trễ theo phân vị (percentile) — p50, p95, p99 — thay vì giá trị trung bình. Một bảng điều khiển mà không ai tự mở ra nếu không bị nhắc thì chẳng đáng giữ lại.
Cảnh báo cũng vậy. Mỗi cảnh báo phải trả lời được hai câu hỏi: cái gì đang hỏng, và tôi nên bắt đầu tìm từ đâu?
Cảnh báo tệ: “High CPU on web-server-3”
Cảnh báo tốt: “Error rate > 5% on /api/payments since 14:32. Last deploy: 14:15 by @sarah. [View logs] [View trace]”
Có vài cách giúp cảnh báo nghiêng về loại thứ hai: cảnh báo khi số liệu lệch khỏi mức nền (baseline) thay vì dựa vào một ngưỡng đặt tùy tiện; định tuyến theo người phụ trách (lỗi thanh toán thì gửi tới đội thanh toán, chứ không phải cả công ty); và gom các lỗi liên quan vào một tin nhắn Slack thay vì 50 tin. Vòng phản hồi cũng phải thật ngắn — từ lúc “có gì đó hỏng” đến lúc “lập trình viên biết chuyện” nên dưới một phút. Muốn vậy thì cần truyền nhật ký theo thời gian thực thay vì gom theo lô năm phút một lần, có dấu mốc triển khai (deploy marker) trên mọi bảng điều khiển, và luồng truy vết không bị đứt khi đi qua ranh giới giữa các dịch vụ.
Xây cho chính những người sẽ dùng#
Sai lầm lớn nhất của các đội vận hành là xây hệ thống giám sát cho chính mình. Cách sửa cũng chẳng có gì cao siêu. Hãy ngồi cạnh một lập trình viên trong lúc họ gỡ lỗi và xem họ bị kẹt ở đâu. Hỏi xem giữa lúc có sự cố thì họ hay đặt ra những câu hỏi nào — “dịch vụ nào?”, “vừa thay đổi cái gì?”, “yêu cầu lúc đó trông ra sao?”. Tìm hiểu xem chỉ số nào thật sự quan trọng với sản phẩm; hiếm khi là CPU, mà thường là những thứ như tỷ lệ hoàn tất thanh toán (checkout) hay tỷ lệ tải lên thành công.
Sau đó, gỡ bỏ những chỗ gây vướng víu. Nếu gắn mã đo đạc (instrumentation) cho một dịch vụ mới mà mất cả ngày, sẽ chẳng ai làm. Hãy cung cấp thư viện tự động gắn đo đạc cho các framework đang dùng (Django, Express, Spring), các mẫu bảng điều khiển và cảnh báo để sao chép dùng ngay, và cơ chế để lập trình viên tự thêm chỉ số mà không phải gửi ticket. Và hãy quản lý toàn bộ hệ thống như mã nguồn: cấu hình nằm trong hệ thống quản lý phiên bản (version control), các quy tắc cảnh báo được kiểm thử để chắc chắn chúng bắn ra đúng lúc, và nếu sau này định chạy trên nhiều vùng (multi-region) thì tính tới từ sớm.
Đội nhỏ dùng AWS? Bắt đầu với CloudWatch#
Nếu đội của bạn dưới 50 kỹ sư và đang dùng AWS, CloudWatch là điểm khởi đầu hợp lý, và tôi sẽ cố nhịn không mua thứ gì xịn hơn ngay từ ngày đầu. EC2, Lambda, RDS và ECS đều tự động đẩy dữ liệu về đó, nên bạn quan sát được hệ thống ngay mà không phải viết mã đo đạc. Với một đội nhỏ, chi phí rơi vào khoảng $10–50 mỗi tháng, không có phí nền tảng, và chỉ số, nhật ký, truy vết (qua X-Ray) cùng cảnh báo (alarm) đều nằm chung một chỗ. Chỉ trong một buổi chiều là bạn đã dựng xong những cảnh báo và bảng điều khiển có ý nghĩa, chứ không phải mất vài tuần.
Phần ít được để ý nhưng rất đáng dùng là CloudWatch Logs Insights — bạn truy vấn được nhật ký mà không cần dựng Elasticsearch:
fields @timestamp, @message
| filter @message like /ERROR/
| stats count() by bin(5m)Ngoài ra còn có:
- Composite alarm giúp giảm nhiễu — chỉ cảnh báo khi tỷ lệ lỗi cao và thời gian phản hồi cũng chậm đi, thay vì cảnh báo riêng cho từng điều kiện.
- Chỉ số tùy chỉnh (custom metric) mới là chỗ mang lại giá trị thật. Hãy đẩy chỉ số kinh doanh (lượt đăng ký, giao dịch, mức độ sử dụng tính năng) qua CloudWatch SDK, song song với các chỉ số hạ tầng.
- CloudWatch Synthetics chạy các bài kiểm tra tự động (canary) theo lịch, đi qua các luồng thao tác thật của người dùng, để bạn biết luồng thanh toán bị hỏng trước khi người dùng phát hiện ra.
- X-Ray cho bạn khả năng truy vết phân tán (distributed tracing) mà gần như không tốn công thiết lập — đủ tốt cho phần lớn kiến trúc vi dịch vụ (microservice).
Bạn sẽ tự biết lúc nào mình đã vượt quá khả năng của nó: khi chuyển sang dùng nhiều nền tảng đám mây (multi-cloud), khi cần phát hiện bất thường cho ra hồn, khi việc tùy biến bảng điều khiển bắt đầu thành cực hình, hoặc khi đội vượt quá 50 kỹ sư và cần các tính năng cộng tác thật sự.
Đội lớn hơn: DataDog#
DataDog đắt — với một tổ chức lớn, $20–100K+ mỗi năm là chuyện bình thường — nhưng ở quy mô lớn thì nó đáng đồng tiền. Bạn có một góc nhìn chung bao quát cả AWS, Azure, GCP, hạ tầng tại chỗ (on-prem), container, serverless, cơ sở dữ liệu và phía giao diện (frontend). Watchdog tự đánh dấu các bất thường mà không cần tinh chỉnh ngưỡng bằng tay, và điều này rất quan trọng vì không ai có thể tự canh hàng nghìn dịch vụ bằng mắt. Bạn cũng có được lớp cộng tác mà CloudWatch còn thiếu: bảng điều khiển theo đội, RBAC, sổ tay điều tra (notebook) dùng chung, tích hợp PagerDuty/Opsgenie, cảnh báo nhiều điều kiện, dự báo ngưỡng, cửa sổ bảo trì, và một APM đi sâu tới tận phân tích hiệu năng (profiling) ở cấp mã nguồn, kèm bản đồ dịch vụ (service map) tự động sinh ra.
Về cách triển khai, đại khái theo thứ tự tôi sẽ làm: gắn đo đạc cho các dịch vụ quan trọng trước, và gắn thẻ (tag) mọi thứ theo đội và môi trường ngay từ ngày đầu. Thống nhất sớm quy ước đặt tên, mẫu bảng điều khiển, các mức độ nghiêm trọng và định nghĩa mục tiêu mức dịch vụ (SLO) — để về sau mới áp chuẩn ngược lại thì rất khổ. Nối DataDog với các dấu mốc triển khai từ quy trình CI/CD, hệ thống quản lý sự cố và Slack. Dành thời gian cho việc đào tạo, vì DataDog mạnh nhưng không dễ tự mày mò. Và để mắt tới hóa đơn: lọc bớt các chỉ số nhiễu, lấy mẫu dữ liệu truy vết ở những dịch vụ có lưu lượng lớn, và rà soát xem mình thật sự đang trả tiền cho những tính năng nào.
Trước khi chốt, cũng nên xem qua vài lựa chọn khác: New Relic (tương tự, đôi khi rẻ hơn nếu cần truy vết với lưu lượng lớn), Dynatrace (mạnh về AIOps, được chuộng trong ngành tài chính), Splunk (phân tích nhật ký thuộc hàng tốt nhất, nhất là khi đội bảo mật đã dùng sẵn), và Grafana Cloud (lựa chọn tự nhiên nếu bạn đang dùng Prometheus/Loki).
Trên thực tế, nhiều đội chọn mô hình lai: CloudWatch cho các dịch vụ gốc của AWS vì nó tự động và rẻ, DataDog cho tầng ứng dụng, rồi nạp chỉ số của CloudWatch vào DataDog để có một góc nhìn thống nhất. Chẳng hào nhoáng gì, nhưng chạy tốt.
Bắt đầu từ con số không#
Nếu là tôi, tôi sẽ làm theo thứ tự này. Trước tiên, nói chuyện với lập trình viên xem điều gì làm họ khổ nhất mỗi khi có sự cố. Định nghĩa SLO cho những luồng quan trọng — với đăng nhập, thanh toán, tìm kiếm thì thế nào mới gọi là “đang chạy tốt”? Gắn đo đạc cho những luồng quan trọng đó trước. Tiếp theo là thêm truy vết phân tán; trong kiến trúc vi dịch vụ, đây là khoản đầu tư cho việc gỡ lỗi có ROI cao nhất. Viết tài liệu hướng dẫn xử lý (runbook) cho mỗi cảnh báo, để bạn của lúc 3 giờ sáng biết cần kiểm tra cái gì. Sau đó đặt lịch rà soát mỗi quý để xóa các cảnh báo đã lỗi thời, chỉnh lại các ngưỡng đã bị lệch, và xác nhận bảng điều khiển vẫn khớp với kiến trúc hiện tại.
Còn đây là những cái bẫy mà tôi cứ phải kéo các đội ra mãi: dùng quá nhiều công cụ (ba công cụ phối hợp ăn ý vẫn hơn sáu công cụ rời rạc), biểu đồ không có mức nền (500 rps là bình thường hay là tăng vọt gấp 10 lần?), giám sát những thứ người dùng không hề cảm nhận được (I/O ổ đĩa trên một container không lưu trạng thái), và không có phương án dự phòng cho chính hệ thống giám sát — nếu hệ thống cảnh báo chết giữa lúc đang có sự cố, bạn sẽ mù đúng vào lúc không thể để mù.
Không cần tới công cụ xịn nhất cho bất cứ điều gì ở trên. Điều cần là lập trình viên nhận được đúng thông tin họ cần, ở đúng chỗ họ sẽ nhìn vào, và thật nhanh.
