Qdrant 入门系列03 – 在 Rocky Linux 10 和 AlmaLinux 10 上安装 Qdrant

Qdrant 是面向自行部署 AI 系统的开源向量数据库,可用于语义搜索与 RAG 检索。Rocky Linux 10 和 AlmaLinux 10 基于 RHEL 10,适合希望保持系统稳定并启用 SELinux enforcing 的团队。本文提供两条安装路径:使用上游镜像的 Docker CE,以及无守护进程、适合 RHEL 生态的 rootless Podman。

原文全部命令在新克隆的 Rocky Linux 10.1 云镜像上测试,SELinux 始终为 enforcing。AlmaLinux 10 共享 RHEL 10 软件包生态,可采用相同步骤。文章重点说明两个实际问题:云镜像内核与 Docker 所需模块不匹配,以及 rootless Podman 绑定挂载同时需要处理用户命名空间所有权和 SELinux 标签。配套代码位于 c4geeks/qdrant 的 install-rocky 目录;参数含义以 Qdrant 官方文档为准。

开始前的准备

  • Rocky Linux 10 或 AlmaLinux 10,至少 2 GB 内存,并为存储卷预留数 GB 磁盘。
  • 具有 sudo 权限的普通用户。云镜像中的 rocky 用户通常已加入 wheel 组。
  • 可以访问 Qdrant 发行版、Docker CE 软件源和发行版镜像站。
  • 空闲 TCP 端口 6333(REST、Web UI)与 6334(gRPC)。
  • 保持 SELinux enforcing,后续步骤不会要求关闭它。

更新软件包索引并安装辅助工具:

sudo dnf -y install dnf-plugins-core curl jq

方法一:使用 Docker CE

Docker CE 可直接运行上游 Qdrant 镜像。原文测试时 Docker 已提供 RHEL 10 支持,Rocky 和 Alma 可使用对应软件源。

第一步:添加软件源并安装

添加官方 RHEL 软件源,安装引擎与 Compose 插件:

sudo dnf config-manager --add-repo \
  https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf -y install docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin
docker --version

原文环境安装了 Docker 29.x 和 kernel-modules-extra-matched-* 软件包。记下模块包版本,下一步需要与内核对应:

Rocky Linux 10 安装 Docker CE 的终端输出

第二步:启动 Docker 前处理内核不匹配

部分 Rocky 10、Alma 10 云镜像中的运行内核,早于 Docker 安装的匹配模块所需版本。立即启动守护进程时,可能出现:

sudo dockerd 2>&1 | tail -3
# Error initializing network controller: failed to register "bridge" driver:
# iptables --wait -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER:
# Warning: Extension addrtype revision 0 not supported, missing kernel module?

安装与模块匹配的新内核,然后重启:

uname -r
# 6.12.0-124.8.1.el10_1.x86_64  (old kernel still running)

rpm -qa | grep kernel-modules-extra
# kernel-modules-extra-matched-6.12.0-124.56.1.el10_1.x86_64  (newer modules)

sudo dnf -y install kernel kernel-core kernel-modules kernel-modules-core
sudo shutdown -r now

重启后确认运行内核已经更新,再启动 Docker:

uname -r
# 6.12.0-124.56.1.el10_1.x86_64

sudo systemctl enable --now docker
sudo docker run --rm hello-world

错误与恢复过程如下:

内核模块不匹配、升级内核与重启后的恢复过程

如果忽略此项,容易在 Docker 日志上花费大量排查时间;早期教程未必涉及较新的匹配模块软件包。

第三步:使用正确的 SELinux 挂载标签

读取最新 Qdrant 标签,创建存储目录并启动容器。卷参数末尾的 :z 表示重新标记宿主机目录,使容器在 enforcing 模式下能够访问它:

