↓ Chuyển đến nội dung chính

DevOps Monitoring Observability

Hệ thống giám sát (monitoring) cho lập trình viên: chỉ số, nhật ký, truy vết và CloudWatch hay Datadog

Cách dựng hệ thống giám sát (monitoring) mà lập trình viên thật sự dùng: liên kết chỉ số, nhật ký và truy vết, viết cảnh báo chỉ rõ nên xem từ đâu, và chọn giữa CloudWatch với Datadog.

Hệ thống giám sát (monitoring) cho lập trình viên: chỉ số, nhật ký, truy vết và CloudWatch hay Datadog

Một hệ thống giám sát (monitoring) dành cho lập trình viên chỉ có một việc: khi có gì đó hỏng, báo ngay cho người cần biết, và cho họ thấy cái gì hỏng, hỏng ở đâu. Muốn vậy thì chỉ số (metric), nhật ký (log) và truy vết (trace) phải được liên kết với nhau, cảnh báo phải chỉ ra nên bắt đầu tìm từ đâu, và bảng điều khiển (dashboard) phải là thứ mọi người tự mở ra mà không cần ai nhắc. Chọn công cụ là chuyện đến sau: nếu chạy trên AWS, đội nhỏ dùng CloudWatch là đủ, còn khi quy mô đã lớn thì Datadog mới đáng tiền.

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.

Bài này nói về cách làm chung. Còn những công cụ tôi thật sự đang dùng cho hai sản phẩm nhỏ thì tôi đã viết riêng ở một bài khác.

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.

Sau khi xây xong, cũng chính những thói quen này giữ cho nó sống. Mã đo đạc đi qua review code như mọi mã production khác, và mỗi chỉ số tự định nghĩa đều có kiểm thử. Mỗi lần mổ xẻ sự cố (postmortem) đều hỏi “giám sát kiểu gì thì đã bắt được chuyện này sớm hơn”, và câu trả lời được đưa vào bảng điều khiển và cảnh báo ngay trong tuần đó, chứ không chỉ nằm trong bản báo cáo. Và vài lần mỗi năm tôi rà lại toàn bộ để xóa những thứ không ai mở, vì một cảnh báo không ai xử lý chỉ tập cho mọi người bỏ qua cảnh báo tiếp theo.

Độ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.

So sánh nhanh CloudWatch và Datadog
#

CloudWatchDatadog
Hợp với aiĐội dưới khoảng 50 kỹ sư, chạy hoàn toàn trên AWSTổ chức lớn, nhiều dịch vụ, dùng nhiều hơn một nền tảng đám mây
Cách tính chi phíDùng bao nhiêu trả bấy nhiêu, không có phí nền tảng; khoảng $10–50 mỗi tháng cho đội nhỏ$20–100K+ mỗi năm là bình thường với tổ chức lớn; phải để mắt tới hóa đơn thường xuyên
Công sức thiết lậpEC2, Lambda, RDS, ECS tự đẩy dữ liệu về; một buổi chiều là có cảnh báo dùng đượcGắn đo đạc cho dịch vụ quan trọng trước, thống nhất sớm thẻ (tag) và quy ước đặt tên, dành thời gian đào tạo
Nhiều nền tảng đám mây (multi-cloud)Xoay quanh AWS; chuyển sang multi-cloud là dấu hiệu đã đến lúc đổiMột góc nhìn chung cho AWS, Azure, GCP, on-prem, container và serverless
Phát hiện bất thườngChủ yếu là cảnh báo bạn tự chỉnh ngưỡng; cần hơn thế cũng là dấu hiệu nên đổiWatchdog tự đánh dấu bất thường, không cần chỉnh ngưỡng bằng tay
Cộng tácKhá mỏng; đội vượt 50 người sẽ thấy thiếuBảng điều khiển theo đội, RBAC, notebook dùng chung, tích hợp PagerDuty/Opsgenie
Truy vếtX-Ray, gần như không tốn công thiết lậpAPM đi sâu tới profiling ở cấp mã nguồn, service map tự sinh

Bắt đầu từ con số không: thứ tự dựng hệ thống giám sát
#

Nếu là tôi, tôi sẽ làm theo thứ tự này:

  1. 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ố.
  2. Đị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”?
  3. Gắn đo đạc cho những luồng quan trọng đó trước.
  4. 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.
  5. Đặt cảnh báo trên chính những luồng đó chứ không phải trên CPU, và gửi từng cảnh báo tới đúng đội phụ trách.
  6. 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ì.
  7. Đặ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.