ドライブのスナップショットは、ある時点のドライブをそのまま保持します。ドライブは書き込まれるそばからリージョンのオブジェクトストアにコピーされ、スナップショットはそこにあるドライブの 1 つのバージョンです。取得しても、使っても、それ以上のコピーは行われません。スナップショットからは、次のことができます。
- ドライブをその場でスナップショットの状態に復元する
- フォークする:スナップショットと同じ中身を持つ新しいドライブを作り、すぐにマウントできる
- ドライブのリージョンのどのマシン上でも、いくつものサンドボックスで同時に読み取り専用でマウントする
スナップショットはドライブより長く残ります。ドライブが削除された後も、スナップショットは一覧表示、フォーク、読み取り専用でのマウントができます。
どのクライアントにもこれらの呼び出しがあります。コマンドライン(glac drives snapshots、glac drives fork、glac drives restore、glac drives attach --snapshot)、SDK(下記の Python と TypeScript、そして Go、Rust、Java の SDK)、MCP サーバー(drive_snapshot、drive_fork、drive_restore)、そしてコンソールの Drives ページです。コンソールでは、各ドライブの Snapshots で、スナップショットの取得、フォーク、復元、削除ができます。
呼び出し一覧
| 呼び出し | 内容 |
|---|---|
POST /v1/drives/{id}/snapshots {name?, fs_consistent?} |
ドライブのスナップショットを今すぐ取得。スナップショットとともに 201 を返す |
GET /v1/drives/{id}/snapshots |
ドライブのスナップショットの一覧(新しい順)。削除済みのドライブのものは、その ID で |
GET /v1/drive-snapshots |
プロジェクトの全ドライブのスナップショットの一覧(新しい順)。その後削除されたドライブのスナップショットは、そのドライブの ID とともにここで見つかる。?drive_deleted=true ならそれだけを、false ならそれ以外を一覧表示(ドライブを指定しない glac drives snapshots ls) |
GET, DELETE /v1/drives/{id}/snapshots/{snapshot} |
ID で指定した 1 つのスナップショット。削除 |
POST /v1/drives/{id}/restore {snapshot} |
ドライブをスナップショットの状態に復元。ドライブを返す |
POST /v1/drives/{id}/fork {name?, from_snapshot?} |
スナップショット、またはドライブの現在の状態から作る新しいドライブ。新しいドライブとともに 201 を返す |
POST /v1/sandboxes/{id}/drives {drive, path, mode: "snapshot", snapshot} |
既存のサンドボックスにスナップショットを読み取り専用でマウント。スナップショットを返す |
drives: [{drive, path, mode: "snapshot", snapshot}] を付けた POST /v1/sandboxes |
新しいサンドボックスに読み取り専用でマウント |
DELETE /v1/sandboxes/{id}/drives/{snapshot} |
スナップショットの ID で、読み取り専用のマウントを外す |
{id} はドライブの ID か名前です。スナップショットの一覧表示と読み取りには read を持つキーが、それ以外の呼び出しには write が必要です。各呼び出しのすべてのフィールドとレスポンスは API リファレンスにあります:取得、一覧、読み取り、削除、復元、フォーク、マウント、マウントの解除。
スナップショットは、id(dsnap-…)、対象のドライブの drive_id、name、consistency(取得時にドライブの書き込みをどう止めたか。後述)、used_bytes(取得時にドライブが保持していた量)、exclusive_bytes(単独で保持する量。課金の基準)と exclusive_at(それを最後に計算した日時)、スナップショットにあたるドライブの version(number、epoch)、created_at を持ちます。
名前は省略できます。英小文字、数字、ハイフンで 1〜63 文字、先頭と末尾はハイフン以外で、vol- や dsnap- のような ID の接頭辞で始めることはできません(400 invalid_name)。2 つのスナップショットが同じ名前を持つこともあるため、呼び出しではスナップショットを ID で指定します。
スナップショットの取得
例では、ドライブは data で、サンドボックス web がそれを /data で持っています。glac drives snapshots create はスナップショットの ID を表示し、ここではそれを SNAP に入れています。
SNAP=$(glac drives snapshots create data --name before-upgrade --fs-consistent)ドライブのスナップショットは、サンドボックスが持っていてもいなくても取得できます。
- 実行中のサンドボックスが持っていない場合(マウントされていない、または持っているサンドボックスがスリープ中):スナップショットはドライブの現在の状態です(
consistency: "at_rest")。 - 実行中のサンドボックスが持っている場合:スナップショットは 2 段階で取得されます。まず、サンドボックスが書き込みを続ける間に、呼び出しまでに書き込まれた内容のバージョンを作ります。次に、書き込みを止めて、その間に書き込まれた内容のバージョンを作ります。止める時間は、書き込みの少ないサンドボックスなら 1 秒未満で、最大 10 秒です。それを超えるとスナップショットは拒否され(再試行できる 503
unavailable)、サンドボックスはそのまま動き続けます。まだオブジェクトストアにないものが先に送られるため、直前に大量に書き込まれたドライブでは時間がかかります。 - 書き込みの止め方:デフォルトでは、サンドボックスのマシンを一時停止します(
consistency: "paused")。ドライブは停電の後と同じ状態になりますが、ファイルシステムのジャーナルはそのためにあります。fs_consistent: true(--fs-consistent)を指定すると、代わりにサンドボックス内のエージェントがドライブのファイルシステムを凍結します("frozen")。ファイルシステムが保持しているものが先に書き出され、スナップショットはジャーナルを再生せずにマウントできます。エージェントが凍結できなければ呼び出しは拒否される(409not_frozen)ので、これを指定せずにスナップショットを取ってください。
ドライブのスナップショットを一覧表示し、1 つを読み、1 つを削除します。
glac drives snapshots ls data # newest first: how each was taken, what it keeps alone
glac drives snapshots get data $SNAP
glac drives snapshots rm data $SNAP削除したスナップショットはすぐに消え、その時点まで課金されます。そこから作ったフォークは必要なものを保持し、それを読み取り専用でマウントしているサンドボックスは、マウントが外されるかサンドボックスが削除されるまでマウントを保ちます。
ドライブの復元
復元は、ドライブをスナップショットの状態に戻します。復元後のドライブは、スナップショットの取得時に保持していたものを保持します。ドライブの最新のバージョンの後に、スナップショットの内容を持つ新しいバージョンを書き込みます。何もコピーされず、ドライブの ID と名前は変わりません。
glac drives detach data web
glac drives restore data $SNAP
glac drives attach data web:/data- サンドボックスが読み書き可能で持っているドライブは復元できません(409
drive_attached)。先にデタッチし、復元後にアタッチし直してください。 - その間のバージョンは、スナップショットかフォークが保持している限り残ります。ドライブのほかのスナップショット(これより後に取ったものも含む)とフォークはそのままなので、古いスナップショットに復元したドライブを、その後に新しいスナップショットに復元することもできます。
- 復元の直前にドライブが保持していたものは、スナップショットが保持する場合にしか残りません。戻ってくる可能性があるなら、先にスナップショットを取ってください。
- 復元後、ドライブのブロックは読み取られるのに合わせてオブジェクトストアから取得されます。
ドライブのフォーク
glac drives fork(POST /v1/drives/{id}/fork)は、スナップショット(--from-snapshot、from_snapshot)を最初のバージョンとする新しいドライブを作り、その ID を表示します。スナップショットを指定しなければ、ドライブの現在の状態から作ります。スナップショットと同じようにフォークのためのバージョンが作られますが、それは保持されません。何もコピーされないため、フォークはすぐにマウントでき、ブロックは読み取られるのに合わせてオブジェクトストアから届きます。
glac drives fork data --name data-try --from-snapshot $SNAP
glac sandboxes create --name try --drive data-try:/data
glac drives get data-try # with parent_drive_id (the id of data) and root_drive_id- フォークは、ほかと同じドライブです。専用の ID と名前を持ち、一度に 1 つのサンドボックスが書き込み、ドライブとして課金され、ドライブとしての制限を受けます。サイズは元のドライブと同じで、元のドライブのリージョンにあります。
parent_drive_idはフォーク元のドライブ、root_drive_idはフォークの系統の最初のドライブです。フォークでないドライブでは、どちらもnullです。- フォークが書き込むものはフォーク自身のもので、元のドライブとスナップショットは変わりません。どちらを削除しても、フォークは必要なものを保持します。
- 削除済みのドライブのスナップショットは、そのドライブの ID でフォークします。
- フォークの名前に、プロジェクトのほかのドライブやボリュームの名前は使えません(409
name_taken)。プランのドライブ数を超えるフォークは、新しいドライブと同じく拒否されます(403drive_limit_reached)。
スナップショットの読み取り専用のマウント
読み取り専用のマウントは、スナップショットが持つとおりのドライブを、サンドボックスのパスに提供します。ドライブのリージョンのどのマシン上でも、ドライブを誰が持っていても、いくつものサンドボックスが 1 つのスナップショットを同時にマウントできます。1 つのサンドボックスが、ドライブを読み書き可能で、そのスナップショットの 1 つを読み取り専用で持つこともできます。ドライブが削除された後のスナップショットもマウントできます。
glac drives attach data web:/then --snapshot $SNAP # in a sandbox that runs
glac sandboxes exec web -- ls /then
glac drives detach $SNAP web # by the snapshot's id
glac sandboxes create --name reader --drive data:/then:dsnap-… # in a new sandbox: the snapshot's id after the path- 指定するドライブ(API では
drive)は、スナップショットの対象のドライブです。その ID か名前、または削除済みのドライブの ID です。別のドライブのスナップショットは拒否されます(400invalid_field)。 - 新しいサンドボックスでは、
drivesに同じオブジェクトを指定してマウントします(POST /v1/sandboxes。コマンドラインでは--drive DRIVE:/PATH:SNAPSHOT。そこでの--snapshotは、続きを始めるサンドボックスのスナップショットを指すため)。読み取り専用のマウントは、サンドボックスを作るマシンを決めませんが、サンドボックスはドライブのリージョンに作られます。別のリージョンを指定した作成や、2 つのリージョンのドライブを指定した作成は拒否されます(409not_on_one_machine)。 - ドライブとは別のリージョンのマシンで動くサンドボックスも拒否されます(409
not_on_one_machine)。 - ファイルシステムは読み取り専用でマウントされ、サンドボックスは書き込めません。
- ブロックはサンドボックスが読むのに合わせてオブジェクトストアから届き、サンドボックスのマシンに保持されます。読み取りに料金はかかりません(後述)。保持されたブロックは、1 つのアカウントがそのマシンのディスクに持てる割り当て量に数えられ、それを超えるとマウントは拒否されます(403
account_share_reached。量が示されます)。 - 1 つのサンドボックスがマウントするドライブとボリュームの上限 8 個に数えられます(409
too_many_drives)。 - ドライブの
attached_toには含まれず、drive.attachedイベントもdrive.detachedイベントも送られません。 - スナップショットの ID で外します。ドライブの ID か名前で外せるのは、読み書き可能なマウントだけです(404
drive_not_attached)。サンドボックスを削除しても外れます。
サンドボックスのスナップショットとドライブ
ドライブを読み書き可能で持つサンドボックスのスナップショットは、各ドライブをバージョンとして保持し、ドライブのものは何もコピーしません。そのスナップショットから作ったサンドボックスには、各ドライブのフォークが同じパスにマウントされ、スナップショットの取得時にドライブが保持していたものを持ちます。ドライブ自体は最初のサンドボックスのままで、その後に書き込まれたものはフォークに届きません。
これらのフォークはそれぞれ、ほかと同じプロジェクトのドライブです。一覧に表示され、parent_drive_id は元のドライブで、used_bytes で課金され、新しいサンドボックスが削除されても、削除するまで保持されます。
Python と TypeScript から
from glac import DriveMount, Glac
glac = Glac() # GLAC_API_KEY and GLAC_API_URL
drive = glac.drives.get("data")
web = glac.sandboxes.get("web") # the sandbox that has it
snap = drive.snapshot(name="before-upgrade", fs_consistent=True)
for s in drive.snapshots():
print(s.id, s.name, s.consistency, s.exclusive_bytes)
# a new Drive made of the snapshot, in a new sandbox
fork = glac.drives.fork(drive, name="data-try", from_snapshot=snap)
trial = glac.sandboxes.create(drives=[DriveMount("/data", fork)])
# the snapshot, read-only: in a new sandbox, and in one that runs
reader = glac.sandboxes.create(drives=[DriveMount("/then", drive, snapshot=snap)])
glac.drives.attach_snapshot(trial, snap, "/then")
print(trial.run("ls /then").stdout)
glac.drives.detach_snapshot(trial, snap)
# the Drive back to the snapshot, while no sandbox has it read-write
glac.drives.detach(web, drive)
glac.drives.restore(drive, snap)
glac.drives.attach(web, drive, "/data")
snap.delete()import { Glac } from "glac";
const glac = new Glac(); // GLAC_API_KEY and GLAC_API_URL
const drive = await glac.drives.get("data");
const web = await glac.sandboxes.get("web"); // the sandbox that has it
const snap = await drive.snapshot({ name: "before-upgrade", fsConsistent: true });
for (const s of await drive.snapshots()) console.log(s.id, s.name, s.consistency, s.exclusiveBytes);
// a new Drive made of the snapshot, in a new sandbox
const fork = await glac.drives.fork(drive, { name: "data-try", fromSnapshot: snap });
const trial = await glac.sandboxes.create({ drives: [{ path: "/data", drive: fork.id }] });
// the snapshot, read-only: in a new sandbox, and in one that runs
const reader = await glac.sandboxes.create({ drives: [{ path: "/then", drive: drive.id, snapshot: snap }] });
await glac.drives.attachSnapshot(trial, snap, "/then");
console.log((await trial.run("ls /then")).stdout);
await glac.drives.detachSnapshot(trial, snap);
// the Drive back to the snapshot, while no sandbox has it read-write
await glac.drives.detach(web, drive);
await glac.drives.restore(drive, snap);
await glac.drives.attach(web, drive, "/data");
await snap.delete();スナップショットは、どちらでも DriveSnapshot で、専用の refresh、fork、restore、attach、detach、delete を持ちます。attach はドライブを読み書き可能でマウントします。スナップショットを読み取り専用でマウントするには、attach_snapshot(attachSnapshot)を使うか、新しいサンドボックスの drives に snapshot を指定します。すべての呼び出しは Python と TypeScript の SDK のページを参照してください。
コマンドラインで
| コマンド | 内容 |
|---|---|
glac drives snapshots create DRIVE [--name NAME] [--fs-consistent] |
スナップショットを取得し、ID を表示 |
glac drives snapshots ls DRIVE, get DRIVE SNAPSHOT, rm DRIVE SNAPSHOT… |
ドライブのスナップショットの一覧(新しい順)、1 つの詳細、削除。削除済みのドライブのものは、その ID で |
glac drives restore DRIVE SNAPSHOT |
ドライブをスナップショットの状態に戻す |
glac drives fork DRIVE [--name NAME] [--from-snapshot SNAPSHOT] |
スナップショット、またはドライブの現在の状態から作る新しいドライブ。ID を表示 |
glac drives attach DRIVE SANDBOX:/PATH --snapshot SNAPSHOT, glac drives detach SNAPSHOT SANDBOX |
実行中のサンドボックスにスナップショットを読み取り専用でマウント。外す |
glac sandboxes create --drive DRIVE:/PATH:SNAPSHOT |
スナップショットを読み取り専用でマウントした新しいサンドボックス |
glac drives get DRIVE |
フォークの parent_drive_id と root_drive_id(ドライブのほかの情報とともに) |
glac usage --snapshot SNAPSHOT |
1 つのスナップショットが保持した量 |
課金対象
- スナップショットは、単独で保持する量(
exclusive_bytes)に対して課金されます。そのバージョンが必要とするデータのうち、ドライブの現在の状態、より新しいスナップショット、フォークのどれも必要としないものです。2 つのスナップショットが保持するデータは、古い方で数えます。取得後に変更されていないドライブのスナップショットが単独で保持するものはありません。ドライブが削除された後は、ドライブが保持していたものはスナップショットで数えます。 - 1 時間ごとに、1 GB-月あたり $0.02 で、ドライブが保持するものと同じデータの計測項目で課金されます。課金は、単独で保持する量が初めて計算された時点(
exclusive_at)から、削除されるまでです。有料プランには毎月 20 GB-月 のデータが含まれ、スナップショット、ドライブ、スリープ中のサンドボックスで共有します。無料プランで同時に保持できるデータはスナップショットを含めて最大 15 GB で、それを超えると、アカウントの保持量が減るまで新しいスナップショットは拒否されます(403storage_quota_reached)。料金とプランを参照してください。 GET /v1/usage?snapshot_id=dsnap-…は 1 つのスナップショットが保持した量を報告し、glac usage --snapshot dsnap-…も同じです。- フォークはドライブであり、ドライブとして
used_bytesで課金されます。読み取ったときに見える中身すべてで、作成元のスナップショットと共有しているデータも含みます。10 GB を保持するドライブのスナップショットのフォークは、内部ではブロックの大半が共有されていても、最初から 10 GB のドライブとして課金されます。NVMe キャッシュはほかのドライブと同じく課金され、書き込みと読み取りに料金はかかりません。ドライブの仕組みを参照してください。 - 読み取り専用のマウント:そのために階層型ストレージから取得するブロックに料金はかからず、1 つのスナップショットを 2 つのサンドボックスがマウントしても、どちらも無料で読めます。マシン上に保持するブロックはスナップショットのキャッシュで、スナップショット自体は上記のとおり課金されます。
未払いや支出の制限があるアカウント
- 未払い状態のアカウントは、未払いが増え続けないように、ドライブのスナップショットの一覧表示、読み取り、削除ができます。スナップショットの取得、フォーク、復元、マウントはできません(402
account_in_debt)。最初のメールから 30 日経っても未払いが残っていれば、保存しているものはスナップショットも含めてすべて削除されます(drive.snapshot.deleted)。未払いのあるアカウントを参照してください。 - 利用上限額で止められているプロジェクトや、有料プランの期間に含まれる CPU 時間かメモリを使い切って残高もないアカウントのプロジェクトでは、スナップショットの取得もフォークの作成もできません(403
spend_limit_reached、balance_used_up)。無料プランでは、そのどちらかの 1 日のクォータを使い切ったアカウントも、00:00 UTC まではできません(429quota_used_up)。スナップショットが保持するものは引き続き数えられます(計測項目を使い切ったとき)。
制限とエラー
- ドライブはスナップショットをいくつでも持てます。それぞれ単独で保持する量に対して課金されます。スナップショットは、プロジェクトのドライブの数には数えません。
- フォークは、そのサイズの新しいドライブとして数えます。プロジェクトが保持できる量を参照してください。
- 読み取り専用のマウントは、サンドボックスのドライブとボリュームの上限 8 個に数えます。
| レスポンス | 条件 |
|---|---|
400 invalid_name |
英小文字、数字、ハイフンによる 1〜63 文字でない名前、または ID の接頭辞で始まる名前 |
400 missing_field |
snapshot のない復元。mode: "snapshot" で snapshot のないマウント |
400 invalid_field |
snapshot が別のドライブのスナップショットを指している、または mode: "snapshot" なしで指定されている |
402 account_in_debt |
未払いがある間の、一覧表示、読み取り、削除以外の操作 |
403 drive_limit_reached |
プランでプロジェクトが保持できるドライブ数を超えるフォーク |
403 spend_limit_reached, balance_used_up |
プロジェクトが止められている間のスナップショットやフォーク |
403 storage_quota_reached |
無料プランで、アカウントが同時に保持できる上限までデータを保持している間のスナップショット |
429 quota_used_up |
無料プランで、その日の CPU 時間かメモリのクォータを使い切った後、00:00 UTC までのスナップショットやフォーク |
403 account_share_reached |
アカウントが、1 つのアカウントで持てる上限までディスクをすでに使っているマシン上での、フォーク、復元、読み取り専用のマウント。メッセージに量が示される |
404 drive_not_found, snapshot_not_found |
その ID や名前のドライブがない、またはドライブにその ID のスナップショットがない。削除済みのドライブのスナップショットには、ドライブの ID でアクセスする |
404 drive_not_attached |
スナップショットの ID ではなく、ドライブの ID か名前で外そうとした読み取り専用のマウント、またはサンドボックスが持っていないマウント |
409 drive_attached |
サンドボックスがドライブを読み書き可能で持っている間の復元 |
409 not_frozen |
fs_consistent: true で、サンドボックス内のエージェントがファイルシステムを凍結できなかった |
409 name_taken |
フォークの名前が、ほかのドライブやボリュームの名前と同じ |
409 not_on_one_machine |
ドライブとは別のリージョンのサンドボックスでの読み取り専用のマウント、またはドライブとリージョンが異なる新しいサンドボックス |
409 too_many_drives |
サンドボックスがすでに 8 個のドライブとボリュームを持っている |
503 unavailable |
今はバージョンを作れない:止めている 10 秒以内にサンドボックスの書き込みを読み切れなかった、またはオブジェクトストアがまだドライブの現在の状態を保持していない。少し後に再度要求する |
503 drive_in_store |
今はどのマシンもドライブを保持していない(別のマシンへ移動中)。少し後に再度要求する |
503 node_unavailable |
ドライブを保持するマシンに到達できない |
イベント
drive.snapshot.created と drive.snapshot.deleted は、snapshot_id、drive_id、name、consistency とともに、プロジェクトのイベントと Webhook で届きます。アカウントの未払いで削除されたスナップショットでも drive.snapshot.deleted が送られます。読み取り専用のマウントとその解除では、drive.attached も drive.detached も送られません。
未対応の機能
- キューブのバージョンは、ドライブを読み書き可能でしかマウントしません。
mode: "snapshot"を指定したバージョンは拒否されます(400invalid_field)。読み取り専用のマウントはサンドボックス用です。 - 読み取り専用のマウントを持つサンドボックスは、別のマシンへ移動できません。
- 1 台のマシン上で同じスナップショットをマウントするサンドボックスは、それぞれブロックを保持し、共有はしません。
- サンドボックスのスナップショットから作ったサンドボックスが受け取るフォークは、作成時にはプランのドライブの制限と照合されず、それ以降に数えられます。
- スナップショットを読み取り専用でマウントできるのは、取得したリージョンだけです(ドライブ自体は別のリージョンでもマウントできます:リージョンをまたぐ場合)。削除済みのドライブのスナップショットには、プラットフォームが把握しているリージョンがありません。サンドボックスが作られる場所でマウントされ、別のリージョンのオブジェクトストアにコピーするマシンはそれを拒否します。