十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

麒麟V10-SP1离线部署Docker与Milvus向量数据库全流程

麒麟V10-SP1离线部署Docker与Milvus向量数据库全流程 最近在忙信创迁移核心任务是把原本跑在CentOS 7上的应用服务整体搬到银河麒麟高级服务器操作系统V10-SP1上。第一个绕不开的坎就是Docker的离线部署。生产网段不能连外网既不能用yum在线装也不能docker pull拉镜像所有东西都得在隔离环境里手工搬进去。这次要部署的组件里最关键的是Milvus向量数据库——它承担着知识库语义检索和向量召回的功能能不能稳定跑起来直接决定业务是否可用。我把整个部署过程记录下来从离线物料准备、Docker安装、镜像导入到Milvus单机版编排再到SP1上踩过的坑全都摊开讲一遍。1. 信创迁移的整体设计与方案选型1.1 为什么是这个组合麒麟V10-SP1 Milvus银河麒麟V10-SP1是信创环境里最常见的服务器操作系统之一x86_64架构支持很成熟跑主流Docker版本没有问题。Milvus则是当前使用最广的开源向量数据库专门处理海量向量的相似度检索。大模型知识库这类场景先把文档切片做embedding再把向量灌进Milvus查询时做top-K召回比用传统数据库硬扛like查询快几个量级。信创环境下应用要真正落地光有操作系统还不够中间件和数据库这一层必须能离线装、能稳定跑。所以选型就定成麒麟V10-SP1做底座Docker做运行时Milvus提供向量检索能力。这套组合的好处是后面再迁移其他业务时Docker环境是通用的可以把更多组件逐步搬过来不用每个组件都重新解决运行环境问题。有人会问Milvus不是可以在宿主机上直接跑二进制吗理论上可以但Milvus依赖etcd、MinIO等一堆组件版本兼容、动态库、配置文件散落各处排查起来非常痛苦。用Docker做封装以后业务无关的运行细节都被收敛到镜像里迁移的边界就清晰了。1.2 为什么坚持Docker离线部署而不是源码编译我在做方案时也认真想过要不要直接在麒麟SP1上源码编译Milvus。结论是离线环境下源码编译的不可控因素太多。Milvus的主程序、etcd、MinIO、底层依赖库每一层编译都可能因为缺少某个开发包卡住而且信创机器很难临时装这些编译依赖。就算编译成功版本和现有业务验证过的版本有偏差风险也不小。Docker离线部署的核心思路是提前在一台有网的、与目标机器同架构的机器上把安装包和镜像全部准备好打包带到目标环境导入。这个方式的优点很直接环境一致性有保障镜像里把运行时、动态库、配置都固化好了回滚也简单删掉容器换一个镜像就能回到之前版本后续批量分发到多台服务器时复制同样的tar包就能完成。当然Docker本身也需要一些系统软件包这部分要在物料准备阶段提前下载rpm包。不能完全无脑但工作量比源码编译少太多尤其是面对Milvus这种组件较多的项目时省下的时间是很可观的。1.3 离线部署的前置准备清单先把我这次用到的物料清单列出来方便你照着准备一台已经装好银河麒麟V10-SP1的目标服务器x86_64架构建议至少4核8G内存磁盘预留50GB以上。Docker相关rpm包docker-ce、docker-ce-cli、containerd.io、docker-compose-plugin版本我用的20.10.x与1.6.x组合。Milvus镜像与依赖镜像tar包milvusdb/milvus:v2.6.8、quay.io/coreos/etcd:v3.5.5、minio/minio:RELEASE.2023-03-20T20-16-18Z。docker compose独立二进制如果rpm包里的plugin没能生效时备用。一个容量足够的U盘或移动硬盘建议exFAT格式因为镜像tar包动辄几个GBFAT32单文件4GB限制会卡住。可选的pymilvus离线whl包方便在目标机器上直接做连通性测试。这些物料最好集中放在一个目录里比如/data/offline/方便后续校验和管理。2. 离线物料准备工作2.1 在联网机器上准备Docker安装包准备物料需要一台联网的机器架构一定要和目标服务器一致我这里都是x86_64。用yumdownloader可以一次性把rpm包和依赖拉下来yum install -y yum-utils yumdownloader --resolve docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io-1.6.28 docker-compose-plugin-2.21.0如果没有现成的Docker仓库先配置好官方yum源再执行。下载完成后目录里会出现docker-ce、docker-ce-cli、containerd.io、docker-compose-plugin等rpm文件大概率还有libseccomp这类基础依赖。把它们全部带上尤其是libseccomp麒麟SP1上如果版本太低容器启动时会报seccomp相关的权限错误。这里有一个容易踩的细节rpm包不要光拿主包--resolve参数能自动把依赖拉全少了它后面在离线机上装到一半才发现缺包就很被动。2.2 Milvus 2.6.8依赖镜像的下载与导出还是在这台联网机器上先确保Docker能用然后拉取Milvus单机版需要的三个镜像docker pull milvusdb/milvus:v2.6.8 docker pull quay.io/coreos/etcd:v3.5.5 docker pull minio/minio:RELEASE.2023-03-20T20-16-18Z拉完后检查一下docker images确认镜像完整存在后用docker save导出。我习惯合并成一个tar包导入时一次搞定docker save milvusdb/milvus:v2.6.8 quay.io/coreos/etcd:v3.5.5 minio/minio:RELEASE.2023-03-20T20-16-18Z -o milvus-all-images.tar如果你后面需要在多台机器上分别部署也可以拆开save方便按组件分发。但拆开保存会多占用一些磁盘空间因为etcd和minio的基础层在多个tar里会有重复。我建议在一台机器上部署时用合并包在多台机器间分发时分开。2.3 物料转移与文件校验物料准备好以后把rpm目录和镜像tar包复制到U盘或者移动硬盘再拷到麒麟SP1服务器上。大文件传输过程中可能出现损坏强烈建议做MD5校验。先在联网机器上生成校验值md5sum milvus-all-images.tar docker-ce-*.rpm checksums.txt到目标机器上执行md5sum -c checksums.txt只要输出全部是OK再继续下一步。这一步看起来多花几分钟但能避免装到一半发现镜像加载失败找回U盘重新拷贝的尴尬。我自己是吃过亏的所以现在无论多急都会先校验。3. 银河麒麟V10-SP1上离线安装Docker3.1 系统检查内核、磁盘、防火墙一个都不能少登录目标服务器第一件事是确认系统版本和内核cat /etc/os-release uname -r正常会看到银河麒麟V10-SP1的标识内核一般4.19。接着看磁盘规划和内存df -h free -hMilvus跑起来以后etcd、MinIO、Milvus三块数据都在增长尤其MinIO里存的是向量索引文件数据量大了很占空间。如果系统盘空间紧建议单独挂载一块数据盘后面Docker的data-root就指到数据盘去。再查防火墙和SELinux状态systemctl status firewalld getenforce我的建议是测试环境直接关掉firewalld省得端口放行的问题反复折腾生产环境如果必须开防火墙就把Milvus用到的端口放行。常用端口有19530Milvus客户端、9091Prometheus/健康检查、9000与9001MinIO API与控制台、2379etcd。SELinux如果处于enforcing先临时setenforce 0验证一下业务是否正常确认是SELinux拦截后再决定调整文件上下文还是保持关闭。不要一上来就永久关闭有些信创环境验收会检查SELinux状态。3.2 Docker离线rpm安装与daemon.json配置把rpm包放到目标机器目录比如/opt/docker-rpm然后执行cd /opt/docker-rpm yum install -y ./docker-ce-*.rpm这里建议用yum install而不是rpm -ivh因为yum会自动识别当前目录下所有的rpm包并处理依赖关系。如果提示缺依赖就把缺的rpm也放到同目录继续执行yum install即可。安装完成后先不急着启动配置daemon.json。我一般这样写mkdir -p /etc/docker cat /etc/docker/daemon.json EOF { data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 50m, max-file: 5 }, storage-driver: overlay2 } EOF解释一下这几个配置>systemctl enable --now docker systemctl status docker docker info docker version重点关注docker info里的几个信息Storage Driver是否为overlay2Cgroup版本以及是否报WARNING。如果看到overlay2说明存储驱动正常。再检查docker composedocker compose version如果命令不存在有可能是rpm包不完整或者plugin没生效。这时候可以用独立二进制兜底在联网机器上下载docker-compose-linux-x86_64拷到目标机器后放到/usr/local/bin/docker-compose加执行权限chmod x /usr/local/bin/docker-compose docker-compose versionDocker环境稳定以后再继续导入Milvus镜像。4. Milvus镜像导入与单机版编排4.1 镜像导入、打标签与一致性确认导入镜像docker load -i /data/offline/milvus-all-images.tar导入完成后立即确认docker images如果save时候是完整名称load后也会保留完整名称。看到三个镜像都在列表里标签和拉取时一致就不用额外docker tag了。有一个小坑如果你save的时候只写了短名称load出来的镜像repository和tag可能不完整这时候compose文件里引用的image名字就要跟着调整否则docker compose拉镜像会去远程仓库然后因为没网直接失败。我的建议是compose文件写好之后一定要检查每个image:字段都对应docker images里的实际名称。4.2 手写docker-compose.yml并逐项解读创建部署目录mkdir -p /opt/milvus cd /opt/milvus然后创建docker-compose.yml。我这次用的2.6.8单机版完整配置如下version: 3.5 services: etcd: image: quay.io/coreos/etcd:v3.5.5 environment: - ETCD_AUTO_COMPACTION_MODErevision - ETCD_AUTO_COMPACTION_RETENTION1000 - ETCD_QUOTA_BACKEND_BYTES4294967296 - ETCD_SNAPSHOT_COUNT50000 volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd command: etcd -advertise-client-urlshttp://etcd:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd healthcheck: test: [CMD, etcdctl, endpoint, health] interval: 30s timeout: 20s retries: 3 restart: always minio: image: minio/minio:RELEASE.2023-03-20T20-16-18Z environment: MINIO_ACCESS_KEY: minioadmin MINIO_SECRET_KEY: minioadmin volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data command: minio server /minio_data --console-address :9001 healthcheck: test: [CMD, curl, -f, http://localhost:9000/minio/health/live] interval: 30s timeout: 20s retries: 3 restart: always standalone: image: milvusdb/milvus:v2.6.8 command: [milvus, run, standalone] security_opt: - seccomp:unconfined environment: ETCD_ENDPOINTS: etcd:2379 MINIO_ADDRESS: minio:9000 volumes: - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus healthcheck: test: [CMD, curl, -f, http://localhost:9091/healthz] interval: 30s start_period: 90s timeout: 20s retries: 3 ports: - 19530:19530 - 9091:9091 depends_on: - etcd - minio restart: always简单解读一下三个服务的职责。etcd是Milvus的元数据存储collection、partition、segment等元信息都放这里。环境变量里的ETCD_AUTO_COMPACTION_MODErevision和ETCD_AUTO_COMPACTION_RETENTION1000用来定期压缩历史版本避免etcd空间被无限增长的事务记录撑爆。ETCD_QUOTA_BACKEND_BYTES设置了后端存储告警阈值默认4GB单机场景够用。MinIO是外部对象存储这是Milvus 2.x的常见部署模式Milvus不再使用内置对象存储而是把向量数据文件和索引文件写到MinIO。这样数据与计算分离后面如果要扩节点或者迁移数据对象存储是可以独立管理的。MINIO_ACCESS_KEY和MINIO_SECRET_KEY我暂时用默认值生产环境一定要改而且建议通过环境变量文件传入别直接硬编码在compose里。standalone服务是Milvus的单机模式内部自带proxy、datanode、indexnode、querynode等组件。ETCD_ENDPOINTS指向compose网络内的etcd服务名MINIO_ADDRESS指向minio:9000。容器内部通过服务名互相访问走的都是compose默认的bridge网络。depends_on只保证启动顺序不保证服务健康所以etcd和minio的健康检查配置很有必要。4.3 一次性启动三件套并验证服务启动服务cd /opt/milvus docker compose up -d然后观察状态docker compose ps一开始容器可能处于health: starting状态属正常。等待一两分钟后再看三个服务应该都能变成healthy或者running。如果standalone一直重启先看日志docker compose logs -f standalone docker compose logs etcd docker compose logs minio看到Milvus日志出现类似proxy started、query node started等关键字就说明核心组件都起来了。更严谨的验证是用pymilvus连一下pip install pymilvus2.6.8 python3进入Python交互环境from pymilvus import connections connections.connect(host127.0.0.1, port19530) print(connected)能打印connected说明客户端和服务端链路正常。如果你还想进一步验证插入和检索可以创建一个简单collection插入几条随机向量再执行search。这一步能确认存储链路是否完整因为有些环境端口通了但写入MinIO或etcd时会有权限问题只有真实写入才能发现。5. SP1专属避坑指南与实操心得5.1 SP1高频报错速查表我把这次部署中遇到的和身边同事常踩的问题整理成了一张表遇到问题可以先对照查找报错或异常常见原因处理方式overlay/overlay: unsupported内核未加载overlay模块执行modprobe overlay并写入/etc/modules-load.d/error creating overlay mount数据分区不支持d_type使用ext4格式化数据盘或将Docker数据目录改到ext4分区iptables failed: iptables --wait -t natDocker与nftables/iptables不兼容安装iptables-nft停止firewalld必要时重启dockerd容器内时间差8小时容器默认UTC时区compose中增加TZ: Asia/Shanghai环境变量Permission denied等挂载报错SELinux拦截或目录权限不对临时setenforce 0定位调整目录context或授予权限Milvus容器不断重启etcd或MinIO服务未就绪查看etcd/minio日志确认容器间DNS解析是否正常disk space exhausted日志或数据占满磁盘检查daemon.json日志限制确认数据盘大小docker-compose: command not foundcompose plugin未安装或不生效确认docker-compose-plugin rpm或使用独立二进制5.2 内核模块、存储驱动与iptables处理SP1和CentOS/RHEL系类似但有个很典型的问题部分内核模块默认没有加载特别是br_netfilter。没有它容器跨主机通信、端口映射都容易出问题。安装Docker后先执行modprobe br_netfilter modprobe overlay echo br_netfilter /etc/modules-load.d/docker.conf同时调整内核参数让IPv4转发和iptables桥接生效cat /etc/sysctl.d/docker.conf EOF net.ipv4.ip_forward 1 net.bridge.bridge-nf-call-iptables 1 EOF sysctl --system另一个高频问题是存储驱动overlay2。SP1上如果Docker数据目录所在分区是xfs且没有开启ftype1创建overlay2挂载点时会报错。docker info能看到存储驱动但真正报错时在容器启动阶段。处理办法是数据盘格式化时用mkfs.ext4或者确保xfs格式化带有-n ftype1参数。如果现有分区不愿意重格可以临时把storage-driver改成vfs但vfs性能很差只适合应急验证不建议长期跑。iptables问题也很折磨人。麒麟SP1在部分版本里默认用的是nftables而Docker希望操作iptables转发链。如果启动容器时看到Failed to program NAT chain之类的错误先停止firewalldsystemctl disable --now firewalld如果还不行安装iptables-nft或iptables-services套件再重启dockerd。这个问题的根源是iptables与nftables语法不兼容Docker写入NAT链失败容器端口映射就会异常。5.3 时间、数据目录与安全策略调整容器和宿主机时间差8小时几乎每次部署都会遇到。compose里对每个服务增加TZ: Asia/Shanghai环境变量比如etcd的environment列表里加上一行minio和standalone同理。也可以统一挂载宿主机时间配置volumes: - /etc/localtime:/etc/localtime:ro两种方式我都在生产用过效果相同。时间不一致会导致日志时间错乱虽然不影响Milvus主流程但排查问题的时候非常误导人。数据持久化目录方面我用的${DOCKER_VOLUME_DIRECTORY:-.}/volumes这种写法意思是默认在compose文件同级目录生成volumes文件夹也可以通过环境变量DOCKER_VOLUME_DIRECTORY整体改到其他位置。比如想放到数据盘export DOCKER_VOLUME_DIRECTORY/data/milvus docker compose up -d这样所有中间数据都落在/data/milvus/volumes下。后面要备份直接打包这个目录即可。注意改目录后要确保目录属主和权限正确否则容器以内部用户写文件时可能报Permission denied。SELinux在SP1上默认可能是enforcing容器挂载宿主目录时经常被拦截。先用setenforce 0验证一下如果确实是SELinux导致的问题可以在不关闭SELinux的前提下调整挂载目录的上下文chcon -Rt svirt_sandbox_file_t /data/milvus/volumes /data/docker如果项目验收没有强制要求长期跑测试环境也可以直接关闭SELinux修改/etc/selinux/config后重启生效。我个人的倾向是生产环境尽量保留SELinux并正确设置上下文测试环境关闭来省时间。5.4 我的SP1实操心得这次做完以后有几个比较深的体会。第一个物料准备阶段无论多着急都一定要在联网机器上把rpm依赖和镜像全部核对一遍。离线环境最大的成本就是“返工”漏一个依赖就可能要用U盘再跑一趟机房。rpm依赖问题可以通过yumdownloader --resolve解决镜像可以通过docker images核对tar包用md5校验这些步骤看起来琐碎但每一道都是在给后面省时间。第二个Milvus单机版的资源占用比想象中要高。etcd、MinIO、Milvus三个容器同时跑内存最少给到8GB磁盘上MinIO的索引文件增长非常快。我在测试机上一开始只分了4GB内存结果Milvus起来后频繁因为内存不足触发OOM容器一直重启。后来加内存加swap才稳定下来。建议正式使用前用真实数据量压测一轮确认资源水位。第三个验证不能只看docker compose ps。容器是running状态不代表Milvus的链路是通的etcd可能连不上MinIO的写入可能失败这些在业务查询时才会暴露。所以我在部署完成后一定会用pymilvus创建一个临时collection插入几条向量再search一次把写入、索引、查询全链路跑通才算结束。第四个后续如果要在SP1上继续扩展其他组件这套离线Docker环境可以直接复用。比如离线部署redis、mysql、superset或者跑一个本地大模型推理服务都可以用同样的方式提前制备rpm和镜像。事实上我下一阶段计划把内网镜像仓库和监控组件也纳入这套信创离线体系里让新机器上线时不再依赖U盘逐个拷包。信创迁移这件事看起来是操作系统切换真正花时间的其实还是应用中间层的适配和交付。Docker这套离线部署思路在很多SP1项目里都能复用先把底座搭稳后面再迁什么都顺。希望这篇笔记能让你少走几步弯路。
返回列表