Skip to content

云盘的工作方式

在沙箱或方块中挂载云盘、唯一的写入方、云盘存放在哪里、如何计费,以及项目最多能保有多少。

更新于

调用

调用 作用
POST /v1/drives {name?, size_bytes?, region?, durability?} 创建一个云盘,里面只有文件系统。大小必须是 4 KiB 块的整数倍,最小 16 MiB;默认 64 GiB,免费版上为 5 GiB。区域默认为控制平面所在的区域。durability 默认为 standard,也可以设为 strict(见下文)。
GET /v1/drives, GET /v1/drives/{id} 项目的云盘,最新的在前;按 id 或名称查看一个。
PATCH /v1/drives/{id} {name} 重命名,或去掉名称 (null)。
DELETE /v1/drives/{id} 删除云盘及其中的内容。沙箱持有的云盘不能删除 (409 drive_attached)。
POST /v1/sandboxes/{id}/drives {drive, path, mode?, snapshot?} 立即以读写方式把它挂载到一个已有的沙箱中;休眠的沙箱会被唤醒。带上 mode: "snapshot" 和 snapshot 时,改为以只读方式挂载它的那个快照。
DELETE /v1/sandboxes/{id}/drives/{drive} 卸载它,先把文件系统写出。仍有进程在使用时会被拒绝 (409 mount_in_use),除非带 ?force=true。用快照的 id 时,卸载该快照的只读挂载。
POST /v1/sandboxes 带上 drives: [{drive, path, mode?, snapshot?}] 在新沙箱中挂载云盘,或以只读方式挂载云盘的快照。
POST /v1/drives/{id}/snapshots, /restore, /fork 为它创建快照;把它恢复到某个快照;从某个快照或它当前的状态创建新云盘。参见快照与分叉。
POST /v1/drives/{id}/home 立即把它的归属区域迁到它现在所在的区域,不必等它到那里一小时之后(跨区域)。

云盘对象包含 id(vol-…:云盘底层就是存储卷)、name、size_bytes、used_bytes(已写入的数据量,也是计费依据)、attached_to(以读写方式持有它的沙箱及挂载路径:最多一个)、region(它现在所在的区域)、home 和 home_move(跨区域)、durability、status、lease(沙箱持有它期间:写入它的机器,以及租约的到期时间)、app_id 和 key(键控实例的云盘)、parent_drive_id 和 root_drive_id(分叉出的云盘才有:来源云盘,以及这一脉的第一个云盘;其他云盘为 null),以及 created_at。

挂载

  • 在沙箱中:创建时用 --drive data:/data,运行时用 glac drives attach data web:/data。一个沙箱挂载的云盘和存储卷合计最多 8 个(409 too_many_drives;只请求存储卷时为 too_many_volumes)。
  • 在方块中:版本上的 --drive data:/var/lib/data(API 中为 drives)由服务唯一的实例挂载。带云盘的服务只有一个实例,多个实例或使用键都会被拒绝 (409 drive_single_writer)。实例创建在应用的第一个区域中,这个区域必须是云盘所在的区域 (--region)。参见保存数据的服务。
  • 每个键一个:键控应用的版本可以给每个键的实例一个独立的云盘(--key-drive home:/home/app:10GiB、key_drives),随该键的第一个实例创建,随键删除。参见键控实例。
  • 从快照只读挂载:云盘所在区域的任意多个沙箱可以同时以只读方式挂载它的某个快照(mode: "snapshot"、glac drives attach data web:/then --snapshot dsnap-…),无论云盘被谁持有。为挂载而从对象存储取来的数据不收费,作为冷读显示在持有该挂载的沙箱名下。参见以只读方式挂载快照。

里面的文件系统是 ext4。删除文件释放的空间会被归还:机器每分钟对云盘执行一次 trim,used_bytes 随之下降。

唯一的写入方

