关于 lightning-deployments
lightning-deployments 是用于在 Lightning AI 上创建和运维部署的技能,面向需要发布容器服务或 HuggingFace 模型的开发者。它涵盖 CLI 与 Python SDK 操作,并说明扩缩容、发布和认证注意事项。
主要功能
- 01部署 Docker 镜像、Studio 环境或 HuggingFace 模型
- 02管理部署与版本发布
- 03调整副本数量并缩容至零
- 04查看日志、配置环境变量和密钥
- 05通过 CLI 或 Python SDK 操作
适用场景
- 01将容器镜像发布为 HTTPS 服务
- 02使用 vLLM 提供 HuggingFace 模型 API
- 03按负载调整部署副本数量
- 04滚动更新服务镜像版本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lightning-ai/ skills --skill lightning-deployments安装后在 Claude Code 中输入/lightning-deployments确认已加载。
详细介绍
Lightning AI 部署
部署会在带有自动伸缩的 HTTPS 端点后运行一个容器(或为 HuggingFace 模型自动构建的 vLLM 服务)。来源互斥:--image(Docker)、--model(HuggingFace id,需要 GPU)或 --studio(部署某个 Studio 的环境)。
设置与身份验证
export DEBUG=0 LIGHTNING_DEBUG=0 # an inherited DEBUG=1 logs the Authorization header; set this in every new shell
# Use the Lightning AI CLI from the current env; install or upgrade it there if it's missing or older than 2026.9.18
v=$(lightning --version 2>/dev/null | sed -n 's/^Lightning CLI version //p')
[ -n "$v" ] && [ "$(printf '%s\n' 2026.9.18 "$v" | sort -V | head -1)" = 2026.9.18 ] \
|| uv pip install -U lightning-sdk || python3 -m pip install -U lightning-sdk
lightning --version # must print "Lightning CLI version …"; if not, see the table below
lightning login # browser flow; or headless:
export LIGHTNING_API_KEY=... LIGHTNING_USER_ID=... # USER_ID optional: with it Basic auth, without it the key is a Bearer token
这会使用 Agent 当前的环境(项目 venv、conda 环境等),并在需要时将其安装到该环境中;之后在所有地方都调用普通的 lightning …。如果设置不顺利:
| 症状 | 解决方法 |
|---|---|
没有激活的环境、出现 externally-managed-environment,或与项目自身的固定版本冲突 | 单独安装:uv tool install lightning-sdk(或 pipx install lightning-sdk),如果它不在 PATH 中,则调用 "$(uv tool dir --bin)/lightning" |
安装后仍没有 Lightning CLI version 行 | 另一个 lightning(PyTorch Lightning 的)或未激活的环境排在前面:检查 command -v lightning,然后激活环境或调用其 bin/lightning |
No such command、No such option 或 unexpected extra argument | CLI 版本太旧:在 command -v lightning 指向的位置升级(uv pip install -U lightning-sdk,或 uv tool upgrade lightning-sdk) |
| 安装受阻(环境或主目录只读、Agent 沙盒) | 将每条命令作为 UV_CACHE_DIR="${TMPDIR:-/tmp}/uv" UV_TOOL_DIR="${TMPDIR:-/tmp}/uv-tools" uvx lightning-sdk … 运行 |
每次调用都出现 SSL/CA 错误,甚至 lightning --version 也如此,且仅在 Agent 沙盒中出现 | **/*.pem 读取拒绝规则隐藏了 certifi 的 cacert.pem:允许读取该路径;不要禁用沙盒 |
NameResolutionError,且仅在 Agent 沙盒中出现 | 如果 lightning api 也失败,请让用户允许 lightning.ai 和 *.lightning.ai(/sandbox)。如果只有 studio/job 命令或 SDK 失败,它们会绕过沙盒代理:只在沙盒外运行这些命令。后台轮询程序也会以同样方式静默失败 |
上述安装也会让 lightning_sdk 可在该环境中导入,因此 Python 代码片段会使用该环境中的 python 运行。如果 CLI 来自 uv tool 或 uvx 回退方案,请用 uv run --with lightning-sdk python script.py 运行一次性脚本。对于保留在用户项目中的代码,请先征求同意,然后使用项目自身的工具(uv add、poetry add)将 lightning-sdk 声明为依赖项。
解析组织和 teamspace(首先执行)
部署位于由组织或用户拥有的 teamspace 中。切勿猜测。 使用显式的 --teamspace owner/teamspace(Python:teamspace="owner/teamspace";单独的 org=/user= 参数已弃用)、环境变量 LIGHTNING_ORG / LIGHTNING_TEAMSPACE,或配置默认值(lightning config get teamspace)。如果这些都未设置,请列出选项,并询问用户要使用哪个组织/teamspace:
lightning api /v1/memberships | jq -r '.memberships[] | [.ownerType, .name, .projectId] | @tsv'
保存该选择:lightning config set teamspace <owner>/<teamspace>。
使用受限 API 密钥时(没有用户可供询问的 Agent):--teamspace 需要所有者的 slug,而 /v1/memberships 只会提供所有者的 id;同一个 teamspace 可能出现两次(一条 organization 记录和一条具有同一 projectId 的 user 记录)。只有在只列出一个 teamspace 时才继续,优先选择其 organization 记录,并通过 ownerType 解析所有者(需要 jq):
M=$(lightning api /v1/memberships)
if [ "$(printf "%s" "$M" | jq '[.memberships[].projectId] | unique | length')" != 1 ]; then
echo "several teamspaces: ask the user which one" >&2
else
ROW=$(printf "%s" "$M" | jq -c '(.memberships | map(select(.ownerType=="organization"))) + .memberships | .[0]')
TS=$(printf "%s" "$ROW" | jq -r .name); OID=$(printf "%s" "$ROW" | jq -r .ownerId)
if [ "$(printf "%s" "$ROW" | jq -r .ownerType)" = organization ]; then
OWNER=$(lightning api "/v1/orgs/$OID" | jq -r .name)
else # a personal teamspace; the search is fuzzy, so match the id exactly
OWNER=$(lightning api /v1/users/search -X GET -f "query=$OID" \
| jq -r --arg id "$OID" '.users[] | select(.id==$id) | .username')
fi
lightning config set teamspace "$OWNER/$TS" # or pass --teamspace "$OWNER/$TS" each time
fi
CLI 参考
子命令:create、list、inspect、update、delete、logs(以及 logs download)、reload-weights,以及 env / secret(在运行中的部署上执行 list/set/delete)。没有 stop:使用 update --min-replicas 0 --max-replicas 0 将副本数缩减为零。
# container deployment (a --port is required for non-model deployments)
lightning deployment create my-api --teamspace owner/teamspace \
--image nginx:latest --machine CPU --port 80 --replicas 1 --api-key-auth
# HuggingFace model via vLLM (GPU machine required; port defaults to 8000)
lightning deployment create llama --teamspace owner/teamspace \
--model meta-llama/Llama-3.1-8B-Instruct --machine L40S \
[--hf-token-secret <secret-name>] [--tensor-parallel-size 2] [--max-model-len 8192] \
[--quantization fp8] [--dtype bfloat16] [--dry-run] [--force]
# cloud account — if you pass none, the SDK picks one (config `cloud-account`, then
# LIGHTNING_CLUSTER_ID, then the teamspace's default binding) and prints which on stderr.
# Other deployments in the same teamspace may sit on a different account, which
# `deployment list` shows in its last column; match it with --cloud when relevant.
lightning deployment create ... --cloud gcp-lightning-public-prod
# autoscaling / env / secrets
lightning deployment create ... \
--min-replicas 0 --max-replicas 4 --autoscale-metric GPU --autoscale-threshold 90 \
-e KEY=VALUE --secret MY_LIGHTNING_SECRET --interruptible # check the spot price first (below)
# endpoint auth: mutually exclusive; OMITTING ALL THREE MAKES THE ENDPOINT PUBLIC (confirm that's intended)
--api-key-auth # require a Lightning USER API key (Bearer)
--basic-auth USER:PASS
--token-auth TOKEN # any bearer string you choose
# operate
lightning deployment list --teamspace owner/teamspace [--all] [--sort-by state]
lightning deployment inspect my-api --teamspace owner/teamspace # full JSON incl. endpoint URLs
lightning deployment logs my-api --teamspace owner/teamspace [-f] [--tail 100] [--timestamps]
lightning deployment logs my-api --teamspace owner/teamspace --query timeout --severity error # filter server-side
lightning deployment logs my-api --teamspace owner/teamspace --since 30m --until 5m # window (replicas merged + labelled)
lightning deployment update my-api --teamspace owner/teamspace --max-replicas 8
lightning deployment update my-api --teamspace owner/teamspace --min-replicas 0 --max-replicas 0 # "stop"
lightning deployment update my-api --teamspace owner/teamspace --image myimg:v2 [--max-surge 1] [--max-unavailable 0] # new release, rolling update
lightning deployment reload-weights llama --teamspace owner/teamspace # hot-reload BYOM weights
lightning deployment delete my-api --teamspace owner/teamspace --yes
- 根据
lightning auth whoami选择身份验证标志:user调用方使用--api-key-auth,scoped-api-key调用方使用--token-auth。--api-key-auth仅接受 Lightning 用户密钥(它会序列化为userApiKey: true)。使用范围受限密钥的调用方在副本运行期间,每次请求都会得到 401,且费用会按秒计收。若端点由使用范围受限密钥、CI 作业或 Agent 调用,请使用--token-auth <token>。若端点由使用各自 Lightning 登录凭据的人员调用,请使用--api-key-auth。 --interruptible不一定更便宜,因此传入前请先查看价格。 某些 SKU 和云服务中,竞价实例比按需实例更贵,而且创建时不会发出警告。请从加速器目录获取两种价格(参见lightning-cost-estimation技能),并取min(cost, spotPrice)。- 更改镜像、命令、环境变量、入口点、路径映射、健康检查、云账户、竞价实例、数量或最长运行时间会创建新版本;仅切换机器不会。 CLI 会自动添加滚动更新。若部署没有发布策略(既未传入,也未预先存储),SDK 会引发
RuntimeError。
Python SDK
from lightning_sdk import Deployment, Machine
from lightning_sdk.api.deployment_api import (
ApiKeyAuth, BasicAuth, TokenAuth, AutoScaleConfig, Env, Secret,
RollingUpdateReleaseStrategy, HttpHealthCheck,
)
dep = Deployment("my-api", teamspace="my-org/my-teamspace") # owner/teamspace, same as the CLI
dep.start(
image="nginx:latest",
machine=Machine.CPU,
ports=[80], # REQUIRED for non-model deployments; a LIST, not an int
autoscale=AutoScaleConfig(min_replicas=0, max_replicas=4, metric="CPU", threshold=90),
env=[Env("MODE", "prod"), Secret("HF_TOKEN")], # or a plain dict for env vars
auth=ApiKeyAuth(), # None => PUBLIC endpoint
health_check=HttpHealthCheck(path="/health", port=80),
spot=False, # True = interruptible replicas
)
print(dep.urls) # endpoint URL(s); no .status property — use replica counts
print(dep.running_replicas, dep.pending_replicas, dep.failing_replicas)
r = dep.get(path="/health") # convenience HTTP; auto-auths only for ApiKeyAuth
# a new release needs a release strategy (see the release rule under CLI reference)
dep.update(image="nginx:1.27", release_strategy=RollingUpdateReleaseStrategy(max_surge=1, max_unavailable=0))
dep.update(min_replicas=1, max_replicas=8) # scaling: no new release, no strategy needed
dep.stop() # scales to 0; blocks until replicas reach 0
通过 SDK 提供 HuggingFace 模型服务:dep.start(model="meta-llama/...", machine=Machine.L40S, ports=[8000], hf_token_secret="...")。image/studio 必须为 None;仍需传入 ports。
dep.delete() 不会删除部署。 与 dep.get()/dep.post() 一样,它是一个 HTTP 助手:会向已部署服务的端点发送 HTTP DELETE 请求。若要删除部署资源,请使用 lightning deployment delete NAME --yes 或原始 API。
私有容器镜像
镜像需要注册表凭据的部署必须将 V1JobSpec.image_secret_ref 设置为 teamspace 中某个 SECRET_TYPE_DOCKER_REGISTRY 密钥的名称。CLI 和 Deployment.start() 均未提供 image_secret_ref,若不设置,服务器会以模糊的 500 错误拒绝该镜像。 错误信息既不会指出镜像,也不会指出缺少的凭据:
Exception: The jobs_service_create_deployment_with_http_info request failed to reach the server, response: 500.
在 SDK 提供此字段之前,请将其补丁添加到创建请求中:
from lightning_sdk.lightning_cloud.openapi.api import jobs_service_api
_create = jobs_service_api.JobsServiceApi.jobs_service_create_deployment_with_http_info
def _with_image_secret(self, body, project_id, **kwargs):
if getattr(body, "spec", None) is not None:
body.spec.image_secret_ref = "MY_REGISTRY_SECRET"
return _create(self, body, project_id, **kwargs)
jobs_service_api.JobsServiceApi.jobs_service_create_deployment_with_http_info = _with_image_secret
使用以下命令列出 teamspace 的密钥及其类型:
PROJECT_ID=$(lightning api /v1/memberships | jq -r '.memberships[] | select(.name=="<teamspace>") | .projectId')
lightning api "/v1/projects/${PROJECT_ID}/secrets" | jq -r '.secrets[] | "\(.name) \(.type)"'
要诊断此 500 错误,请使用公开镜像(nginx:latest)重试,并保持其他参数不变。 如果创建成功,问题出在镜像,而非机器、端口、副本数量或云账户。
示例工作流
此技能可处理的提示词:"将此 Docker 镜像部署到 API 后面"、"在 lightning 上提供 Llama 3.1 8B 服务"、"夜间缩减我的部署规模"、"推出新镜像版本"。
部署容器,确认其响应,然后清理。 请使用 deployment inspect 返回的端点 URL 进行验证,绝不要验证源 Studio 中的应用。Studio 只能证明镜像可用;只有端点才能证明服务可用。
lightning auth whoami # pick the auth flag from this (see the auth rule under CLI reference)
lightning deployment create hello-api --teamspace my-org/my-teamspace \
--image nginx:latest --machine CPU --port 80 --min-replicas 0 --max-replicas 1 --api-key-auth
lightning deployment inspect hello-api --teamspace my-org/my-teamspace # JSON: status, endpoint URL
URL=<endpoint URL from the inspect output above>
curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $LIGHTNING_API_KEY" "$URL/" # verify the ENDPOINT, not the Studio
from lightning_sdk import Deployment
dep = Deployment("hello-api", teamspace="my-org/my-teamspace")
print(dep.urls) # e.g. ['https://80-dep-<id>-d.cloudspaces.litng.ai'] — available even while scaled to zero
print(dep.get(path="/").status_code) # sends the caller's Lightning API key for ApiKeyAuth
lightning deployment delete hello-api --teamspace my-org/my-teamspace --yes
提供开放权重 LLM 服务(vLLM,由服务器端构建,无需 Dockerfile):
lightning deployment create qwen-served --teamspace my-org/my-teamspace \
--model Qwen/Qwen2.5-7B-Instruct --machine L40S --min-replicas 0 --max-replicas 1 --api-key-auth --dry-run
# review the model spec it prints, then re-run without --dry-run; if the real create reports
# unacknowledged warnings, re-run with --ack <code> (repeatable) or --force
lightning deployment logs qwen-served --teamspace my-org/my-teamspace -f # watch it come up
该端点在端口 8000 上提供兼容 OpenAI 的 API。将任意 OpenAI 客户端的 base_url 指向 dep.urls[0]。
运维:缩放、更新、回滚流量成本:
lightning deployment update hello-api --teamspace my-org/my-teamspace --min-replicas 1 --max-replicas 4 # keep warm
lightning deployment update hello-api --teamspace my-org/my-teamspace --min-replicas 0 --max-replicas 0 # stop (scale to zero)
lightning deployment update hello-api --teamspace my-org/my-teamspace --image nginx:1.27 # new release, rolling by default
原始 API 回退方案
PROJECT_ID=$(lightning api /v1/memberships | jq -r '.memberships[] | select(.name=="<teamspace>") | .projectId' | head -1)
lightning api "/v1/projects/${PROJECT_ID}/deployments" -q '.deployments[].name' # plain GET; -f/-F without -X would send a POST
lightning api "/v1/projects/${PROJECT_ID}/deployments/${DEPLOYMENT_ID}"
lightning api "/v1/projects/${PROJECT_ID}/deployments/${DEPLOYMENT_ID}" -X DELETE
注意事项
- 只要副本处于运行状态,部署就会持续计费;创建前请先向用户确认费用。 在启动 GPU 机器、设置
--min-replicas >= 1(这会持续计费)以及提高--max-replicas(费用上限取决于此值)之前,都要先获得用户明确同意。先使用lightning-cost-estimation技能估算机器费用。 - 请使用
deployment inspect返回的公开 URL 验证部署,切勿使用源 Studio 中的应用进行验证。 Studio 只能证明镜像正常;只有端点才能证明服务正常。部署可能显示副本健康且正常计费,但对每个请求都返回 401。 min_replicas=0会在副本数降至 0 时停止计费,下一个请求会等待冷启动,而不会失败。 边缘层会保持连接打开,直到副本就绪(GPU 镜像大约需要 6 分钟),然后返回正常的 200。它不会返回 503 或拒绝请求,因此没有设置较短超时时间的客户端只会一直等待。min_replicas >= 1会持续计费:请向用户说明这笔费用。- 缩容至零的空闲时间窗口和健康检查只能通过 SDK 设置。
AutoScaleConfig(idle_threshold_seconds=...)和HttpHealthCheck(path=..., port=...)没有对应的deployment create/update标志(没有--health-check-path/--readiness-probe)。通过 CLI 操作时只能使用默认空闲时间窗口,而且无法阻止流量到达已启动但尚未就绪的副本。 - 对现有部署调用
Deployment.start()会静默地变成更新/重启操作。 名称冲突不会报错。 - 端口错误不会指出具体端口。 没有端口的非模型部署会引发
ValueError。在 SDK 中,如果ports是整数,会在 SDK 内部引发TypeError: 'int' object is not iterable,错误信息中不会提到ports。 - 未设置
metric的AutoScaleConfig会在之后调用start()时才失败。 它会引发ValueError: The autoscaling metric is required. Currently supported metrics are ['GPU', 'CPU', 'RPM'],回溯指向start(),而不是配置对象。务必传入metric=。 - 在
deployment inspect中看到Secret("NAME")的name为空并非错误。 它会显示为{"from_secret": "NAME", "name": "", "value": ""};平台会解析该引用,并使用密钥名称作为环境变量名称。 - 任何有权访问 teamspace 的人都能读取部署日志,因此启动时绝不要输出真实密钥。 会打印环境变量的容器会将密钥值泄露到
deployment logs中。 - 显示
Deployment deleted不代表部署已“消失”:部署最多可能会继续列出约 2.5 分钟。 它可能仍以PENDING状态显示在deployment list(和list --all)中,副本数可能已过时,且deletedAt: None。不要将此视为删除失败,也不要轮询list来确认清理完成;如果几分钟后仍然存在,再次执行delete。删除具有破坏性,除非使用--yes,否则 CLI 会提示确认,因此请先征得用户同意。 - 不带
-f的deployment logs可能会在无输出的情况下卡住,且永不返回。 对于脚本中有界的读取(--tail 25,不使用--follow),请单独设置超时。-f可以正常使用。 - 整个部署生命周期中,
deployment inspect中的total_cost都会保持0.0,因此请通过 teamspace 的额度余额衡量费用。 与作业不同,也没有计费/用量端点可以查询部署费用。请比较操作前后的额度余额。连续调用时,该字段会在完整浮点精度和保留 2 位小数的舍入值之间变化,因此应选择足够长的时间窗口,让舍入误差可以忽略。 --dry-run从不会调用服务器,因此不会显示未确认警告的错误。 实际使用--model创建部署时,可能会失败并提示Deployment has unacknowledged warnings: ... Re-run with --ack <code> (repeatable) or --force.。试运行只会回显你设置的模型规格(served_model_name、weight_source以及传入的任何 vLLM 标志),不会显示机器、镜像变体或副本配置。- 使用
--model时遇到无法解释的403,意味着该功能未向你的账户开放;请改用--image。 错误为Exception: The jobs_service_create_deployment_with_http_info request failed to reach the server, response: 403.,且没有服务器消息;LIGHTNING_DEBUG=1会添加回溯,但仍不会说明原因。这是权限问题,不是参数错误,因此不要排查模型 ID 或标志。直接部署 vLLM 容器镜像(--image),不需要此权限。 - 同时传入
teamspace="owner/teamspace"和org=/user=会引发ValueError。 单独传入org=/user=会发出DeprecationWarning。在早于 2026.7.31 的 SDK 中,组合形式会报错并提示 "Teamspace owner/name does not exist";请升级,而不要拆开传入。