🚀 Milvus 实战部署全记录

🚀 Milvus 实战部署全记录

Milvus 2.5.23 + Attu + 鉴权 + 幂等初始化(Docker Compose)


一、背景说明

在实际工程中部署 Milvus,并不是简单 docker run 就能解决的问题。

本文完整记录了一次 从踩坑到稳定上线 的 Milvus 私有化部署过程。

最终方案选择:

  • Milvus v2.5.23(Standalone)
  • 开启官方鉴权(RBAC)
  • Attu 管理界面
  • 幂等的初始化用户方案
  • Docker Compose 一键部署

二、为什么选择 Milvus 2.5.23?

放弃 2.6.7 的原因

  1. 内存要求更高

    • 2.6.x 引入 StreamingNode
    • 启动时内存占用明显增加
    • 8G 内存机器非常吃力
  2. MinIO 依赖更激进

    • 常搭配 minio/minio:RELEASE.2024-05-28T17-19-04Z
    • 部分环境下存在 GPU / 指令集兼容问题
    • MinIO 起不来 → Milvus 直接失败

选择 2.5.23 的理由

  • 架构成熟
  • 资源占用低
  • MinIO 兼容性好
  • Attu / SDK 稳定

结论:2.5.23 是当前工程部署的"甜点版本"


三、项目目录结构

text 复制代码
milvus/
├── docker-compose.yml
├── config/
│   └── milvus.yaml
├── init/
│   ├── Dockerfile
│   └── init_user.py
└── volumes/

四、docker-compose.yml

yaml 复制代码
version: '3.5'

services:
  etcd:
    container_name: milvus-etcd
    image: quay.io/coreos/etcd:v3.5.18
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
      - ETCD_SNAPSHOT_COUNT=50000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
    command: etcd -advertise-client-urls=http://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
    networks:
      - milvus
  minio:
    container_name: milvus-minio
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    ports:
      - "9001:9001"
      - "9000:9000"
    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
    networks:
      - milvus
  milvus:
    container_name: milvus-standalone
    image: milvusdb/milvus:v2.5.23
    command: ["milvus", "run", "standalone"]
    security_opt:
      - seccomp:unconfined
    environment:
      MINIO_REGION: us-east-1
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
      - ${DOCKER_VOLUME_DIRECTORY:-.}/config/milvus.yaml:/milvus/configs/milvus.yaml
    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"
    networks:
      - milvus
  attu:
    container_name: milvus-attu
    image: zilliz/attu:v2.4
    environment:
      MILVUS_URL: milvus:19530
      MILVUS_USERNAME: root
      MILVUS_PASSWORD: Milvus@123
    ports:
      - "17000:3000"
    depends_on:
      - "milvus"
    networks:
      - milvus
  init:
    build: ./init
    container_name: milvus-init
    environment:
      MILVUS_HOST: milvus
      NEW_ROOT_PASSWORD: ********  #设置自己新的密码
      APP_USER: ********			#应用账号
      APP_PASSWORD: ********		#应用密码
      APP_ROLE: admin
    networks:
      - milvus
    depends_on:
      - milvus
    restart: "no"
networks:
  milvus:

五、开启 Milvus 官方鉴权

config/milvus.yaml

yaml 复制代码
common:
  security:
    authorizationEnabled: true

开启后:

  • 所有客户端必须登录
  • Attu 也必须使用账号密码

六、幂等的 Milvus 初始化用户方案

init/Dockerfile

dockerfile 复制代码
FROM python:3.10-slim-bullseye
RUN pip install --no-cache-dir pymilvus==2.5.16
WORKDIR /app
COPY init-user.py /app/init-user.py
CMD ["python", "/app/init-user.py"]

init/init_user.py

python 复制代码
import os
import time
from pymilvus import connections, utility, Role
from pymilvus.exceptions import MilvusException

# ---------- 基础配置 ----------
MILVUS_HOST = os.getenv("MILVUS_HOST", "milvus")
MILVUS_PORT = os.getenv("MILVUS_PORT", "19530")

ROOT_USER = "root"
DEFAULT_ROOT_PASSWORD = os.getenv("ROOT_PASSWORD", "Milvus")
NEW_ROOT_PASSWORD = os.getenv("NEW_ROOT_PASSWORD")  # 可选

APP_USER = os.getenv("APP_USER", "app_user")
APP_PASSWORD = os.getenv("APP_PASSWORD", "App@123456")
APP_ROLE = os.getenv("APP_ROLE", "admin")

# ---------- 等待 Milvus ----------
print("⏳ Waiting for Milvus to be ready...")
time.sleep(12)

