模板
报价决定你拿到什么硬件。模板决定在上面跑什么。部署这两样都要有:你在市场里挑好报价,部署页面会把它带下去,同时你挑选模板。
模板是一份启动配方
模板是对“这台机器应该启动进入什么”这个问题的一份已保存答案。它包含:
| 组成部分 | 它决定什么 |
|---|---|
| 镜像与标签 | 要拉取的容器镜像,可以来自私有镜像仓库。 |
| 启动模式 | 容器如何启动,以及随之带来哪些端口。 |
| 端口 | 发布哪些容器端口,每个端口带一个标签。 |
| 环境 | 交给容器的变量。值可以标记为机密。 |
| 启动脚本 | 容器第一次启动时在容器内运行的命令。之后再启动不会重新运行它们。 |
| 约束 | 最低 CUDA 版本、最低显存,以及部署页面在放你启动之前会检查的其他硬件下限。 |
模板从不指定某台机器。它的约束是下限——一个最低 CUDA 版本、一个最低显存——而不是绑定某台主机,所以同一个模板不用改就能部署到 1× RTX 4090 或 8× H100 PCIe 上,只要两者都过得了这些下限。这正是保存一个模板、而不是每次重填一遍相同设置的价值所在。
启动模式
启动模式是唯一一个改变实例形态而不是内容的字段。
| 模式 | 你得到什么 |
|---|---|
ssh | 一个 SSH 服务器。端口 22 会自动为你加上。 |
jupyter | JupyterLab 加一个 SSH shell。端口 22 和 8080 会自动为你加上。 |
args | 镜像自带的 entrypoint,用你提供的参数运行。无交互界面。 |
vm | 一台完整的 KVM 虚拟机。只能部署到支持 VM 的报价上。 |
ssh 和 jupyter 需要一个从 Superheat 基础镜像派生的镜像,因为这两种模式依赖基础镜像的 entrypoint 来拉起 SSH 守护进程和 JupyterLab。args 和 vm 可以跑任何镜像。参见 启动模式。
无论你的模板设了什么,平台都会在其之上覆盖自己的环境,而且覆盖的一方胜出。你无法从模板里改掉 JupyterLab 令牌或 GPU 数量。环境变量 讲了平台控制哪些内容。
可见性
每个模板都有三种可见性级别之一。
| 可见性 | 谁能看到 | 谁能编辑 |
|---|---|---|
system | 所有人。这些是 Superheat 维护的精选起点。 | 没有人。系统模板通过 API 是不可变的。 |
private | 只有拥有它的组织。这是你创建的任何模板的默认值。 | 那个组织。 |
public | 所有人。任何账户都能读到这份配方。 | 拥有它的组织。 |
机密环境值对拥有该模板的组织以外的人是遮蔽的,所以发布模板分享的是配方,而不会泄露烧进去的凭据。
你不能编辑不属于你的系统模板或公开模板,但你可以复制任何你能看到的模板。副本会以 private 落到你的组织里,随你改动。复制别人的模板会清空它的机密值和私有镜像仓库凭据——这些由你自己提供。
模板为什么有两个身份
模板有一个稳定的 id 和一个 hash_id。hash_id 是与启动相关的那些字段的内容哈希——镜像、标签、仓库、模式、参数、启动脚本、环境、端口、约束、Jupyter 目录与 JupyterLab 开关,以及私有镜像仓库的用户名——并加上 th_ 前缀。
只要这些字段中任何一个发生变化,它就会重新生成;而当所有者修改名称、描述、readme、可见性或排序时,它保持不动。启动配方有自己的身份,与承载它的那一行记录分开。
这种拆分给了你两种指向模板的方式:
| 你分享的东西 | 行为 |
|---|---|
| id | 跟着模板走。如果所有者改了它启动的内容,你的链接就会启动新版本。 |
hash_id | 标识某一份确切的配方。如果所有者改了它启动的内容,旧的哈希就解析不出来了。 |
当别人需要复现你的运行时,该用的是第二种。一个过期的哈希链接会明确报错,而不是悄悄启动一个已经不是你测过的东西。API 在 GET /v1/templates/by-hash/{hash_id} 解析它。