通过私网访问沙箱实例

更新时间:
复制 MD 格式

在专有网络 VPC 内创建接口终端节点后,客户端可通过私网地址调用沙箱 API、连接沙箱并访问沙箱内服务,请求全程不经公网。

工作原理

本方案在客户端所在的 VPC 内创建接口终端节点,连接沙箱服务提供的终端节点服务 com.aliyuncs.privatelink.<REGION>.sandbox。接口终端节点是 VPC 内调用沙箱 API 的私网入口,终端节点服务负责转发 API 请求。SDK 连接沙箱及访问沙箱内运行的服务时,使用沙箱服务的私网访问域名。

私网访问过程如下:

  1. 解析沙箱 API 域名:私网连接(PrivateLink)在接口终端节点所在的 VPC 内提供沙箱 API 域名的私网解析,将 API 域名解析为终端节点的私网 IP。

  2. 通过终端节点调用 API:客户端发起 HTTPS API 请求,通过终端节点关联安全组的访问检查后,经 PrivateLink 终端节点连接到达沙箱 API 入口。

    创建、管理沙箱的请求使用 E2B_API_URL,SDK 连接沙箱及生成沙箱内服务访问域名时使用 E2B_DOMAIN,两项均需配置为下表中的私网地址。

参数

私网配置

用途

E2B_API_URL

https://api.<REGION>-vpc.sandbox.aliyuncs.com

调用沙箱 API,例如创建沙箱。

E2B_DOMAIN

<REGION>-vpc.sandbox.aliyuncs.com

SDK 连接沙箱,并通过 getHost(port) / get_host(port) 生成沙箱内服务的访问域名;该参数不包含 https://。

表中 <REGION> 为目标地域 ID,例如 cn-shanghai,应与所选终端节点服务的地域保持一致。SDK 生成的连接域名和服务访问域名解析到沙箱服务的私网地址,不要求与接口终端节点的私网 IP 相同;本文后续章节涉及解析结果的判断,均以这一关系为准。

该接口终端节点连接由 VPC 内的客户端主动发起访问,响应通过已有连接返回。创建此连接不会建立沙箱主动访问 VPC 内数据库等资源的通道。终端节点及私网域名解析的更多说明,参见 PrivateLink 工作原理。

私网访问与公网访问并存

开启私网访问不会关闭原有公网入口:创建接口终端节点只是新增一条通过 PrivateLink 访问沙箱的链路,已有客户端仍可继续通过公网地址访问。要让客户端改用私网链路,需在已配置接口终端节点的 VPC 内按本文配置私网地址;开启 PrivateLink 不等同于将沙箱设置为“仅允许私网访问”。

前提条件

本文的操作与验证均以客户端与接口终端节点位于同一 VPC 为前提;客户端位于其他 VPC 或本地环境时,还需额外配置网络连通和 DNS 解析,不在本文范围内。开始操作前,确认以下条件已具备:

  • 首次使用前,已开通私网连接(PrivateLink)服务。

  • 已准备客户端所在的 VPC,以及创建接口终端节点所需的交换机和安全组。客户端侧的出方向规则需允许访问终端节点的 TCP 443 端口,终端节点关联安全组的入方向规则在创建接口终端节点时配置。

  • 已获取沙箱 API Key,用于配置环境变量 E2B_API_KEY。

  • 已在该 VPC 内准备运行示例的 ECS 实例或容器,并按示例语言安装 Python 与 pip,或 Node.js 与 npm。

创建接口终端节点

  1. 登录私网连接控制台,选择接口终端节点,进入创建页面。

  2. 在基础配置中将所属地域设置为目标地域并填写节点名称;将类型设置为 阿里云服务,并在可用的服务中选择 com.aliyuncs.privatelink.<REGION>.sandbox。

  3. 配置专有网络、可用区与交换机和安全组。终端节点关联安全组的入方向需允许客户端的私网 IP 或网段访问 TCP 443,客户端出方向也需允许该访问。

  4. 单击确认创建,等待接口终端节点状态变为“可用”、终端节点连接状态变为“已连接”。

    创建完成后,该 VPC 内即可使用下文的私网地址访问沙箱。

配置私网地址并验证连通性

以下示例使用 E2B SDK 2.50.0。运行 Python 示例前,执行 python3 -m pip install e2b==2.50.0 安装依赖;运行 TypeScript 示例前,执行 npm install e2b@2.50.0 安装依赖。

在接口终端节点所在 VPC 内的 ECS 或容器上配置环境变量,将 E2B_API_URL 和 E2B_DOMAIN 均设置为私网地址:

export E2B_API_KEY="<YOUR-API-KEY>"
export E2B_API_URL="https://api.<REGION>-vpc.sandbox.aliyuncs.com"
export E2B_DOMAIN="<REGION>-vpc.sandbox.aliyuncs.com"

运行以下任一示例,验证从该 VPC 到沙箱服务的私网连通性。示例会创建沙箱、在 8000 端口启动临时 HTTP 服务,并通过私网地址读取验证文件;最多请求 10 次,单次请求超时设为 3 秒,失败后间隔 1 秒重试。只有响应状态为 HTTP 200 且正文与验证文件内容一致,才判定访问成功;超过重试次数会抛出错误。

预期输出如下。示例以 cn-shanghai 地域为例;<SANDBOX-ID> 为本次创建的沙箱 ID,每次运行生成的 ID 不同。其他地域的域名以实际配置和 SDK 生成结果为准。

验证地址:https://8000-<SANDBOX-ID>.cn-shanghai-vpc.sandbox.aliyuncs.com/private-access-check.txt
HTTP 200
sandbox-private-access-ok

