→ From Coder to Shipper
From Coder to Shipper · DevOps

Observability

Đừng hay tin web sập từ lời phàn nàn của user. Hãy nhìn thấy chuyện gì đang xảy ra — và được cảnh báo ngay khi nó hỏng.

← / → để chuyển slide · chuyển EN/VI bên dưới

Vấn đề

"Web có bị sập không?"

Không có observability, điều đầu tiên bạn biết về một lần sập là tin nhắn từ một người không dùng được sản phẩm của bạn.

🌐 Web của bạn

Nó lặng lẽ ngừng phục vụ — tiến trình crash, đĩa đầy, deploy hỏng.

→

👤 Một user ghé vào

Họ thấy trang trắng hay lỗi — và giờ <b>họ</b> biết trước cả bạn.

→

📣 Họ báo cho bạn

Email, chat, một tweet. Mất vài phút hay vài giờ — và cả uy tín trong mắt họ.

web hỏng trong im lặng · user là cảm biến duy nhất của bạn · observability xóa bỏ đúng phần đó

Việc của người vận hành

Một câu hỏi, cả ngày dài

Mọi thứ ở chủ đề này đều để trả lời cùng ba điều, nhanh hơn và sớm hơn cả user.

Nó có chạy không?

Một user thật có thể truy cập web ngay lúc này không?

Nó có khỏe không?

Ngay cả khi tải được — nó có chậm, lỗi, hay sắp hết tài nguyên không?

Báo tôi khi nó hỏng

Một thông báo trên điện thoại bạn — trước khi ai khác nhận ra.

1
Phần 1 · Tại sao

Toàn cảnh

Observability trong một câu: biến điều vô hình thành hữu hình — và điều im lặng thành ồn ào.

Thuật ngữ

Ba trụ cột

Bạn hiếm khi cần cả ba phải hoàn hảo — nhưng phải biết mỗi thứ là gì.

📈 Metrics (chỉ số)

Số liệu theo thời gian — requests/giây, độ trễ, CPU, RAM. Dùng xem xu hướng và cảnh báo.

📜 Logs (nhật ký)

Điều gì đã xảy ra — mỗi sự kiện một dòng, kèm thời điểm và nội dung. Dùng đào sâu vào một lỗi cụ thể.

💓 Uptime (trực tuyến)

Có truy cập được không? Một trình kiểm tra ping web theo định kỳ và lên tiếng khi không tới được.

Một bức tranh

Ba câu trả lời cho "đang xảy ra gì?"

App của bạn tạo ra cả ba. Công cụ khác nhau thu thập từng loại — và câu hỏi khác nhau dẫn bạn tới từng loại.

📈 Metrics

"Nó đang thế nào?" — các con số chạy trên dòng thời gian.

→ xu hướng + cảnh báo

📜 Logs

"Chính xác chuyện gì?" — câu chuyện của một request, một lỗi.

→ đào một vấn đề

💓 Uptime

"Nó còn đó không?" — có/không, kiểm tra từ bên ngoài.

→ sập / chạy

hôm nay tập trung uptime + metrics — hai thứ giữ cho web sống

Hai nhiệm vụ

Nhìn thấy nó. Rồi được đánh thức.

Observability gồm hai nửa, phải có cả hai — thiếu một nửa thì chưa đủ.

👁 Nhìn chuyện đang xảy ra

Dashboard các chỉ số, tìm trong logs, trạng thái uptime thời gian thực. Đây là góc nhìn hằng ngày, thảnh thơi.

Trả lời: nó có chậm? tỷ lệ lỗi có tăng? đĩa có sắp đầy?

🚨 Được cảnh báo khi nó hỏng

Một luật theo dõi con số và, khi nó vượt ngưỡng, gửi tin tới điện thoại bạn. Đây là thứ cứu bạn lúc 3 giờ sáng.

Trả lời: tôi phải xem đúng thứ nào ngay bây giờ?

Các nhân vật

Ba công cụ, một việc

Làm quen với các nhân vật trước khi vào truyện. Mỗi thứ làm một việc mà các thứ kia không làm được.

