Header Ads Widget

Chuyển Qdrant sang server mới bằng Docker, khôi phục dữ liệu và cấu hình API Key bảo mật

Qdrant là một Vector Database mã nguồn mở, được sử dụng phổ biến trong các hệ thống AI, chatbot, RAG (Retrieval-Augmented Generation) và tìm kiếm ngữ nghĩa.


Khi hệ thống có hàng nghìn collections và lượng dữ liệu vector lớn, việc chuyển Qdrant sang server mới không đơn giản chỉ là copy thư mục. Chúng ta cần quan tâm đến tính toàn vẹn của RocksDB, quyền truy cập, tài nguyên hệ thống, Docker và cơ chế xác thực API.

Bài viết này tổng hợp quy trình chuyển Qdrant giữa hai server Linux bằng Docker và rsync, đồng thời hướng dẫn thay đổi API Key, xử lý các lỗi thực tế như Too many open files, Resource temporarily unavailable và API không phản hồi.

1. Mô hình triển khai

Ví dụ chúng ta có hai server:

Thành phầnServer nguồnServer đích
IPSERVER_SOURCE_IP14.225.18.11
SSHPort 65333Port 65333
QdrantDockerDocker
REST API63336333
gRPC63346334
Storage/data/qdrant/data.lienvu.com/data/storage/qdrant/data.fchat.ai
Containerqdrantqdrant_app

Trong ví dụ này, server nguồn chứa 1.414 collections và server đích cần được khởi tạo để phục vụ hệ thống AI.

Mục tiêu:

  • Di chuyển dữ liệu Qdrant sang server mới.

  • Giữ nguyên cấu trúc collections và vector.

  • Hạn chế thời gian gián đoạn dịch vụ.

  • Bảo vệ API bằng token.

  • Tự động khởi động Qdrant sau khi reboot.

  • Kiểm tra dữ liệu trước khi chuyển ứng dụng sang server mới.

2. Kiểm tra Qdrant trên server nguồn

Trước tiên, SSH vào server nguồn và kiểm tra container:

docker ps -a | grep qdrant

Kiểm tra thư mục lưu dữ liệu:

docker inspect qdrant \
  --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'

Ví dụ kết quả:

/data/qdrant/data.fchat.ai -> /qdrant/storage

Kiểm tra phiên bản Qdrant:

docker exec qdrant /qdrant/qdrant --version

Nếu lệnh không phù hợp với image hiện tại, có thể kiểm tra qua API:

curl -H "api-key: $QDRANT_API_KEY" \
  http://127.0.0.1:6333/

Kiểm tra số collections

Nếu Qdrant đã cấu hình API Key, cần lấy key trước khi gọi API.

export QDRANT_API_KEY="$(docker inspect qdrant \
  --format '{{range .Config.Env}}{{println .}}{{end}}' \
  | sed -n 's/^QDRANT__SERVICE__API_KEY=//p' \
  | head -n 1)"

Không in API Key ra terminal hoặc đưa vào log công khai.

Sau đó kiểm tra:

curl -fsS \
  -H "api-key: $QDRANT_API_KEY" \
  http://127.0.0.1:6333/collections \
  | python3 -c '
import json,sys
data=json.load(sys.stdin)
print("Total collections:",len(data["result"]["collections"]))
'

Ví dụ:

Total collections: 1414

Con số này sẽ được sử dụng để đối chiếu sau khi chuyển dữ liệu.

3. Chuẩn bị server mới

Trên server đích, kiểm tra Docker:

docker --version
docker info

Nếu chưa cài Docker, có thể cài bằng repository chính thức phù hợp với hệ điều hành.

Ví dụ với AlmaLinux/RHEL:

dnf install -y dnf-plugins-core

dnf config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo

dnf install -y docker-ce docker-ce-cli containerd.io

systemctl enable --now docker

Tạo thư mục lưu dữ liệu:

mkdir -p /data/storage/qdrant/data.fchat.ai

Kiểm tra dung lượng ổ đĩa:

df -h /data/storage/qdrant

Kiểm tra CPU và RAM:

nproc
free -h

Với hệ thống có nhiều collections, nên chuẩn bị đủ RAM, dung lượng SSD và giới hạn file descriptor phù hợp.