export QDRANT_VERSION=$(curl -s https://api.github.com/repos/qdrant/qdrant/releases/latest | jq -r .tag_name)
echo $QDRANT_VERSION  # v1.18.1 at the time of writing

sudo mkdir -p /var/lib/qdrant/storage

sudo docker run -d \
  --name qdrant \
  --restart unless-stopped \
  -p 6333:6333 -p 6334:6334 \
  -v /var/lib/qdrant/storage:/qdrant/storage:z \
  qdrant/qdrant:${QDRANT_VERSION}  # https://github.com/qdrant/qdrant/releases

验证容器、健康检查和目录的 SELinux 上下文:

getenforce                                  # Enforcing
curl -sf http://localhost:6333/healthz       # healthz check passed
ls -lZ /var/lib/qdrant/storage               # system_u:object_r:var_lib_t:s0

完整过程如下:

SELinux enforcing 下使用 z 标签运行 Qdrant

需要注意,原文测试中的 Docker CE 容器进程使用 spc_t(超级特权容器)SELinux 类型,对绑定挂载的限制较少。该环境中,容器写入文件在重新标记后显示为 var_lib_t,进程本身也未因 SELinux 被阻止访问多数路径。这是该测试环境的观察,不能据此假定 Docker 提供了与下文 Podman 相同的隔离。

方法二:Rootless Podman

Podman 来自 Rocky 与 Alma 基础软件源,不依赖常驻守护进程。rootless 模式以普通用户运行容器,并使用 container_t 类型施加 SELinux 限制,因而会暴露一些 Docker 环境未阻止的绑定挂载错误。Podman 与 Buildah 的基础概念可结合本机发行版文档学习。

第一步:安装 Podman

直接使用 dnf 安装。原文编写时基础软件源提供 Podman 5.6.0:

sudo dnf -y install podman
podman --version
# podman version 5.6.0

第二步:观察首次 rootless 启动的权限错误

Podman 要求明确的完整镜像名称,因此使用 docker.io/qdrant/qdrant:<tag>。先以普通绑定挂载启动,观察错误:

mkdir -p /tmp/qdrant-podman-test
podman run -d --name qdrant-podman \
  -p 7333:6333 \
  -v /tmp/qdrant-podman-test:/qdrant/storage \
  docker.io/qdrant/qdrant:v1.18.1

podman ps -a --filter name=qdrant
# qdrant-podman   Exited (1) 4 seconds ago

podman logs qdrant-podman | tail -1
# Error: Service internal error: Failed to write file:
# Permission denied (os error 13) at path "/qdrant/./storage/..."

容器内 Qdrant 进程的非 root UID,与宿主机目录所有者并不相同。rootless Podman 通过 subordinate UID 范围映射用户,因此容器内 UID 1000 不等同于宿主机 UID 1000,进程会因访问被拒绝而退出:

rootless Podman 因用户命名空间映射导致权限被拒绝

第三步:使用 :z,U 修复挂载

:z 处理 SELinux 标签,:U 将目录所有权调整为容器用户命名空间映射后的 UID。示例将两者结合使用;其中 :U 会实际改变宿主机目录所有权,应只对专用数据目录使用:

podman rm -f qdrant-podman
rm -rf /tmp/qdrant-podman-test
mkdir -p /tmp/qdrant-podman-test

podman run -d --name qdrant-podman \
  -p 7333:6333 \
  -v /tmp/qdrant-podman-test:/qdrant/storage:z,U \
  docker.io/qdrant/qdrant:v1.18.1

curl -sf http://localhost:7333/healthz
# healthz check passed

ls -lZ /tmp/qdrant-podman-test
# system_u:object_r:container_file_t:s0  (correct SELinux label)
# rocky rocky                            (correct UID after :U chown)

修复前后对比如下:

使用 z 和 U 挂载选项后 rootless Podman 正常运行

长期运行时,可在 ~/.config/containers/systemd/qdrant.container 创建 Quadlet 单元,由用户级 systemd 负责重启与日志。原文配套仓库提供了对应模板。

配置防火墙并恢复 Docker 网络规则

原文 Rocky 10 云镜像默认没有 firewalld。若安全策略要求,安装并配置它。默认 public 区域适合公网 VPS 或堡垒机这类环境:

sudo dnf -y install firewalld
sudo systemctl enable --now firewalld
firewall-cmd --get-default-zone     # public

sudo firewall-cmd --permanent --add-port=6333/tcp
sudo firewall-cmd --permanent --add-port=6334/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

原文环境在执行 firewall-cmd --reload 后,Docker 创建的 nftables 规则被清除,导致容器不可达。重新启动 Docker,让其重建网络规则:

sudo systemctl restart docker
curl -sf http://localhost:6333/healthz

完整配置过程如下:

Rocky 10 上通过 firewalld 开放 Qdrant 端口

只允许可信子网时,通过 --source 限定来源:

sudo firewall-cmd --permanent --remove-port=6333/tcp
sudo firewall-cmd --permanent --add-rich-rule=\
  'rule family="ipv4" source address="10.0.0.0/8" port port="6333" protocol="tcp" accept'
sudo firewall-cmd --reload
sudo systemctl restart docker

端到端验证:创建集合并搜索

创建 demo 集合,写入三个带载荷的数据点,再执行相似度查询:

curl -s -X PUT http://localhost:6333/collections/demo \
  -H "Content-Type: application/json" \
  -d '{"vectors":{"size":4,"distance":"Cosine"}}' | jq .

curl -s -X PUT http://localhost:6333/collections/demo/points \
  -H "Content-Type: application/json" \
  -d '{
    "points": [
      {"id":1, "vector":[0.1,0.2,0.3,0.4], "payload":{"city":"Nairobi"}},
      {"id":2, "vector":[0.2,0.3,0.4,0.5], "payload":{"city":"Berlin"}},
      {"id":3, "vector":[0.9,0.8,0.7,0.6], "payload":{"city":"Tokyo"}}
    ]
  }' | jq .