Công cụTrả lờiViệc của nó
Uptime Kuma"Truy cập được không?"Trình kiểm tra tự host, ping web mỗi phút và cảnh báo khi không tới được.
Prometheus"Các con số là gì?"Rút metrics từ các service theo lịch và lưu thành chuỗi thời gian để truy vấn.
Grafana"Cho tôi xem bức tranh"Đọc dữ liệu Prometheus và biến thành dashboard — đồ thị metrics theo thời gian.
"Nếu không nhìn thấy nó, bạn không sửa được — và nếu đang ngủ, bạn chẳng nhìn thấy gì cả."
— toàn bộ lý do observability tồn tại
2
Phần 2 · Uptime

Truy cập được không?

Cảm biến đơn giản nhất, giá trị cao nhất: trình kiểm tra ping web mỗi phút.

Cơ chế

Một trình kiểm tra, nằm ngoài app

Ý chính: trình kiểm tra <b>không phải</b> app của bạn. Nó theo dõi từ bên ngoài, như y tá đo mạch.

⏱ Theo lịch

Mỗi phút (hay cứ vài phút), nó làm điều user thật sẽ làm: mở URL, hoặc ping máy chủ.

📢 Khi thất bại

Nếu request thất bại — bị timeout, mã trạng thái sai, không tới được — nó ghi nhận thời gian sập và bắn cảnh báo.

Vì sao nó đi trước

Vài phút cũng quan trọng

Giám sát uptime là cách rẻ nhất, nhanh nhất để phát hiện kiểu hỏng tệ nhất: sập toàn bộ.

🕐 Phát hiện trong ~1 phút

Kiểm tra mỗi phút nghĩa là sập toàn bộ sẽ lộ ra trong 1 phút — chứ không phải 1 giờ sau.

📱 Cảnh báo tới chỗ bạn

Telegram, Zalo, email, Slack — cảnh báo rơi vào thiết bị mà bạn thật sự hay xem.

📉 Tự chứng minh cho bạn

Lịch sử up/down kèm mốc giờ chính xác — hữu ích cho "nó hỏng lúc nào?" và để tạo niềm tin.

Vì sao Uptime Kuma

Cái dễ nhất

Uptime Kuma là trình kiểm tra uptime mã nguồn mở, tự host. Bạn chạy nó trong một container và nó chạy trong chính stack của bạn.

🏠 Tự host

Một Docker container trên VPS của bạn. Dữ liệu giám sát nằm trên máy bạn, chứ không phải máy người lạ.

🖱 Đơn giản theo thiết kế

Giao diện web: dán URL, chọn loại kiểm tra và chu kỳ, lưu. Không cần học ngôn ngữ config trước.

🔔 Kênh cảnh báo

Telegram, Zalo, email, Slack, Discord… — thêm token bot là bạn được thông báo trên điện thoại.

Chạy nó

Uptime Kuma trong docker compose

Một service, một cổng, một volume cho dữ liệu. Đó là toàn bộ việc triển khai.

docker-compose.yml
services:
  uptime-kuma:
    image: "louislam/uptime-kuma:1"   # the official image
    container_name: uptime-kuma
    restart: unless-stopped              # come back after a reboot
    ports:
      - "3001:3001"                    # your browser -> the web UI
    volumes:
      - kuma-data:/app/data             # heartbeats + settings survive

rồi: docker compose up -d → mở http://your-vps:3001

Thử nó

Chạy trong ba lệnh

Khởi động, kiểm tra nó chạy, và xác nhận web trả lời.

ops@vps — zsh
❯ docker compose up -d uptime-kuma
[+] Running 1/1
✔ uptime-kuma Started
❯ docker compose ps
NAME STATUS PORTS
uptime-kuma Up 0.0.0.0:3001->3001/tcp
❯ curl -sI https://yoursite.com | head -1
HTTP/2 200
Vòng lặp

Kiểm tra → ghi nhận → (có thể) cảnh báo

Vòng lặp nhỏ này, chạy mỗi phút, là toàn bộ sản phẩm.

⏱ Mỗi phút

Uptime Kuma chạy kiểm tra: HTTP GET tới URL của bạn (hoặc ping, TCP, từ khóa).

