BI mã nguồn mở 8 — Triển khai & chọn công cụ

13 thg 7, 2026 3 lượt xem
#deployment
#architecture
#bi
#kubernetes
#docker

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ảnnâ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ụ:

  1. superset (web) — ứng dụng Flask/Gunicorn phục vụ UI và API.
  2. metadata DB (PostgreSQL) — lưu định nghĩa dataset/chart/dashboard/user.
  3. Redis — vừa làm cache kết quả truy vấn (results backend), vừa làm message broker cho Celery.
  4. Celery worker — chạy các truy vấn async (SQL Lab query dài) và các job nền.
  5. 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_CONFIGRESULTS_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_FAILED nếu không tin CA của công ty. Phải copy .crt vào build context và update-ca-certificates (ảnh Debian) hoặc set NODE_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ụcNguyên tắcLý do
Metadata DBPostgreSQL managed/HA + volume bền vững, tuyệt đối không SQLite/H2Mất metadata = mất toàn bộ dashboard đã dựng
Kết nối warehouseTài khoản read-only, chỉ SELECT, trỏ read replicaBảo vệ OLTP core banking khỏi truy vấn phân tích nặng
SecretKéo từ Vault / K8s Secret / docker secret, không hardcodeChuẩn tuân thủ, xoay khoá không phải rebuild image
TimezoneSet Asia/Ho_Chi_Minh đồng nhất app + warehouseBucket 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 metricCộng gộp sai tiền tệ = báo cáo sai (xem bài 6)
TLSReverse proxy (Nginx) terminate TLSMọ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ậtgov 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_LIMITquery 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_ROW và 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íMetabaseSupersetPower BI / Looker (thương mại)
Đối tượng chínhNgười nghiệp vụ, self-serviceAnalyst / DE, kỹ thuậtDoanh nghiệp, mixed
Chi phí licenseMiễ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ốtSelf-host tốtPower BI: cloud-first; Looker: cloud
Đường cong họcRất thấpTrung bình–caoTrung bình (đội quen công cụ MS/Google)
Số loại chartVừa đủRất nhiềuRất nhiều
Quy mô / asyncTrung bìnhCao (Celery, K8s)Cao (managed)
Semantic layerModel nhẹMetric/datasetMạnh (DAX / LookML)
Chi phí vận hànhThấpCao (nhiều service)Thấp (managed) nhưng phụ thuộc vendor

Tiêu chí quyết định, theo thứ tự thực tế:

  1. 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.
  2. 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.
  3. 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.
  4. 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 overviewLooker 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ướcSau
Tải truy vấn lên OLTP core100% (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 dashboard9,2s1,4s
Alert "dư nợ chi nhánh vượt hạn mức"thủ côngtự độ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.

13 thg 7, 2026 4

Kimball dimensional modeling: bảng fact/dimension, star vs snowflake, grain, và Slowly Changing Dimension.

13 thg 7, 2026 3

Khối OLAP, các thao tác drill-down/roll-up/slice & dice/pivot, OLAP vs OLTP và ROLAP/MOLAP/HOLAP.

13 thg 7, 2026 3

Từ nguồn dữ liệu qua ETL/ELT vào Data Warehouse, Data Mart đến dashboard; staging, ODS, batch vs streaming.

13 thg 7, 2026 3