同一时间只有一个沙箱能以读写方式挂载云盘;快照的只读挂载不受此限。挂载另一个沙箱持有的云盘会被拒绝 (409 drive_attached),删除已挂载的云盘也一样。沙箱持有云盘期间,运行该沙箱的机器持有云盘的租约。如果那台机器不再响应,在租约到期之前谁都不能写入这个云盘(503 node_unavailable,附带到期时间);之后,下一个沙箱从对象存储接手它,旧机器再也不能写入。

数据库的云盘只能由数据库的实例以读写方式挂载,重命名、恢复和删除都要通过数据库进行:在这里调用这些操作,或在别处以读写方式挂载它,都会被拒绝 (409 managed_by_database)。它的 managed_by 会说明这一点 ({"object": "database", "id": "db-…"})。和任何云盘一样,项目可以为它创建快照、分叉快照、以只读方式挂载快照。

云盘在哪里

云盘创建在一个区域中,即它的归属区域。它的数据块在最近持有它的机器的 NVMe 磁盘上,写入的同时被复制到所在区域的对象存储中。

  • 在持有云盘的机器上,沙箱把它当作本地磁盘挂载。
  • 同一区域另一台机器上的沙箱也能使用它:云盘会被搬到那里,数据块在被读取时从对象存储取来。对象存储中还没有云盘的最新状态时,调用返回 503 copy_behind 或 drive_not_brought,二者都可重试 (retryable):稍后再调用一次即可。
  • 没有沙箱持有、也没有机器保存的云盘,留在对象存储中等待;下次挂载时,由区域中的任意一台机器接手。
  • 沙箱迁到另一台机器时,会带着它的云盘一起走。
  • 挂载云盘的新沙箱会创建在保存该云盘的机器上(如果那台机器有空间),或者创建在云盘能搬过去的机器上。哪台都接不了时,调用返回 503 no_capacity,错误信息会说明每个云盘在哪里,以及为什么没有别的机器能接手。

跨区域

另一个区域的沙箱也能挂载云盘,前提是那个区域的机器能读取云盘归属区域的对象存储(不能时返回 409 not_on_one_machine):可以在那里新建一个带这个云盘的沙箱,也可以把它交给那里正在运行的沙箱。

  • 保存它的机器先把它释放为一个包含所有写入的版本,另一个区域的机器再从这个版本接手:云盘立即挂载,客户机读到哪里,就从归属区域的存储读取哪里的数据块(跨区域冷读,速度取决于两地之间的链路)。
  • 客户机写入的数据进入它现在所在区域的对象存储:它的 region 是这个区域,而 home 仍是它原来的区域。
  • 云盘在那里待满一小时后,归属区域会跟过去;也可以用 POST /v1/drives/{id}/home (glac drives home data) 立即迁移:它的机器在后台把归属区域存储中剩下的内容原样复制到自己区域的存储中,那里什么都不剩时,home 就变成新区域。home_move 显示迁移进行到哪一步(asked_at;asked_by,即 user 或 away;copied_objects、copied_bytes、objects_left;error,即停下的位置:它会自行继续)。
  • 如果归属区域迁移之前,云盘又回到归属区域挂载,它在另一个区域写入的数据会以同样的方式复制回归属区域(asked_by 为 back),归属区域保持不变。迁移期间,已迁过去的数据从新区域的存储读取,无论旧存储发生了什么。
  • 云盘保留的版本都不再需要旧归属区域的副本后(迁移一天后,即对象存储的宽限期),这份副本会被删除。
  • 云盘的归属区域最多每六小时迁移一次(409 home_moved_recently,附带 retry_after_seconds):在两个区域轮流使用的云盘,不会被来回复制。归属区域就是当前所在区域的云盘返回 409 home_here,没有任何机器保存的云盘返回 503 drive_in_store(先挂载它)。

云盘的快照留在创建快照时云盘所在的区域,也只能在那里以只读方式挂载(快照)。

写入有多持久