→

📊 Ghi một nhịp

Kết quả + thời gian phản hồi được lưu → lịch sử uptime và trang trạng thái.

→

🚨 Nếu thất bại

Sau N lần kiểm tra thất bại, đẩy cảnh báo: Telegram / Zalo / email.

thành công = im lặng (bạn không muốn tin nhắn mỗi phút) · thất bại = ồn ào

3
Phần 3 · Metrics

Số liệu theo thời gian

Uptime nói up/down. Metrics nói <i>thế nào</i> — và cảnh báo bạn khi nó vẫn còn chạy.

Đừng nhầm lẫn

Metrics vs logs

Chúng là hai hình dạng dữ liệu khác nhau, và mỗi thứ trả lời một câu hỏi khác.

📈 Metrics — nhịp mạch

Một con số kèm mốc giờ: 42 requests/giây lúc 14:03, độ trễ 180ms lúc 14:04. Nhỏ, rẻ, và rất hợp để vẽ đồ thị và đặt ngưỡng.

📜 Logs — cuốn nhật ký

Một dòng văn bản về một sự kiện: "500 ở /checkout lúc 14:04:11, KeyError: 'card'". Lớn hơn, chi tiết hơn, và hợp để giải thích một lần hỏng cụ thể.

Theo dõi gì

Sáu con số đáng một dashboard

Bạn sẽ không bao giờ học thuộc mọi metrics — sáu con số này bao phủ phần lớn thứ mà người vận hành thật sự theo dõi.

🚀 Tốc độ request

Bao nhiêu request/giây — một cú giảm đột ngột thường báo vấn đề ở phía trước.

⏳ Độ trễ

Một request mất bao lâu. Chậm cũng là vấn đề dù không hề lỗi.

💥 Tỷ lệ lỗi

Tỷ lệ request thất bại (5xx). Con số cần xem kỹ nhất.

🧠 CPU

Bộ vi xử lý bận thế nào — 100% kéo dài nghĩa là có thứ đang xoay vòng hay kẹt.

🧮 Bộ nhớ

Dùng bao nhiêu RAM. Một đường leo chậm trong vài ngày là rò rỉ chờ ngày crash.

💾 Đĩa

Còn bao nhiêu chỗ trống. Đĩa đầy kéo sập cả app khỏe mạnh.

Nói cho Prometheus rút gì

Một scrape_config nhỏ

Prometheus hỏi: "mỗi 15 giây, tới địa chỉ này và lấy /metrics." Đó là toàn bộ config.

prometheus.yml
scrape_configs:
  - job_name: "myapp"             # a named target to scrape
    scrape_interval: 15s              # how often to pull
    metrics_path: /metrics            # the endpoint with the numbers
    static_configs:
      - targets: ["localhost:5000"]  # where the app listens

app của bạn chỉ cần mở một endpoint /metrics — phần kế tiếp

Mô hình pull

Prometheus tự tìm tới bạn

Đây là phần khiến nhiều người bất ngờ: app của bạn <b>không</b> đẩy metrics ra ngoài. Prometheus ghé vào và kéo chúng.

→ App mở ra

Một endpoint HTTP nhỏ (/metrics) mà khi ghé vào, in ra các con số hiện tại dưới dạng văn bản.

← Prometheus kéo

Theo lịch, nó ghé mọi /metrics đã cấu hình, đọc con số, và đóng dấu thời gian vào.

Cơ chế

Vòng kéo, mỗi 15 giây

Không push, không gửi. Prometheus giữ một danh sách địa chỉ /metrics và cứ hỏi, theo lịch.

🌐 App của bạn

Mở /metrics — một trang con số dạng văn bản. Nó không bao giờ gọi về.

GET /metrics →

←kéo

⏲ Prometheus

Ghé mọi target theo lịch, đọc con số, đóng dấu thời gian.

→

🗄 Chuỗi thời gian

Mỗi con số lưu kèm mốc giờ → lịch sử truy vấn được cho dashboard và cảnh báo.

nếu một target biến mất, Prometheus nhận ra cú kéo thiếu — đó cũng là một cảnh báo có sẵn

Hỏi nó một câu

Một truy vấn PromQL

Bạn sẽ không tự viết nhiều thứ này — nhưng hãy nhận ra hình dạng: <b>một metric, một cửa sổ, một hàm</b>.

promql
# how many requests per second, averaged over 5 minutes:
rate(http_requests_total[5m])

# and the p95 latency (95% of requests were faster than this):
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

đừng học thuộc cú pháp — ý tưởng là "metric + khoảng thời gian + thứ bạn muốn"

Lưu thứ gì

Một con số + một mốc giờ

Mọi metrics Prometheus giữ là một chuỗi thời gian: cùng một tên, đo lặp đi lặp lại.

🏷 Một tên + nhãn

http_requests_total{status="200", path="/"} — nhãn cho phép cắt cùng một con số theo nhiều cách.

🔢 Một giá trị

Con số tại khoảnh khắc đó — 42.7, 180, 0.003…

⏱ Một mốc giờ

Lúc đo được. Ba thứ này hợp lại thành một điểm trên đồ thị.

4
Phần 4 · Dashboard & cảnh báo

Grafana: bức tranh

Prometheus có các con số. Grafana biến chúng thành thứ bạn thật sự nhìn chằm chằm.

Ai là ai

Dữ liệu vs dashboard

Một cặp hay xuất hiện khắp nơi — một bên lưu, một bên hiển thị.

🗄 Prometheus — dữ liệu

Bộ não kéo và lưu các con số. Không có giao diện — bạn chủ yếu nói chuyện với nó bằng truy vấn.

📊 Grafana — bức tranh

Giao diện. Chỉ nó vào Prometheus, và nó vẽ đồ thị: độ trễ theo thời gian, lỗi, CPU, RAM.

Thứ bạn sẽ nhìn

Một dashboard trong một cái nhìn

Các panel của metrics, đặt cạnh nhau. Màu xanh nghĩa là khỏe — bạn quét qua trong hai giây.

REQUEST LATENCY (p95) — 6 giờ qua

184 ms → 402 ms ↑

ERROR RATE

0.4% → 3.1%

CPU

88%

một dashboard kể một chuyện: độ trễ tăng, lỗi tăng, CPU leo — có vấn đề, và bạn là người thấy trước

Phần "gọi điện cho tôi"

Cảnh báo: một luật biết gào lên

Dashboard chỉ hữu ích nếu bạn đang nhìn. Cảnh báo hữu ích khi bạn không đang nhìn.

📏 Một ngưỡng

Bạn nói: "nếu tỷ lệ lỗi trên 5% trong hơn 5 phút…" Đó là luật.

📲 Một thông báo

…"rồi gửi tin vào Telegram của tôi." Luật kích hoạt, tin đến, bạn đi xem.

Chuỗi

Con số → luật → điện thoại bạn

Ba mắt xích. Gãy một, chuông báo sẽ im lặng.

🔢 Một metric dịch chuyển

error_rate leo từ 0.4% lên 7% — Prometheus chỉ có con số.

→

📏 Luật khớp

"&gt; 5% trong 5 phút" đúng → cảnh báo vào trạng thái "bắn".

→

📲 Bạn được thông báo

Telegram / Zalo / email: "tỷ lệ lỗi myapp cao — đi xem đi."

luật nằm trong Prometheus · việc gửi có thể dùng lại kênh của Uptime Kuma hay kênh riêng (webhook → bot)

Một khởi đầu hợp lý

Cảnh báo thứ gì

Ít mà ồn tốt hơn nhiều mà im. Bắt đầu với bốn cái này.

Tín hiệuKhi nàoVì sao đau
Web sập3 lần kiểm tra liên tiếp thất bạiKhông ai dùng được gì — cái cảnh báo lớn nhất bạn sẽ cần.
Tỷ lệ lỗi cao&gt; 5% trong 5 phútWeb tải được, nhưng một nhóm user đang hỏng.
Độ trễ caop95 &gt; 1 giây trong 10 phútWeb chậm → user bỏ đi, dù không có lỗi.
Đĩa sắp đầy&gt; 90% đã dùngKéo sập cả app khỏe mạnh; logs + dữ liệu ngừng ghi.
5
Phần 5 · Cả stack