响应状态为 HTTP 200 且正文与验证文件内容一致,说明沙箱内服务可访问。要确认访问确实经由私网,还需检查私网地址已按本文配置,且 API 域名与 SDK 生成的服务访问域名的解析结果符合工作原理的说明。

自动清理:本示例仅用于连通性验证,成功或失败后都会自动销毁沙箱,打印出的验证地址随之失效。

若请求超时、响应状态非 HTTP 200 或正文与验证文件不一致,按故障排查逐项检查客户端所在 VPC、私网域名解析与安全组配置。

TypeScript

以下示例使用 ESM import 语法,并在模块顶层直接 await 创建沙箱,运行环境需支持 ES 模块。

import { Sandbox } from "e2b";

const sandbox = await Sandbox.create("code-interpreter-v1", {
  apiKey: process.env.E2B_API_KEY,
  apiUrl: process.env.E2B_API_URL,
  domain: process.env.E2B_DOMAIN,
});

try {
  await sandbox.files.write(
    "/tmp/private-access-check.txt", "sandbox-private-access-ok\n"
  );
  await sandbox.commands.run("python3 -m http.server 8000 --directory /tmp", {
    background: true,
  });

  const url = `https://${sandbox.getHost(8000)}/private-access-check.txt`;
  console.log(`验证地址:${url}`);

  // 等待服务就绪:最多请求 10 次,单次超时 3 秒,失败后间隔 1 秒重试。
  for (let attempt = 1; attempt <= 10; attempt++) {
    try {
      const response = await fetch(url, { signal: AbortSignal.timeout(3000) });
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      const body = await response.text();
      if (response.status !== 200 || body.trim() !== "sandbox-private-access-ok") {
        throw new Error(`响应不符合预期:HTTP ${response.status}`);
      }
      console.log(`HTTP ${response.status}`);
      console.log(body.trim());
      break;
    } catch (error) {
      if (attempt === 10) throw error;
      await new Promise((resolve) => setTimeout(resolve, 1000));
    }
  }
} finally {
  // 本示例结束后自动销毁沙箱,以上验证地址随之失效。
  await sandbox.kill();
}

Python

以下示例在脚本顶层直接调用 SDK 的同步接口,无需额外配置模块系统。

import os
import time
import urllib.error
import urllib.request

from e2b import Sandbox

sandbox = Sandbox.create(
    template="code-interpreter-v1",
    api_key=os.environ["E2B_API_KEY"],
    api_url=os.environ["E2B_API_URL"],
    domain=os.environ["E2B_DOMAIN"],
)

try:
    sandbox.files.write(
        "/tmp/private-access-check.txt", "sandbox-private-access-ok\n"
    )
    sandbox.commands.run(
        "python3 -m http.server 8000 --directory /tmp", background=True
    )

    url = f"https://{sandbox.get_host(8000)}/private-access-check.txt"
    print(f"验证地址:{url}")

    # 等待服务就绪:最多请求 10 次,单次超时 3 秒,失败后间隔 1 秒重试。
    for attempt in range(1, 11):
        try:
            with urllib.request.urlopen(url, timeout=3) as response:
                body = response.read().decode().strip()
                if response.status != 200 or body != "sandbox-private-access-ok":
                    raise ValueError(f"响应不符合预期:HTTP {response.status}")
                print(f"HTTP {response.status}")
                print(body)
            break
        except (urllib.error.URLError, OSError, ValueError):
            if attempt == 10:
                raise
            time.sleep(1)
finally:
    # 本示例结束后自动销毁沙箱,以上验证地址随之失效。
    sandbox.kill()

故障排查

私网访问失败时,先确认失败发生在创建沙箱、连接沙箱还是访问沙箱内服务,再按下表排查:

检查项

排查方法

客户端所在 VPC 与目标地域

确认代码运行于接口终端节点所在的 VPC;终端节点服务名称为 com.aliyuncs.privatelink.<REGION>.sandbox,私网地址的地域与所选服务一致。其他 VPC 或本地环境需要额外配置网络连通和 DNS 解析。

终端节点及连接状态

在私网连接控制台确认接口终端节点状态为“可用”,终端节点连接状态为“已连接”。尚未完成连接时,先检查连接状态及控制台提示。

私网域名解析与 DNS

在运行代码的客户端上,用 nslookup 分别检查 API 域名和 SDK 生成的服务访问域名。API 域名应解析到对应终端节点网卡的私网 IP,SDK 生成的服务访问域名应解析到沙箱服务的私网地址,两者的预期解析关系见工作原理。若无法解析或结果不符,检查客户端使用的 DNS。若 API 域名解析异常,还需登录私网连接控制台,检查该接口终端节点的自定义服务域名开关是否被手动关闭;若已关闭,请恢复开启。

安全组与访问端口

确认终端节点关联安全组允许客户端来源网段访问 TCP 443,客户端侧出方向规则也允许该访问。示例中的 8000 是沙箱内 HTTP 服务的监听端口,客户端通过 HTTPS 443 访问 SDK 生成的域名。

API Key 与访问权限

如返回 HTTP 401 或 403,请结合错误信息检查 API Key 和访问权限,不要仅凭状态码判断为 PrivateLink 连接失败。

沙箱内服务是否就绪

确认 HTTP 进程正常运行、监听 8000 端口,且验证文件存在。若创建沙箱成功但访问服务失败,检查进程日志与响应内容;示例结束后沙箱会被销毁,此时验证地址失效属于预期行为。

后续步骤

验证完成后,示例创建的沙箱已自动销毁,接口终端节点继续作为该 VPC 内客户端访问沙箱的私网入口。接口终端节点的管理操作与相关机制,参见以下文档: