在专有网络 VPC 内创建接口终端节点后,客户端可通过私网地址调用沙箱 API、连接沙箱并访问沙箱内服务,请求全程不经公网。
工作原理
本方案在客户端所在的 VPC 内创建接口终端节点,连接沙箱服务提供的终端节点服务 com.aliyuncs.privatelink.<REGION>.sandbox。接口终端节点是 VPC 内调用沙箱 API 的私网入口,终端节点服务负责转发 API 请求。SDK 连接沙箱及访问沙箱内运行的服务时,使用沙箱服务的私网访问域名。
私网访问过程如下:
-
解析沙箱 API 域名:私网连接(PrivateLink)在接口终端节点所在的 VPC 内提供沙箱 API 域名的私网解析,将 API 域名解析为终端节点的私网 IP。
-
通过终端节点调用 API:客户端发起 HTTPS API 请求,通过终端节点关联安全组的访问检查后,经 PrivateLink 终端节点连接到达沙箱 API 入口。
创建、管理沙箱的请求使用
E2B_API_URL,SDK 连接沙箱及生成沙箱内服务访问域名时使用E2B_DOMAIN,两项均需配置为下表中的私网地址。
|
参数 |
私网配置 |
用途 |
|
|
|
调用沙箱 API,例如创建沙箱。 |
|
|
|
SDK 连接沙箱,并通过 |
表中 <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。
创建接口终端节点
-
登录私网连接控制台,选择接口终端节点,进入创建页面。
-
在基础配置中将所属地域设置为目标地域并填写节点名称;将类型设置为
阿里云服务,并在可用的服务中选择com.aliyuncs.privatelink.<REGION>.sandbox。 -
配置专有网络、可用区与交换机和安全组。终端节点关联安全组的入方向需允许客户端的私网 IP 或网段访问 TCP 443,客户端出方向也需允许该访问。
-
单击确认创建,等待接口终端节点状态变为“可用”、终端节点连接状态变为“已连接”。
创建完成后,该 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;终端节点服务名称为 |
|
终端节点及连接状态 |
在私网连接控制台确认接口终端节点状态为“可用”,终端节点连接状态为“已连接”。尚未完成连接时,先检查连接状态及控制台提示。 |
|
私网域名解析与 DNS |
在运行代码的客户端上,用 |
|
安全组与访问端口 |
确认终端节点关联安全组允许客户端来源网段访问 TCP 443,客户端侧出方向规则也允许该访问。示例中的 8000 是沙箱内 HTTP 服务的监听端口,客户端通过 HTTPS 443 访问 SDK 生成的域名。 |
|
API Key 与访问权限 |
如返回 HTTP 401 或 403,请结合错误信息检查 API Key 和访问权限,不要仅凭状态码判断为 PrivateLink 连接失败。 |
|
沙箱内服务是否就绪 |
确认 HTTP 进程正常运行、监听 8000 端口,且验证文件存在。若创建沙箱成功但访问服务失败,检查进程日志与响应内容;示例结束后沙箱会被销毁,此时验证地址失效属于预期行为。 |
后续步骤
验证完成后,示例创建的沙箱已自动销毁,接口终端节点继续作为该 VPC 内客户端访问沙箱的私网入口。接口终端节点的管理操作与相关机制,参见以下文档:
-
PrivateLink 工作原理:接口终端节点、终端节点连接与私网域名解析的机制说明。
-
访问阿里云服务:接口终端节点的创建与管理操作。