# ---------- 使用默认 root 密码连接 ----------
connections.connect(
    alias="default",
    host=MILVUS_HOST,
    port=MILVUS_PORT,
    user=ROOT_USER,
    password=DEFAULT_ROOT_PASSWORD
)

# ---------- 修改 root 密码(幂等) ----------
if NEW_ROOT_PASSWORD and NEW_ROOT_PASSWORD != DEFAULT_ROOT_PASSWORD:
    try:
        utility.update_password(
            ROOT_USER,
            DEFAULT_ROOT_PASSWORD,
            NEW_ROOT_PASSWORD
        )
        print("✅ Root password updated")

        # 重新连接(非常重要)
        connections.disconnect("default")
        connections.connect(
            alias="default",
            host=MILVUS_HOST,
            port=MILVUS_PORT,
            user=ROOT_USER,
            password=NEW_ROOT_PASSWORD
        )
    except MilvusException as e:
        if "password is incorrect" in str(e) or "authentication failed" in str(e):
            print("ℹ️ Root password already changed, continue")
            connections.disconnect("default")
            connections.connect(
                alias="default",
                host=MILVUS_HOST,
                port=MILVUS_PORT,
                user=ROOT_USER,
                password=NEW_ROOT_PASSWORD
            )
        else:
            raise

# ---------- 创建用户 ----------
try:
    utility.create_user(APP_USER, APP_PASSWORD)
    print(f"✅ User created: {APP_USER}")
except MilvusException as e:
    if "already exists" in str(e):
        print(f"ℹ️ User already exists: {APP_USER}")
    else:
        raise

# ---------- 创建角色 ----------
role = Role(APP_ROLE)
try:
    role.create()
    print(f"✅ Role created: {APP_ROLE}")
except MilvusException as e:
    if "already exists" in str(e):
        print(f"ℹ️ Role already exists: {APP_ROLE}")
    else:
        raise

# ---------- 绑定角色 ----------
try:
    role.add_user(APP_USER)
    print(f"✅ Granted role [{APP_ROLE}] to user [{APP_USER}]")
except MilvusException as e:
    if "already" in str(e):
        print("ℹ️ Role already granted")
    else:
        raise

print("🎉 Milvus RBAC initialization finished")

幂等性说明

  • 重复执行不会报错
  • 适合 CI/CD
  • 容器只执行一次即可退出

七、运行与验证

bash 复制代码
docker compose up -d

成功标志:

  • milvus-init 容器执行后退出,具体的执行日志如下:

    csharp 复制代码
    #执行脚本
    docker logs -f milvus-init
  • Milvus 日志无 ERROR

  • Milvus 的webui管理端,注意这个管理端没有账号与密码,能直接访问

  • Attu需要账号密码才能登录,需要自己测试下新的root密码、应用账号与密码

八、踩坑记录

9091 访问不了?

原因:

  • Milvus 未完全就绪
  • MixCoord 尚未启动完成

解决:

  • 耐心等待
  • 通过 docker logs -f milvus-standalone 查看状态

docker start 看不到日志?

bash 复制代码
docker logs -f milvus-standalone

没有 /var/lib/milvus/logs 目录?

  • 2.5.x 默认日志输出 stdout
  • 属于正常现象

有异常需要重新操作

  • 看情况,可以选择从新编译init的镜像

    csharp 复制代码
     docker-compose build init
  • 账号信息放在ect里面,根据情况可以删除

    bash 复制代码
    rm -rf ./volumes/*

九、总结

  • Milvus 是工程系统,不是 Demo
  • 2.5.23 是当前最稳妥的生产选择
  • 初始化用户一定要做成幂等
  • 鉴权 + Attu 才是完整方案

一次搭好,后面都省心


完 🎉

相关推荐
l1t2 小时前
PostgreSQL pg_clickhouse插件的安装和使用
数据库·clickhouse·postgresql·插件
令狐囱2 小时前
宝塔docker 运行 go-zero-looklook项目
docker·容器·golang
yBmZlQzJ2 小时前
内网穿透 + 域名解析:到底解决了什么核心问题?
运维·经验分享·网络协议·docker·容器
小挪号底迪滴2 小时前
Docker容器化实践:从开发到生产的完整流程
运维·docker·容器
古德new2 小时前
openFuyao多样化算力使能:技术实现原理与开发者集成指南
服务器·数据库·安全
惊鸿.Jh3 小时前
高频SQL50题(基础版)解析(I)
数据库
gordon~93 小时前
Docker常用命令
运维·docker·容器
sone121383 小时前
Oracle 12c实验3:实验步骤的SQL语句
数据库·sql·oracle