Skip to main content

UV-based virtual environment manager for LangGraph node isolation

Project description

Environment Fabric

Ray 的环境供应插件 — 基于 UV + NAS + Hardlink 的 AOT 预构建虚拟环境管理服务


🎯 项目定位

Environment Fabric 不是 Ray 的替代品,而是 Ray 的「环境供应插件」。

┌─────────────────────────────────────────────────────────────────────────────────┐
│                           系统架构定位                                           │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│  ┌──────────────────────────────┐         ┌───────────────────────────────────┐ │
│  │     Environment Fabric       │   API   │      Execution Engine             │ │
│  │     ────────────────────     │ ──────► │      ───────────────────          │ │
│  │     • AOT 预构建环境          │         │      • Ray                        │ │
│  │     • NAS 共享存储 + Hardlink │   输出   │      • Celery                     │ │
│  │     • pyproject.toml + uv.lock│  路径   │      • Kubernetes Job             │ │
│  │     • 环境生命周期管理         │         │      • Docker / subprocess        │ │
│  └──────────────────────────────┘         └───────────────────────────────────┘ │
│                                                                                 │
│  产出:标准的 .venv 路径(如 /mnt/nas/envs/wf-001/node-A/.venv/bin/python)      │
│  消费者:任何能使用 Python 解释器路径的执行引擎                                    │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

🔌 与 Ray 的融合方案:py_executable

利用 Ray 的 py_executable 参数(实验性功能),可以让 Ray Worker 直接使用 Environment Fabric 预构建的 Python 环境:

import ray

# 1. Environment Fabric 预先构建的环境路径(位于 NAS 共享存储)
#    所有 Ray Worker 节点通过 NFS 挂载同一路径
PREBUILT_PYTHON = "/mnt/nas/envs/workflow-001/node-A/.venv/bin/python"

# 2. 定义 runtime_env,告诉 Ray:"别自己装包了,直接用我给你的这个 Python"
runtime_env = {
    "py_executable": PREBUILT_PYTHON,  # 关键:指定 Worker 启动时使用的解释器
    "working_dir": "./my_project_code"  # 仍可挂载代码目录
}

@ray.remote(runtime_env=runtime_env)
def heavy_computing_task():
    import sys
    import torch
    # 这里使用的是 Environment Fabric 预构建的环境
    return f"Running on {sys.executable} with torch {torch.__version__}"

# 3. 执行
ray.init()
print(ray.get(heavy_computing_task.remote()))

[!TIP] 融合架构的核心思想

  • Environment Fabric:负责 AOT 预构建环境,产出 .venv 路径
  • Ray:负责 JIT 任务调度,通过 py_executable 使用预构建环境
  • 结果:环境构建与任务执行解耦,两者各司其职

🚀 为什么需要 Environment Fabric?

Ray 的 runtime_env 虽然强大,但它本质上是 "分布式的、节点本地的、JIT 的"。 而 Environment Fabric 是 "中心化的、全局共享的、AOT 的"

以下 4 个生产级场景,Ray 原生方案解决不了,而 Environment Fabric 是完美解法:

场景一:大规模 SaaS 平台(10000+ 环境)

问题:磁盘成本爆炸

架构 10 台机器 × 安装 torch (2GB) 总磁盘占用
Ray Runtime Env (Node-local) 每台机器独立安装 20 GB
Environment Fabric (NAS + Hardlink) 共享存储 + 硬链接 2 GB

Environment Fabric 方案

  • 所有环境构建在 NAS 共享存储上
  • 利用 uv 的 Hardlink 机制,相同包只占用一份物理空间
  • 节省 90% 以上存储成本
NAS 共享存储架构:
┌─────────────────────────────────────────────────────────────────────┐
│  /mnt/nas/                        <- NFS/EFS 挂载点                 │
│    │                                                                │
│    ├── envs/                      <- 所有环境                       │
│    │   ├── wf-001_node-A/.venv/   <- 环境A (torch)                 │
│    │   ├── wf-001_node-B/.venv/   <- 环境B (torch)  ──┐            │
│    │   └── wf-002_node-C/.venv/   <- 环境C (torch)  ──┼─ Hardlink  │
│    │                                                  │             │
│    └── uv_cache/                  <- 全局缓存 ────────┘             │
│        └── torch-2.0.0.whl        <- 物理文件只存一份               │
└─────────────────────────────────────────────────────────────────────┘

场景二:生产环境零冷启动

问题:Ray JIT 导致任务冷启动不可控

sequenceDiagram
    participant User
    participant Ray as Ray (JIT 模式)
    participant EnvFabric as Environment Fabric (AOT 模式)
    participant Task

    Note over Ray: Ray 原生方案 - 冷启动
    User->>Ray: 提交任务
    Ray->>Ray: 发现没环境
    Ray->>Ray: 开始构建环境(可能耗时数分钟)
    Ray->>Task: 等待... 执行任务

    Note over EnvFabric: Environment Fabric 方案 - 预热
    User->>EnvFabric: 保存工作流配置
    EnvFabric->>EnvFabric: 后台静默构建环境 ✅
    Note over User: 稍后...
    User->>EnvFabric: 点击运行
    EnvFabric->>Task: 环境已就绪 → 毫秒级启动 🚀

Environment Fabric 方案

  • AOT 预构建:用户编辑完工作流 → 保存 → 后台静默构建环境
  • 毫秒级启动:运行时环境已就绪,Ray 直接使用 py_executable
  • 解耦构建与执行:环境构建作为独立环节,不阻塞任务调度

场景三:可调试的白盒环境

问题:Ray 环境是黑盒,故障难排查

