BI mã nguồn mở 8 — Triển khai & chọn công cụ
Từ demo tới production
Bảy bài trước của loạt này đã đi qua toàn bộ vòng đời sử dụng hai công cụ: tổng quan so sánh, Metabase căn bản và nâng cao, Superset căn bản, SQL Lab và trực quan hoá, semantic layer & metric, cuối cùng là governance & bảo mật. Nhưng một dashboard đẹp chạy trên laptop chưa phải là một nền BI. Bài tổng kết này trả lời câu hỏi cuối cùng: làm sao đưa nó vào production ngân hàng một cách bền vững, an toàn, và chọn đúng công cụ ngay từ đầu.
Cả Metabase và Superset đều là ứng dụng web có trạng thái (stateful): chúng lưu định nghĩa dashboard/dataset/user vào một metadata database riêng, và mở kết nối tới warehouse để đọc số liệu. Triển khai đúng là bài toán tách bạch ba lớp lưu trữ này — metadata bền vững, cache tạm thời, và warehouse chỉ đọc — rồi bọc chúng trong hạ tầng có backup, giám sát và scale được.
Triển khai Metabase với Docker Compose
Metabase là công cụ đơn giản hơn để đưa vào production. Ở mức tối thiểu nó chỉ gồm hai thành phần: ứng dụng Metabase (một tiến trình JVM) và metadata DB (PostgreSQL). Tuyệt đối không dùng H2 mặc định cho production — H2 là file embedded, dễ hỏng và không backup an toàn được; đây là lỗi phổ biến nhất khi lên production.
# docker-compose.yml — Metabase production tối thiểu (minh hoạ)
services:
metabase:
image: metabase/metabase:v0.49.x # ghim version cụ thể, không dùng :latest
ports:
- "3000:3000"
environment:
MB_DB_TYPE: postgres
MB_DB_HOST: metadb
MB_DB_PORT: 5432
MB_DB_DBNAME: metabase
MB_DB_USER: metabase
MB_DB_PASS_FILE: /run/secrets/mb_db_pass # secret ngoài, không hardcode
JAVA_TIMEZONE: Asia/Ho_Chi_Minh
depends_on:
metadb:
condition: service_healthy
restart: unless-stopped
metadb:
image: postgres:16
environment:
POSTGRES_DB: metabase
POSTGRES_USER: metabase
POSTGRES_PASSWORD_FILE: /run/secrets/mb_db_pass
volumes:
- metadb-data:/var/lib/postgresql/data # volume bền vững
healthcheck:
test: ["CMD-SHELL", "pg_isready -U metabase"]
interval: 10s
retries: 5
volumes:
metadb-data:
Ba điểm sống còn ở đây: metadata DB nằm trên volume bền vững (mất volume là mất toàn bộ dashboard), mật khẩu đến từ secret ngoài chứ không hardcode trong YAML, và JAVA_TIMEZONE được set đúng Asia/Ho_Chi_Minh để mọi bucket theo ngày/tháng khớp múi giờ nghiệp vụ.
Triển khai Superset với Docker Compose
Superset phức tạp hơn vì kiến trúc bốn khối như đã mô tả ở bài căn bản. Một triển khai production đầy đủ cần năm dịch vụ:
- superset (web) — ứng dụng Flask/Gunicorn phục vụ UI và API.
- metadata DB (PostgreSQL) — lưu định nghĩa dataset/chart/dashboard/user.
- Redis — vừa làm cache kết quả truy vấn (results backend), vừa làm message broker cho Celery.
- Celery worker — chạy các truy vấn async (SQL Lab query dài) và các job nền.
- Celery beat — scheduler kích hoạt alert & report định kỳ (gửi cảnh báo khi một metric vượt ngưỡng).
# docker-compose.yml — Superset production (minh hoạ, rút gọn)
x-superset-image: &superset-image apache/superset:3.x.x
x-superset-env: &superset-env
DATABASE_HOST: metadb
DATABASE_DB: superset
REDIS_HOST: redis
SUPERSET_SECRET_KEY_FILE: /run/secrets/superset_secret
services:
superset:
image: *superset-image
command: ["gunicorn", "-w", "8", "-b", "0.0.0.0:8088", "superset.app:create_app()"]
environment: *superset-env
ports: ["8088:8088"]
depends_on: [metadb, redis]
worker:
image: *superset-image
command: ["celery", "--app=superset.tasks.celery_app:app", "worker"]
environment: *superset-env
depends_on: [metadb, redis]
beat:
image: *superset-image
command: ["celery", "--app=superset.tasks.celery_app:app", "beat"]
environment: *superset-env
depends_on: [metadb, redis]
metadb:
image: postgres:16
volumes: ["superset-metadb:/var/lib/postgresql/data"]
redis:
image: redis:7
volumes:
superset-metadb:
Không có worker và beat thì SQL Lab async và tính năng alert/report sẽ không hoạt động — đây là lý do nhiều đội "thử Superset thấy chậm/không gửi được alert" chỉ vì chạy thiếu hai service này. Toàn bộ cấu hình chi tiết đặt trong superset_config.py (mount vào container): SQLALCHEMY_DATABASE_URI trỏ metadata DB, CACHE_CONFIG và RESULTS_BACKEND trỏ Redis, CELERY_CONFIG khai báo broker và beat schedule.
Lưu ý build sau proxy công ty. Khi build image trong hạ tầng NCB (proxy SSL-inspecting), pip/npm/apk trong container sẽ báo
CERTIFICATE_VERIFY_FAILEDnếu không tin CA của công ty. Phải copy.crtvào build context vàupdate-ca-certificates(ảnh Debian) hoặc setNODE_EXTRA_CA_CERTS(ảnh Alpine). Đây là bẫy hay gặp khi tự build image thay vì kéo image chính thức.
Kiến trúc triển khai Superset
Sơ đồ cho thấy đường đi của một truy vấn: web nhận request, trả cache-hit từ Redis nếu có; nếu là truy vấn dài, web đẩy job vào Redis, worker chạy trên warehouse rồi trả kết quả về qua results backend. Beat độc lập kích hoạt alert theo lịch. Điểm mấu chốt: cả web lẫn worker đều kết nối warehouse, và warehouse là một read replica — không đụng vào OLTP core banking.
Kubernetes cho quy mô
Khi vượt qua một node, hoặc cần HA (high availability) và khả năng scale co giãn, chuyển sang Kubernetes là lựa chọn tự nhiên. Cả hai công cụ đều có Helm chart chính thức, giúp bung toàn bộ stack thành các Deployment/StatefulSet/Service:
# values.yaml — Superset Helm (minh hoạ, rút gọn)
supersetNode:
replicaCount: 3 # web scale ngang, đứng sau Service/LB
supersetWorker:
replicaCount: 4 # scale worker theo tải async query
supersetCeleryBeat:
enabled: true # beat luôn là 1 replica (tránh trùng lịch)
postgresql:
enabled: false # dùng metadata DB managed bên ngoài, đừng chạy trong cluster
redis:
enabled: true
Nguyên tắc scale khác nhau theo từng lớp: web scale ngang tuỳ số người dùng đồng thời; worker scale theo khối lượng truy vấn async và alert; beat luôn giữ đúng 1 replica — hai beat sẽ kích hoạt trùng lịch, gửi alert nhân đôi. Metadata DB trên K8s nên dùng managed PostgreSQL bên ngoài cluster (dễ backup, khỏi lo StatefulSet/PVC), đừng nhốt nó trong pod. Chi tiết về probe, resource limit, rolling update và HA xem k8s production ops.
Cấu hình quan trọng khi lên production
| Hạng mục | Nguyên tắc | Lý do |
|---|---|---|
| Metadata DB | PostgreSQL managed/HA + volume bền vững, tuyệt đối không SQLite/H2 | Mất metadata = mất toàn bộ dashboard đã dựng |
| Kết nối warehouse | Tài khoản read-only, chỉ SELECT, trỏ read replica | Bảo vệ OLTP core banking khỏi truy vấn phân tích nặng |
| Secret | Kéo từ Vault / K8s Secret / docker secret, không hardcode | Chuẩn tuân thủ, xoay khoá không phải rebuild image |
| Timezone | Set Asia/Ho_Chi_Minh đồng nhất app + warehouse | Bucket theo ngày/tháng khớp múi giờ nghiệp vụ |
| Tiền tệ | Mapping VND/USD ở semantic layer, không trộn trong 1 metric | Cộng gộp sai tiền tệ = báo cáo sai (xem bài 6) |
| TLS | Reverse proxy (Nginx) terminate TLS | Mọi truy cập BI qua HTTPS |
Việc dùng tài khoản warehouse chỉ đọc vừa là chốt bảo mật (chi tiết ở governance & bảo mật và gov access control) vừa là chốt bảo vệ hiệu năng hệ thống nguồn.
Hiệu năng & mở rộng
Bốn đòn bẩy chính để một nền BI ngân hàng không "gục" khi cuối tháng cả phòng cùng mở dashboard:
- Cache Redis. Kết quả chart được cache theo TTL. Một dashboard "Tổng huy động theo chi nhánh" mở 200 lần/ngày chỉ cần chạy warehouse vài lần nếu cache 15–30 phút. Cân bằng độ tươi dữ liệu với tải warehouse.
- Giới hạn truy vấn. Đặt
ROW_LIMITvà query timeout để một truy vấn lỗi không quét cả tỷ dòng làm nghẽn warehouse. Superset cóSQL_MAX_ROWvà timeout cấp app. - Async query. Truy vấn dài chạy qua Celery worker thay vì chặn web request; người dùng không bị treo trình duyệt. Xem thêm mô hình async ở api async performance.
- Đọc từ replica. Toàn bộ truy vấn BI trỏ read replica của warehouse, tách khỏi OLTP. Mô hình replica xem db-opt replication.
Thứ tự ưu tiên khi tối ưu: trước hết đảm bảo đọc từ replica (bảo vệ hệ thống nguồn), rồi cache (giảm số lần chạy), rồi giới hạn + async (chặn truy vấn xấu). Sai lầm thường gặp là nhồi RAM cho app trong khi nghẽn nằm ở warehouse.
Backup metadata & nâng cấp
Metadata database là "bộ não" — sao lưu nó là sao lưu toàn bộ công sức dựng dashboard.
-- Backup metadata DB (chạy trên host, KHÔNG phải sandbox — minh hoạ)
pg_dump -Fc -h metadb -U superset superset > superset_meta_$(date +%F).dump
Lịch backup nên hằng ngày, giữ theo chính sách retention của ngân hàng, và test restore định kỳ — một backup chưa từng restore thử là một backup chưa tồn tại. Với nâng cấp version: luôn backup metadata trước, đọc release note (Superset có thể đổi schema metadata và chạy superset db upgrade tự động migrate), nâng cấp trên môi trường staging trước, và ghim version cụ thể trong image (đừng :latest) để rollback được. Nhớ nâng cấp cả web lẫn worker cùng version — lệch version giữa chúng gây lỗi task khó lần.
Vận hành: giám sát & log
Một nền BI production cần được giám sát như mọi dịch vụ khác:
- Health check endpoint (
/health) cho load balancer và K8s liveness/readiness probe. - Metrics: độ trễ query trung vị/p95, tỷ lệ cache-hit, độ dài hàng đợi Celery, số worker bận. Hàng đợi Celery phình liên tục là dấu hiệu thiếu worker.
- Log tập trung: gom log web + worker + metadata DB về một nơi để truy vết một truy vấn chậm hoặc một dashboard lỗi.
Mô hình observability đầy đủ (log/metric/trace, alerting) xem devops observability. Với ngân hàng, thêm audit log truy cập (ai xem dashboard nào, chạy truy vấn gì) là yêu cầu tuân thủ, không phải tuỳ chọn.
Bảng chọn công cụ
Câu hỏi lớn nhất của mọi đội data khi bắt đầu: dùng gì? Bảng dưới tổng hợp tiêu chí thực tế.
| Tiêu chí | Metabase | Superset | Power BI / Looker (thương mại) |
|---|---|---|---|
| Đối tượng chính | Người nghiệp vụ, self-service | Analyst / DE, kỹ thuật | Doanh nghiệp, mixed |
| Chi phí license | Miễn phí (OSS, có bản Pro) | Miễn phí (Apache 2.0) | Trả phí theo user/capacity |
| On-prem / tuân thủ | Self-host tốt | Self-host tốt | Power BI: cloud-first; Looker: cloud |
| Đường cong học | Rất thấp | Trung bình–cao | Trung bình (đội quen công cụ MS/Google) |
| Số loại chart | Vừa đủ | Rất nhiều | Rất nhiều |
| Quy mô / async | Trung bình | Cao (Celery, K8s) | Cao (managed) |
| Semantic layer | Model nhẹ | Metric/dataset | Mạnh (DAX / LookML) |
| Chi phí vận hành | Thấp | Cao (nhiều service) | Thấp (managed) nhưng phụ thuộc vendor |
Tiêu chí quyết định, theo thứ tự thực tế:
- On-prem/tuân thủ. Nếu dữ liệu ngân hàng bắt buộc on-prem (như NCB), loại dần các lựa chọn cloud-only; đây thường là ràng buộc mạnh nhất.
- Kỹ năng đội. Người nghiệp vụ tự phục vụ nhanh → Metabase. Đội DA/DE mạnh SQL, cần nhiều chart và quy mô → Superset.
- Chi phí. OSS không license nhưng tốn công vận hành; thương mại đắt license nhưng nhẹ vận hành. So sánh tổng chi phí sở hữu, không chỉ giá license.
- Quy mô & tính năng. Số người dùng, độ phức tạp semantic layer, nhu cầu async/alert.
Không hiếm ngân hàng chạy cả hai OSS: Metabase cho self-service diện rộng của phòng ban nghiệp vụ, Superset cho dashboard phân tích sâu của đội data. Tham khảo thêm các nền thương mại tại Power BI overview và Looker overview.
Checklist go-live cho nền BI ngân hàng
- Metadata DB: PostgreSQL managed/HA, volume bền vững, không SQLite/H2.
- Backup metadata hằng ngày + đã test restore thành công.
- Kết nối warehouse: tài khoản read-only, trỏ read replica.
- Secret kéo từ vault/secret store, không hardcode.
- TLS bật, truy cập BI chỉ qua HTTPS.
- Timezone
Asia/Ho_Chi_Minh+ mapping tiền tệ VND/USD chuẩn. - (Superset) worker + beat chạy đủ; alert/report test được.
- Cache TTL,
ROW_LIMIT, query timeout đã cấu hình. - Version image ghim cụ thể; quy trình nâng cấp + rollback đã tài liệu hoá.
- Giám sát (health, metrics, log tập trung) + audit log truy cập.
- SSO + phân quyền theo role/RLS đã kiểm thử (xem bài 7).
- (Nếu tự build image) đã tin CA công ty trong build sau proxy.
Use case thực tế
Bối cảnh. NCB đưa Superset lên production phục vụ 120 người dùng: 30 analyst đội data và 90 cán bộ nghiệp vụ xem dashboard "Huy động & tín dụng theo chi nhánh". Trước go-live, dashboard này chạy trực tiếp trên PostgreSQL core, khiến truy vấn OLTP chậm mỗi lần mở báo cáo cuối ngày.
Kiến trúc chốt. Superset chạy trên K8s: 3 web replica sau Nginx (TLS + SSO), 4 Celery worker, 1 beat; metadata DB là PostgreSQL managed HA; Redis cache TTL 20 phút. Warehouse là read replica của core, tài khoản read-only.
Các con số sau 1 tháng.
| Chỉ số | Trước | Sau |
|---|---|---|
| Tải truy vấn lên OLTP core | 100% (trực tiếp) | ~0% (đọc replica) |
| Số lần chạy warehouse cho dashboard chính/ngày | ~200 | ~14 (cache-hit ~93%) |
| p95 thời gian tải dashboard | 9,2s | 1,4s |
| Alert "dư nợ chi nhánh vượt hạn mức" | thủ công | tự động qua beat |
Sự cố & bài học. Tuần đầu, hàng đợi Celery phình vào 8h sáng khi cả phòng cùng mở báo cáo. Nguyên nhân: thiếu worker cho các truy vấn async đồng thời. Scale từ 2 lên 4 worker và bật cache warm-up trước giờ cao điểm đã dứt điểm. Bài học: monitor độ dài hàng đợi Celery là chỉ báo sớm nhất của thiếu năng lực xử lý.
Ghi nhớ
- Metabase production = app + metadata DB (PostgreSQL, không H2). Superset production = app + metadata DB + Redis + Celery worker + beat; thiếu worker/beat là mất async và alert.
- Metadata DB là bộ não — dùng PostgreSQL bền vững, backup hằng ngày và test restore; nâng cấp phải backup trước và ghim version.
- Luôn kết nối warehouse bằng tài khoản read-only trỏ read replica — bảo vệ OLTP core banking.
- Đòn bẩy hiệu năng theo thứ tự: đọc replica → cache Redis → giới hạn truy vấn + async query.
- Kubernetes + Helm cho quy mô/HA: web và worker scale ngang, beat luôn 1 replica, metadata DB dùng managed ngoài cluster.
- Chọn công cụ theo thứ tự: on-prem/tuân thủ → kỹ năng đội → tổng chi phí → quy mô/tính năng. Metabase cho self-service nghiệp vụ, Superset cho phân tích sâu kỹ thuật; nhiều ngân hàng chạy cả hai.
- Cấu hình bắt buộc: secret ngoài, TLS, timezone
Asia/Ho_Chi_Minh, mapping tiền tệ, audit log; nếu tự build image sau proxy công ty phải tin CA.
Bài viết liên quan
Phân biệt ước lượng điểm và ước lượng khoảng, cách xây khoảng tin cậy (CI) bằng margin of error z*·SE / t*·SE, đánh đổi mức 90/95/99%, và cách DIỄN GIẢI ĐÚNG khoảng tin cậy (95% CI không phải xác suất tham số nằm trong khoảng). Có CI cho trung bình và cho tỷ lệ, ảnh hưởng của cỡ mẫu, cùng ví dụ ngân hàng về tỷ lệ nợ xấu và số dư trung bình.
Kimball dimensional modeling: bảng fact/dimension, star vs snowflake, grain, và Slowly Changing Dimension.
Khối OLAP, các thao tác drill-down/roll-up/slice & dice/pivot, OLAP vs OLTP và ROLAP/MOLAP/HOLAP.
Từ nguồn dữ liệu qua ETL/ELT vào Data Warehouse, Data Mart đến dashboard; staging, ODS, batch vs streaming.