curl -s -X POST http://localhost:6333/collections/demo/points/search \
  -H "Content-Type: application/json" \
  -d '{"vector":[0.15,0.25,0.35,0.45],"limit":3,"with_payload":true}' \
  | jq .

Berlin 与 Nairobi 的向量接近查询,应排在前面;Tokyo 方向相反,排名靠后。得到相同顺序,说明数据写入、索引和查询均已工作:

Rocky Linux 上首次向量搜索结果

打开 Web UI

在浏览器中访问服务器 6333 端口的 /dashboard。Collections 面板应列出刚创建的 demo:

Rocky Linux 上 Qdrant Web UI 的集合面板

升级 Qdrant

更换镜像标签并重建容器即可升级。存储卷保留,因此集合和快照不会因删除容器而丢失:

export QDRANT_VERSION=$(curl -s https://api.github.com/repos/qdrant/qdrant/releases/latest | jq -r .tag_name)
sudo docker pull qdrant/qdrant:${QDRANT_VERSION}  # https://github.com/qdrant/qdrant/releases
sudo docker stop qdrant && sudo docker rm qdrant
sudo docker run -d --name qdrant --restart unless-stopped \
  -p 6333:6333 -p 6334:6334 \
  -v /var/lib/qdrant/storage:/qdrant/storage:z \
  qdrant/qdrant:${QDRANT_VERSION}

rootless Podman 使用 podman pull 后重建容器,并继续保留相同的 :z,U 挂载参数。

故障排查

addrtype revision 0 not supported

这是前述内核与模块不匹配问题。安装 kernel kernel-core kernel-modules kernel-modules-core,重启后再启动 Docker。

short-name resolution enforced but cannot prompt without a TTY

Podman 需要完整镜像名称。将 qdrant/qdrant:tag 改为 docker.io/qdrant/qdrant:tag。

本机可访问,其他主机无法访问

先用 firewall-cmd --list-ports 检查防火墙。若刚执行过 firewall-cmd --reload,再重启 Docker,使其重新写入桥接网络所需的 nftables 规则。

Avatar photo

关于 木子

Email: muzi@vip.rockylinux.cn 微信:VebinLee QQ: 2306867585
Founder of the Rocky Linux Chinese community, MVP、VMware vExpert、TVP, advocate for cloud native technologies, with over ten years of experience in site reliability engineering (SRE) and the DevOps field. Passionate about Cloud Computing、Microservices、CI&CD、DevOps、Kubernetes, currently dedicated to promoting and implementing Rocky Linux in Chinese-speaking regions.
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