Chạy ứng dụng SQLite trên Docker và Kubernetes với Litestream: Giải pháp sao lưu tự động

30 tháng 8, 2026·6 phút đọc

OpenRun, nền tảng GitOps mã nguồn mở, vừa tích hợp sẵn Litestream giúp các ứng dụng SQLite trên Docker và Kubernetes tự động sao lưu liên tục lên S3. Bài viết phân tích cách hoạt động, quy trình khôi phục dữ liệu khi mất volume hoặc toàn bộ node, và cách triển khai chỉ với vài lệnh cấu hình đơn giản.

Chạy ứng dụng SQLite trên Docker và Kubernetes với Litestream: Giải pháp sao lưu tự động

Chạy ứng dụng SQLite trên Docker và Kubernetes với Litestream: Giải pháp sao lưu tự động

OpenRun, nền tảng GitOps mã nguồn mở dành cho việc triển khai ứng dụng web và công cụ nội bộ, vừa công bố tích hợp sẵn Litestream cho các ứng dụng SQLite. Tính năng mới này cho phép sao lưu liên tục dữ liệu của ứng dụng lên S3 hoặc các dịch vụ tương thích như Cloudflare R2, MinIO, và SeaweedFS, đồng thời tự động khôi phục khi phát hiện volume trống hoặc bị xóa. Với giải pháp này, các nhà phát triển có thể sử dụng SQLite như bình thường mà không cần cài đặt thêm Litestream hay viết logic khôi phục thủ công.

Vì sao SQLite lại phù hợp với ứng dụng nội bộ?

SQLite là lựa chọn tuyệt vời cho các công cụ nội bộ và ứng dụng web nhỏ: cơ sở dữ liệu dạng file, tốc độ đọc nhanh, và không cần vận hành một server cơ sở dữ liệu riêng. Tuy nhiên, điểm yếu lớn nhất của SQLite là không có khả năng sao lưu từ xa mặc định. Litestream giải quyết vấn đề này bằng cách liên tục sao chép các thay đổi dữ liệu lên object storage, cung cấp bản sao lưu bền vững ngoài node và khả năng khôi phục theo thời điểm (point-in-time recovery).

Không có sự tích hợp nền tảng, bạn vẫn phải tự triển khai Litestream bên cạnh ứng dụng, cấu hình replica và xử lý việc khôi phục cơ sở dữ liệu khi khởi động. OpenRun chuyển toàn bộ công việc đó vào nền tảng, giúp app image không thay đổi và mọi ứng dụng SQLite mới có thể sử dụng replication ngay lập tức.

Kiến trúc single-node với LitestreamKiến trúc single-node với Litestream

Cách triển khai ứng dụng SQLite với OpenRun

Quá trình thiết lập rất đơn giản. Đầu tiên, định nghĩa Litestream một lần trong file cấu hình server openrun.toml:

[litestream.mainbackup]
bucket = "openrun-backups"
region = "us-east-1"
access_key_id = '{{secret_from "env" "LITESTREAM_KEY_ID"}}'
secret_access_key = '{{secret_from "env" "LITESTREAM_KEY"}}'

Sau đó, tạo một service SQLite tham chiếu cấu hình này và gán ứng dụng vào service:

openrun service create sqlite/main --is-default --config litestream_config=mainbackup
openrun app create --bind sqlite --approve github.com/example/notes-app /notes

Toàn bộ quá trình này cũng có thể được khai báo bằng ngôn ngữ lập trình Starlark (tương tự Kubernetes apply), giúp quản lý ứng dụng theo mô hình GitOps:

app("/notes", "github.com/example/notes-app", bindings=["sqlite"])
openrun apply --promote github.com/example/config/apps.star

Ứng dụng sẽ nhận được một persistent volume gắn tại /data và tìm cơ sở dữ liệu thông qua biến môi trường SQLITE_DB_PATHSQLITE_DIR. Mọi file *.db được tạo trong thư mục này đều được sao lưu, kể cả các file tạo ra trong lúc chạy. Dữ liệu thay đổi thường được đồng bộ trong khoảng 1 giây (có thể cấu hình sync_interval).

Hoạt động trên Single Node và Kubernetes