云盘的 durability 在创建时设定,之后不再改变:

  • standard(默认):客户机的 fsync 立即返回,写入稍后才进入对象存储。机器丢失时,最多丢失最后一秒的写入。
  • strict:客户机的 fsync 以及文件系统的每次刷写,都要等对象存储保存了此前的全部写入才返回,所以机器丢失时,客户机已同步的数据一点都不会丢。每次 fsync 都要等一次对象存储请求:适合提交必须在机器丢失后仍然存在的数据库。strict 云盘只保存在会把磁盘复制到对象存储的机器上,也只能由从支持 strict 云盘之后构建的模板创建的沙箱挂载;其他情况都会被拒绝 (409 strict_unsupported)。
glac drives create --name pgdata --size-bytes 20GiB --durability strict

计费内容

  • 数据:used_bytes,即已写入且没有被 trim 掉的字节,全部保存在分层存储中,按小时计,每 GB·月 $0.02:不按云盘的大小计费。这属于数据计量项,与休眠沙箱和快照共用,免费版的 15 GB 和付费版的 20 GB·月 是它们合计的额度。
  • NVMe 缓存(账单上称为存储卷缓存):云盘保存在机器 NVMe 上的部分,每个云盘可以设为从完全不缓存到全部缓存,默认全部缓存;无服务器 Postgres 数据库缓存其云盘的四分之一,至少 1 GiB。价格为每 GB·月 $0.06,按小时计,取缓存大小与已保存数据量中较小的一个:全部缓存时为每 GB·月 $0.08。免费版的缓存最多与云盘保存的数据一样多,合计不超过 15 GB,这是存量上限,不是每日配额;付费版每月包含 20 GB·月。
  • 写入和读取都不收费,无论是否缓存:没有缓存时,数据块以网络的速度读取。
  • 快照:云盘的每个快照按它单独保留的数据计费,价格和计量项都与云盘保存的数据相同。参见快照页面上的计费内容。

GET /v1/usage?group_by=drive(或 drive_id=、kind=drive)报告每个云盘的用量,glac usage --drive data 也一样。支出上限、余额用完和未付欠款对云盘的限制与对沙箱相同:欠费的账户可以列出、读取和删除它的云盘及其快照,但不能创建、挂载或重命名云盘,也不能创建快照、分叉或恢复 (402 account_in_debt)。参见价格与套餐。

项目能保有多少

免费版 付费版
单个项目的云盘和存储卷 3 500
单个云盘上限 10 GiB 1 TiB
一个项目所有云盘合计 15 GiB 不限
单个沙箱挂载的云盘和存储卷 8 8

超过这些数量时,新建云盘会被拒绝(403 drive_limit_reached,并给出具体数字)。在付费版上,数量是一个软限制:可以应要求提高。企业账户可以获得最大 16 TiB 的云盘。键控实例的云盘按字节计,不按个数计。分叉出的云盘按其大小算作一个新云盘。快照不计数:一个云盘可以有任意多个快照。

事件

drive.created、drive.deleted、drive.attached 和 drive.detached(带有 reason:sandbox_deleted、drive_deleted,由调用触发时没有)会出现在项目的事件和 Webhook 中,drive.snapshot.created 和 drive.snapshot.deleted 也一样。快照的只读挂载不会发出 drive.attached 或 drive.detached。

尚未支持

  • 在快照创建时所在区域以外的区域,以只读方式挂载快照 (409 not_on_one_machine)。
  • 重命名没有任何机器保存的云盘(503 drive_in_store:挂载后再重命名)。
  • 在方块的版本中使用只读挂载:版本以读写方式挂载它的云盘,在那里使用 mode: "snapshot" 会被拒绝 (400 invalid_field)。只读挂载只供沙箱使用。
  • 快照、分叉和只读挂载尚未支持的功能,见它们的页面。
导航

输入以搜索……

↑↓ 切换↵ 选择Esc 关闭