4. Chuyển dữ liệu Qdrant bằng rsync

Qdrant sử dụng RocksDB để lưu dữ liệu. Không nên copy trực tiếp dữ liệu đang bị ghi liên tục vì có thể tạo ra bản sao không nhất quán.

Có hai phương án:

Phương án A: Dừng ghi và đồng bộ storage bằng rsync

Phù hợp khi có thể tạm dừng hệ thống để chuyển server.

Phương án B: Sử dụng Qdrant Snapshot API

Phù hợp khi muốn tạo bản sao nhất quán trong lúc hệ thống vẫn hoạt động. Cần lưu ý snapshot có thời điểm chụp cố định; những thay đổi phát sinh sau đó phải được đồng bộ bổ sung hoặc tạm dừng ghi khi cutover.

Trong bài viết này, chúng ta sử dụng phương án A.

Bước 1: Dừng ghi vào Qdrant nguồn

Tạm dừng các ứng dụng, worker, cronjob hoặc API đang ghi dữ liệu vào Qdrant.

Sau đó dừng container nguồn:

docker stop qdrant

Đảm bảo dữ liệu đã được ghi xuống ổ đĩa trước khi đồng bộ.

Bước 2: Copy dữ liệu sang server đích

Chạy trên server nguồn:

rsync -avhP \
  --timeout=600 \
  -e "ssh -p 65333 \
      -o ServerAliveInterval=30 \
      -o ServerAliveCountMax=10" \
  /data/qdrant/data.fchat.ai/ \
  root@14.225.18.11:/data/storage/qdrant/data.fchat.ai/

Giải thích:

  • -a: Giữ cấu trúc thư mục, quyền và thời gian sửa đổi.

  • -v: Hiển thị thông tin.

  • -h: Hiển thị dung lượng dễ đọc.

  • -P: Hiển thị tiến độ và hỗ trợ tiếp tục file truyền dở.

  • --timeout=600: Tránh chờ vô hạn khi kết nối bị treo.

  • -e ssh: Sử dụng SSH để truyền dữ liệu an toàn.

Lưu ý dấu / cuối đường dẫn nguồn. Nó có nghĩa là copy nội dung bên trong thư mục.

Nếu quá trình bị ngắt, có thể chạy lại lệnh rsync.

Bước 3: Kiểm tra dữ liệu sau khi chuyển

Trên server đích:

du -sh /data/storage/qdrant/data.lienvu.com

find /data/storage/qdrant/data.lienvu.com/collections \
  -mindepth 1 -maxdepth 1 -type d | wc -l

Số thư mục collection có thể khác số collections được API công nhận, vì vậy không nên chỉ dựa vào số thư mục để kết luận dữ liệu đã đầy đủ.

Để đối chiếu lần cuối, khi Qdrant nguồn đã dừng và dữ liệu không còn thay đổi, có thể chạy rsync ở chế độ kiểm tra:

rsync -avhn --delete \
  -e "ssh -p 65333" \
  /data/qdrant/data.lienvu.com/ \
  root@14.225.18.11:/data/storage/qdrant/data.lienvu.com/

Tham số -n chỉ mô phỏng, không thay đổi dữ liệu.

Không dùng --delete trong lệnh đồng bộ thật nếu chưa chắc chắn server nguồn là bản dữ liệu chuẩn duy nhất.

5. Khởi tạo Qdrant Docker trên server mới

Để bảo mật, chỉ mở REST API và gRPC trên localhost.

Trên server đích, tạo thư mục cấu hình:

mkdir -p /etc/qdrant
chmod 700 /etc/qdrant

Tạo API Key mới

Sử dụng OpenSSL:

openssl rand -hex 32

Lệnh này tạo token ngẫu nhiên có độ dài 64 ký tự hexadecimal.

Lưu token vào file cấu hình riêng:

read -rsp "Nhap Qdrant API Key: " QDRANT_API_KEY
echo

printf 'QDRANT__SERVICE__API_KEY=%s\n' "$QDRANT_API_KEY" \
  > /etc/qdrant/qdrant.env

chmod 600 /etc/qdrant/qdrant.env

unset QDRANT_API_KEY

Không lưu token trong Git hoặc đưa trực tiếp vào source code.

Khởi tạo container