Trên Docker và Podman, OpenRun chạy Litestream trong một container đồng hành (companion container) chia sẻ volume dữ liệu của ứng dụng. Khi ứng dụng chưa từng khởi động trên volume trống, các restore container sẽ kéo dữ liệu từ replica về trước khi app container khởi động. Nếu ứng dụng scale xuống 0 khi không hoạt động, container Litestream sẽ thực hiện đồng bộ cuối cùng trước khi dừng.

Trên Kubernetes, cùng một cấu hình hoạt động hoàn hảo. Volume của binding trở thành PersistentVolumeClaim, và OpenRun tự động thêm một init container để khôi phục dữ liệu cùng một sidecar Litestream (yêu cầu Kubernetes 1.29 trở lên). Sidecar này khởi động trước app container và kết thúc sau khi app container dừng, cho phép Litestream thực hiện đồng bộ cuối trong quá trình tắt có kiểm soát. Ứng dụng có SQLite binding chạy với một replica duy nhất và chiến lược cập nhật Recreate, ngăn chặn nhiều pod ghi vào cùng một volume trong quá trình cập nhật.

Kiến trúc Kubernetes với LitestreamKiến trúc Kubernetes với Litestream

Khôi phục dữ liệu khi mất volume hoặc toàn bộ node

Khi mất volume ứng dụng, việc khôi phục diễn ra tự động: ở lần khởi động tiếp theo, OpenRun phát hiện volume trống, chạy restore container để kéo dữ liệu về, rồi mới khởi động app container. Replica được gắn với binding, vì vậy nếu gán cùng một binding cho ứng dụng mới, dữ liệu cũng được khôi phục vào volume mới.

Trong trường hợp mất toàn bộ node (với metadata replication được bật), quy trình khôi phục gồm 3 bước:

  1. Cài đặt OpenRun trên máy mới.
  2. Khởi động server với cùng file cấu hình.
  3. Server phát hiện database metadata bị mất, tự động khôi phục metadata và audit databases từ replica, sau đó mỗi ứng dụng sẽ redeploy ở lần request đầu tiên và khôi phục dữ liệu SQLite từ replica riêng của mình.

Điểm mạnh của kiến trúc này là chỉ cần giữ file cấu hình server và các secret liên quan — toàn bộ dữ liệu ứng dụng và metadata đều được khôi phục từ object storage. Replication là bất đồng bộ, với sync_interval mặc định 1 giây, một crash đột ngột có thể mất tối đa khoảng 1 giây dữ liệu chưa kịp đồng bộ.

Quy trình này được kiểm thử end-to-end trong CI: bài test hard-kill server, xóa toàn bộ containers, volumes và thư mục cài đặt, sau đó xác minh mọi thứ được xây dựng lại tự động từ object store.

Giám sát trạng thái replication

Lệnh openrun replication status cung cấp trạng thái chi tiết của mọi cơ sở dữ liệu được sao lưu:

$ openrun replication status -f table
Kind       Target                              Config       State     LastSync             Files      Apps
metadata   metadata                            mainbackup   healthy   2026-08-25 16:31:42  -
metadata   audit                               mainbackup   healthy   2026-08-25 16:31:42  -
app        /auto/app_prd_.../sqlite (prod)     mainbackup   healthy   2026-08-25 23:31:30  data.db    /notes
app        /auto/app_prd_.../sqlite (staged)   mainbackup   pending   -                    -          stage.localhost:/notes

Trạng thái này kết hợp thông tin từ replica listing trên object storage và trạng thái container replication, vì vậy một container replication bị lỗi sẽ hiển thị ngay cả khi object storage vẫn có replica mới. Trạng thái replication cũng có thể xem trực tiếp trong Console App.

Kết luận

Việc tích hợp sẵn Litestream vào OpenRun đánh dấu một bước tiến quan trọng giúp SQLite trở nên "production-ready" hơn trên Docker và Kubernetes. Đây là tin vui đặc biệt cho các nhóm phát triển tại Việt Nam đang tìm kiếm giải pháp đơn giản, chi phí thấp để chạy các ứng dụng web và công cụ nội bộ mà không cần đầu tư vào hạ tầng cơ sở dữ liệu phức tạp. Với mô hình GitOps và khả năng khôi phục tự động, các nhóm có thể tập trung vào phát triển sản phẩm thay vì lo lắng về việc mất dữ liệu.

Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