mcpField
L
lightning-deployments

lightning-deployments

github.com/lightning-ai云与 DevOps962 次安装2 周前更新
代码仓库

关于 lightning-deployments

lightning-deployments 是用于在 Lightning AI 上创建和运维部署的技能,面向需要发布容器服务或 HuggingFace 模型的开发者。它涵盖 CLI 与 Python SDK 操作,并说明扩缩容、发布和认证注意事项。

主要功能

  1. 01部署 Docker 镜像、Studio 环境或 HuggingFace 模型
  2. 02管理部署与版本发布
  3. 03调整副本数量并缩容至零
  4. 04查看日志、配置环境变量和密钥
  5. 05通过 CLI 或 Python SDK 操作

适用场景

  1. 01将容器镜像发布为 HTTPS 服务
  2. 02使用 vLLM 提供 HuggingFace 模型 API
  3. 03按负载调整部署副本数量
  4. 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 argumentCLI 版本太旧:在 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";请升级,而不要拆开传入。

评论

支持 Markdown