Ví dụ sử dụng Qdrant 1.14.1, là phiên bản được dùng trong quá trình chuyển thực tế:

docker run -d \
  --name qdrant_app \
  --restart unless-stopped \
  --cpuset-cpus="0-7" \
  --ulimit nofile=1048576:1048576 \
  --env-file /etc/qdrant/qdrant.env \
  -p 127.0.0.1:6333:6333 \
  -p 127.0.0.1:6334:6334 \
  -v /data/storage/qdrant/data.lienvu.com:/qdrant/storage:Z \
  qdrant/qdrant:v1.14.1

Giải thích cấu hình:

Tham sốCông dụng
--restart unless-stoppedTự khởi động sau reboot
--cpuset-cpus="0-7"Giới hạn CPU affinity về 8 CPU
--ulimit nofile=1048576:1048576Tăng giới hạn file descriptors
--env-fileNạp API Key từ file
-p 127.0.0.1:6333:6333Chỉ mở REST API nội bộ
-p 127.0.0.1:6334:6334Chỉ mở gRPC nội bộ
:ZThiết lập SELinux label phù hợp cho bind mount trên hệ thống có SELinux

Nếu image Qdrant nguồn sử dụng phiên bản khác, cần xác minh tính tương thích trước khi chuyển. Không nên đồng thời nâng cấp phiên bản và chuyển dữ liệu khi chưa có bản sao lưu.

6. Xử lý lỗi Too many open files

Trong quá trình khôi phục nhiều collections, Qdrant có thể gặp lỗi:

Too many open files

Nguyên nhân thường là giới hạn file descriptors quá thấp so với số file RocksDB cần mở.

Kiểm tra:

docker exec qdrant_app sh -c \
  'cat /proc/1/limits | grep "Max open files"'

Cấu hình đề xuất để thử nghiệm:

--ulimit nofile=1048576:1048576

Kết quả:

Max open files 1048576 1048576 files

Nếu container đã tạo, việc thay đổi ulimit thường cần tạo lại container với cấu hình mới. Trước khi thực hiện, phải lưu đầy đủ cấu hình Docker hiện tại.

7. Xử lý lỗi Resource temporarily unavailable

Một lỗi khác có thể gặp khi khôi phục số lượng lớn collections:

terminate called after throwing an instance of 'std::system_error'
what(): Resource temporarily unavailable
Aborted (core dumped)

Lỗi này có thể xuất hiện khi hệ thống không tạo được thêm thread hoặc không cấp phát được tài nguyên cần thiết.

Kiểm tra:

docker inspect qdrant_app \
  --format 'Status={{.State.Status}} RestartCount={{.RestartCount}}'

Kiểm tra tài nguyên:

docker stats --no-stream qdrant_app
free -h

Kiểm tra giới hạn PID:

docker exec qdrant_app sh -c '
cat /sys/fs/cgroup/pids.max
cat /sys/fs/cgroup/pids.current
cat /sys/fs/cgroup/pids.events
'

Kiểm tra giới hạn Docker:

systemctl show docker.service \
  -p TasksMax \
  -p LimitNPROC \
  -p LimitNOFILE

Giới hạn CPU để giảm mức song song

Trong trường hợp server có 88 CPU và Qdrant phải khôi phục hơn 1.400 collections, có thể thử giảm CPU affinity:

docker update --cpuset-cpus="0-7" qdrant_app

Kiểm tra:

docker exec qdrant_app nproc

Kết quả dự kiến:

8

Đây là biện pháp thử nghiệm để giảm mức song song, không phải giải pháp bảo đảm cho mọi lỗi tạo thread.

Sau khi khôi phục ổn định, có thể tăng dần CPU:

docker update --cpuset-cpus="0-15" qdrant_app

Không nên restart liên tục khi Qdrant đang khôi phục dữ liệu bình thường.

8. Kiểm tra Qdrant đã khởi động thành công

Theo dõi log:

docker logs -f --tail 50 qdrant_app

Khi thành công, có thể xuất hiện:

Qdrant HTTP listening on 6333
Qdrant gRPC listening on 6334

Kiểm tra API Key:

export QDRANT_API_KEY="$(
  sed -n 's/^QDRANT__SERVICE__API_KEY=//p' \
  /etc/qdrant/qdrant.env
)"