Một VPS, bốn container

Mọi thứ bạn đã gặp, giờ chạy cùng nhau. App của bạn cùng ba cảm biến.

Toàn bộ

App + Uptime Kuma + Prometheus + Grafana

Một file compose, bốn service, bốn cổng trong trình duyệt. Đây là một bộ khung thật, chạy được.

docker-compose.yml
services:
  app:          # your app, exposing /metrics
    image: "myapp:latest"
    ports: ["5000:5000"]
  uptime-kuma:  # is it reachable? (port 3001)
    image: "louislam/uptime-kuma:1"
    ports: ["3001:3001"]
  prometheus:   # pulls app:5000/metrics (port 9090)
    image: "prom/prometheus:latest"
    ports: ["9090:9090"]
    volumes: ["./prometheus.yml:/etc/prometheus/prometheus.yml"]
  grafana:      # reads prometheus, draws dashboards (port 3000)
    image: "grafana/grafana:latest"
    ports: ["3000:3000"]

docker compose up -d → bốn URL nhỏ: :3001, :9090, :3000 — cùng app của bạn ở :5000

Toàn cảnh

Ai nuôi ai

Hai chuỗi độc lập, đều bắt đầu từ app của bạn. Một chuỗi nhanh và đơn giản; một chuỗi đi sâu.

Chuỗi 1 · Uptime — "còn đó không?"

🌐 App của bạn

Phục vụ user ở :5000.

→ping

💓 Uptime Kuma

Kiểm tra mỗi phút từ bên ngoài.

→khi hỏng

📲 Cảnh báo

Telegram / Zalo / email — "nó sập rồi."

Chuỗi 2 · Metrics — "đang thế nào?"

🌐 App của bạn

Mở /metrics — con số dạng văn bản.

←kéo

🗄 Prometheus

Lưu các con số thành chuỗi thời gian.

→đọc

📊 Grafana

Vẽ dashboard bạn nhìn mỗi ngày.

cùng một app, hai con mắt · uptime cho kịch bản tệ nhất, metrics cho mọi thứ ở giữa

Vòng lặp hằng ngày

Người vận hành thật sự làm gì

Observability không phải cài đặt một lần — nó là một vòng lặp ngắn, lặp lại.

  1. 1

    Quét qua dashboard

    Grafana, hai giây: xanh = khỏe. Đó là toàn bộ việc làm vào một ngày tốt.

  2. 2

    Được gọi

    Cảnh báo rơi vào Telegram/Zalo: "tỷ lệ lỗi cao". Giờ bạn đi xem — không phải đoán.

  3. 3

    Đọc bức tranh

    Metrics nào dịch chuyển? Bắt đầu lúc nào? Khớp với một lần deploy không? Dashboard + vài dòng logs trả lời.

  4. 4

    Sửa, rồi xem nó hồi phục

    Ship bản sửa và xem đường cong quay xuống. Đồ thị xác nhận — chứ không phải cảm giác.

Ngoài phạm vi, chủ đích

Những gì không học ở đây

Dưới bề mặt là cả một ngành. Bài này cho bạn tấm bản đồ, chứ không phải lãnh thổ.

🔍 PromQL sâu

Recording rules, đại số histogram, alert rules trong Prometheus — bạn sẽ copy-paste, không tự viết.

🧭 Phát hiện service

Kubernetes, DNS, Consul — cách Prometheus tự tìm target ở quy mô lớn.

📚 Loki & Tempo

Thu thập logs và traces toàn phần — bước kế tiếp khi một dòng log không đủ.

🔀 Định tuyến cảnh báo

Escalation, silences, on-call của Alertmanager — dành cho team, không phải stack đầu tiên của người solo.

Bắt đầu bằng một kiểm tra uptime và một dashboard. Phát triển từ đó — stack phải chứng tỏ được giá trị trước khi bạn thêm gì nữa.
— cách người vận hành thật sự áp dụng observability

Nhìn thấy. Biết. Sửa.

Tiếp theo: giữ đèn sáng — phần còn lại của DevOps