维度 Ray Runtime Env Environment Fabric
环境位置 临时目录,被 GC 后消失 持久化物理路径
故障排查 只能看 Ray 日志 可 SSH 进去 source .venv/bin/activate
环境回滚 不支持 可对环境做 Snapshot
确定性 pip list 松散 uv.lock 字节级锁定

Environment Fabric 方案

  • 环境是物理存在的文件夹,可随时进入排查
  • pyproject.toml + uv.lock 保证环境字节级一致
  • 支持环境版本管理和回滚

场景四:Vendor Agnostic(不锁定执行引擎)

问题:Ray runtime_env 与 Ray 强绑定

Environment Fabric 方案

  • 产出标准的 .venv 路径
  • 可被任何执行引擎消费
# 被 Ray 消费
@ray.remote(runtime_env={"py_executable": venv_python_path})
def ray_task(): ...

# 被 Docker 挂载
# docker run -v /mnt/nas/envs:/envs python:3.11 /envs/wf-001/.venv/bin/python script.py

# 被 Kubernetes Job 使用
# command: ["/mnt/nas/envs/wf-001/node-A/.venv/bin/python", "main.py"]

# 被 subprocess 调用
subprocess.run([venv_python_path, "script.py"])

📊 技术对比总结

维度 Environment Fabric Ray Runtime Env
构建时机 ⏱️ AOT (提前构建) ⏳ JIT (运行时构建)
存储模型 💾 NAS 共享 + Hardlink 📦 Node-local 缓存
环境确定性 🔒 uv.lock 字节级锁定 🎲 pip list 松散声明
冷启动时间 🚀 毫秒级 🐢 分钟级(大依赖)
可调试性 ✅ 持久化白盒 ❌ 临时黑盒
耦合度 🔌 Vendor Agnostic 🔗 Ray 强绑定
磁盘效率 💰 节省 90%+ 📈 线性增长

🏗️ NAS 共享存储架构

[!IMPORTANT] 硬性部署条件

UV_CACHE_DIR 必须与 ENVS_BASE_PATH 在同一物理分区(NAS 挂载点),才能使用 Hardlink 机制。

/mnt/nas/                           <- NFS/EFS 挂载点(所有节点共享)
│
├── envs/                           <- ENVS_BASE_PATH
│   ├── workflow123_node123/        <- 独立 UV 项目
│   │   ├── .venv/                  <- 虚拟环境
│   │   │   └── bin/python          <- Ray py_executable 指向这里
│   │   ├── pyproject.toml          <- 依赖声明
│   │   ├── uv.lock                 <- 版本锁定
│   │   └── metadata.json           <- 环境元数据
│   └── ...
│
└── uv_cache/                       <- UV_CACHE_DIR(全局共享缓存)
    ├── wheels/                     <- .whl 包文件
    └── archives/                   <- 源码包
            ↑
            └── Hardlink 指向各环境的 .venv/lib/

📁 详细技术文档

技术细节已拆分到独立文档:

文档 描述
📋 PRD - 产品需求文档 背景、目标、功能范围
🏛️ ARD - 架构需求文档 系统架构、组件设计、存储策略
⚙️ TRD - 技术需求文档 API 规范、项目结构、配置说明

🚀 快速开始

1. 环境要求

  • Python 3.11+
  • uv 包管理器
  • NAS/共享存储(生产环境)
  • PostgreSQL(审计数据库)

2. 安装与运行

# 克隆项目
git clone <repo-url>
cd env_manager

# 安装依赖
uv sync

# 配置环境变量
cp .env.template .env
# 编辑 .env 文件配置 DATA_ROOT、DATABASE_URL 等

# 启动服务
uv run uvicorn src.api:app --host 0.0.0.0 --port 8000

3. 创建环境

# 创建一个新环境
curl -X POST http://localhost:8000/envs \
  -F "workflow_id=wf-001" \
  -F "node_id=node-A" \
  -F "packages=numpy>=1.24.0" \
  -F "packages=pandas>=2.0.0"

4. 与 Ray 集成

import ray
import httpx

# 1. 从 Environment Fabric 获取预构建环境路径
resp = httpx.get("http://localhost:8000/envs/wf-001/node-A")
env_path = resp.json()["env_path"]
python_path = f"{env_path}/.venv/bin/python"

# 2. 配置 Ray 使用该环境
runtime_env = {"py_executable": python_path}

@ray.remote(runtime_env=runtime_env)
def my_task():
    import numpy as np
    return np.__version__

ray.init()
print(ray.get(my_task.remote()))

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uv_venv_manager-0.1.0.tar.gz (50.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uv_venv_manager-0.1.0-py3-none-any.whl (56.5 kB view details)

Uploaded Python 3

File details

Details for the file uv_venv_manager-0.1.0.tar.gz.

File metadata

  • Download URL: uv_venv_manager-0.1.0.tar.gz
  • Upload date:
  • Size: 50.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for uv_venv_manager-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d4294a937eeab54d6e757afa312009c1a641f69718d68760cae001eee84964aa
MD5 b5a981a5a14a68e15a35eb6fb4bca920
BLAKE2b-256 7633dedd3235a654bc5dbca6d5fc861b0434aa2138ada8d3fae4fa3750785077

See more details on using hashes here.

File details

Details for the file uv_venv_manager-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for uv_venv_manager-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b18830f623ad84caa3e51423204e4e259b0c6e4b28336031fe9c8872ac38be41
MD5 03ce30b5354b53b352b16c529f5283f1
BLAKE2b-256 18c08ec1e1bcf859c73363d20467d39ad6e0c6045e3187feb05f05115a02b887

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page