Kiểm tra readiness:

curl -fsS \
  -H "api-key: $QDRANT_API_KEY" \
  http://127.0.0.1:6333/readyz

Kết quả thành công:

all shards are ready

Kiểm tra collections:

curl -fsS \
  -H "api-key: $QDRANT_API_KEY" \
  http://127.0.0.1:6333/collections \
  | python3 -c '
import json,sys
d=json.load(sys.stdin)
print("Collections:",len(d["result"]["collections"]))
'

Trong lần triển khai thực tế, server mới đã khởi động thành công với 1.413 collections và API trả về HTTP 200.

Lưu ý: Readiness thành công không tự động chứng minh mọi point đều đã được chuyển đầy đủ. Nếu yêu cầu khôi phục chính xác, cần đối chiếu danh sách collections, số point và dữ liệu quan trọng.

9. Hướng dẫn thay đổi mật khẩu / API Key Qdrant

Qdrant không sử dụng mật khẩu tài khoản theo cách thông thường. Trong cấu hình này, chúng ta dùng API Key để xác thực các request.

Để thay đổi API Key, cần cập nhật đồng bộ cả Qdrant và các ứng dụng đang kết nối.

Bước 1: Tạo token mới

openssl rand -hex 32

Bước 2: Cập nhật file cấu hình

read -rsp "Nhap API Key moi: " NEW_QDRANT_KEY
echo

printf 'QDRANT__SERVICE__API_KEY=%s\n' "$NEW_QDRANT_KEY" \
  > /etc/qdrant/qdrant.env

chmod 600 /etc/qdrant/qdrant.env
unset NEW_QDRANT_KEY

Bước 3: Tạo lại container với cấu hình mới

Quan trọng: docker restart không tự nạp lại nội dung --env-file đã thay đổi. Cần tạo lại container để áp dụng API Key mới.

Trước khi thực hiện, đảm bảo đã ghi lại cấu hình container, đường dẫn mount, CPU, ports và phiên bản image.

docker inspect qdrant_app > /root/qdrant-container-backup.json

Dừng và xóa container cũ:

docker stop qdrant_app
docker rm qdrant_app

Sau đó chạy lại lệnh docker run ở mục 5 với file qdrant.env mới.

Việc xóa container không xóa dữ liệu trong bind mount, nhưng cần tuyệt đối tránh xóa thư mục storage hoặc dùng lệnh xóa volume khi chưa xác minh.

Bước 4: Kiểm tra token mới

export QDRANT_API_KEY="$(
  sed -n 's/^QDRANT__SERVICE__API_KEY=//p' \
  /etc/qdrant/qdrant.env
)"

curl -fsS \
  -H "api-key: $QDRANT_API_KEY" \
  http://127.0.0.1:6333/collections

Nếu thành công, API trả về JSON chứa danh sách collections.

Nếu token không hợp lệ:

HTTP 401
Must provide an API key or an Authorization bearer token

Bước 5: Cập nhật ứng dụng

Ví dụ cấu hình môi trường Node.js:

QDRANT_URL=http://127.0.0.1:6333
QDRANT_API_KEY=YOUR_NEW_API_KEY

Với ứng dụng chạy trên server khác, cần sử dụng kết nối riêng an toàn như VPN hoặc reverse proxy HTTPS có xác thực.

Sau khi đổi key, cập nhật tất cả dịch vụ sử dụng Qdrant, sau đó kiểm tra lại các chức năng AI, chatbot và tìm kiếm vector.

Lưu ý: Thay đổi API Key theo cách này gây gián đoạn ngắn và vô hiệu hóa key cũ. Nên thực hiện trong cửa sổ bảo trì hoặc có phương án chuyển đổi phù hợp.

10. Truy cập Qdrant Dashboard từ máy tính

Nếu Docker chỉ bind cổng 6333 vào localhost, không thể truy cập trực tiếp bằng IP public.

Cách an toàn nhất là SSH Tunnel.

Trên máy tính cá nhân:

ssh -p 65333 \
  -L 6333:127.0.0.1:6333 \
  root@14.225.18.11

Sau đó mở trình duyệt:

http://localhost:6333/dashboard

Giữ kết nối SSH trong khi sử dụng Dashboard.

Nếu muốn truy cập qua tên miền, có thể cấu hình Nginx reverse proxy với HTTPS, đồng thời giới hạn IP hoặc bổ sung xác thực.

Không nên công khai trực tiếp cổng 6333 và 6334 ra Internet.

11. Cập nhật dữ liệu sau khi chuyển server

Trong một số hệ thống, ứng dụng có thể tiếp tục ghi vào server Qdrant cũ trong thời gian chuyển đổi.

Khi đó, dữ liệu giữa hai server có thể khác nhau.

Ví dụ:

  • Server nguồn: 1.414 collections.

  • Server đích: 1.413 collections.

Điều này cho biết số collections khác nhau, nhưng không phản ánh toàn bộ chênh lệch point.

Một collection cũ vẫn có thể nhận thêm nhiều vector mà số lượng collections không thay đổi.

Không nên dùng rsync để ghi đè thư mục RocksDB của Qdrant đang hoạt động.

Các phương án phù hợp gồm:

  • Dừng ghi, dừng container và đồng bộ lại storage từ nguồn chuẩn.

  • Sử dụng Qdrant Snapshot API để sao lưu và phục hồi collection.

  • Đồng bộ dữ liệu ở cấp ứng dụng hoặc point ID nếu hai server đều đã nhận cập nhật.

Nếu chỉ một server nhận ghi, có thể thực hiện cutover có kiểm soát để tránh xung đột.

12. Các lệnh quản trị Qdrant thường dùng

Xem container:

docker ps -a | grep qdrant

Xem log:

docker logs --tail 100 qdrant_app

Theo dõi tài nguyên:

docker stats qdrant_app

Kiểm tra tự khởi động:

docker inspect qdrant_app \
  --format '{{.HostConfig.RestartPolicy.Name}}'

Kiểm tra mount:

docker inspect qdrant_app \
  --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'

Kiểm tra CPU affinity:

docker inspect qdrant_app \
  --format '{{.HostConfig.CpusetCpus}}'

Kiểm tra giới hạn file:

docker exec qdrant_app sh -c \
  'cat /proc/1/limits | grep "Max open files"'

Kiểm tra trạng thái API:

curl -sS -o /dev/null \
  -w "HTTP %{http_code}\n" \
  -H "api-key: $QDRANT_API_KEY" \
  http://127.0.0.1:6333/collections

13. Checklist trước khi đưa Qdrant vào production

  • Đã sao lưu dữ liệu nguồn.

  • Đã kiểm tra phiên bản Qdrant tương thích.

  • Đã xác định đúng thư mục storage.

  • Đã đồng bộ dữ liệu từ trạng thái nhất quán.

  • Đã thiết lập giới hạn file descriptors phù hợp.

  • Đã cấu hình API Key đủ mạnh.

  • Đã giới hạn truy cập mạng.

  • Container tự khởi động sau reboot.

  • /readyz trả về trạng thái sẵn sàng.

  • API /collections hoạt động.

  • Đã kiểm tra dữ liệu và point quan trọng.

  • Đã cập nhật cấu hình các ứng dụng sử dụng Qdrant.

  • Đã thử nghiệm chức năng AI thực tế.

  • Chưa xóa dữ liệu server cũ trước khi xác minh hoàn tất.

Kết luận

Chuyển Qdrant sang server mới bằng Docker và rsync là phương án phù hợp khi cần di chuyển một hệ thống Vector Database có nhiều collections, đặc biệt khi có thể tạm dừng ghi trong thời gian chuyển đổi.

Ba vấn đề cần quan tâm nhất là:

  1. Tính toàn vẹn dữ liệu: Không copy nóng RocksDB bằng rsync khi dữ liệu đang thay đổi.

  2. Tài nguyên hệ thống: Cấu hình file descriptors, CPU và giới hạn tiến trình phù hợp khi khôi phục hàng nghìn collections.

  3. Bảo mật: Sử dụng API Key mạnh, quản lý token ngoài source code và không mở Qdrant trực tiếp ra Internet.

Với hệ thống AI sử dụng Qdrant làm Vector Database, một quy trình chuyển đổi được kiểm soát sẽ giúp giảm rủi ro mất dữ liệu, hạn chế downtime và duy trì hoạt động ổn định sau khi chuyển server.

Nhận xét