创建分布式卷
Goal
Before you start
- 您的租户中至少需要两个就绪节点——只有一个副本的复制卷没有故障转移的目标。请在节点屏幕上检查节点数量和状态。
- 创建卷所需的
volumes:manage权限。operator 角色拥有此权限,admin 角色通过其通配符也拥有;其他角色均无此权限,没有此权限时,仪表板会隐藏创建和故障转移控件。请参阅角色参考。 - 将卷附加到现有部署所需的
deployments:update权限——developer 和 operator 角色都拥有此权限。请注意,对于下面的仪表板路由,仅有权限还不够:部署的编辑屏幕本身仅对 operator 和 admin 可见,直接导航到该屏幕的开发者会被送回。开发者应通过 YAML 清单或 API 附加卷,这两者都接受相同的deployments:update。 - 您打算附加卷的部署,以及您希望将其挂载到的容器路径。
Steps
创建卷。
- 在侧边栏中打开分布式卷——它位于卷正下方;如果您不确定需要哪一个,请参阅概念页面。
- 选择创建卷。
- 为卷命名。
- 将存储类保留为复制 (异步 rsync)——这是默认值,也是提供副本数和自动故障转移的存储类;其他三个类(临时、共享、对象)不接受副本数。
- 将副本数从默认的 1 提高到至少 2,这样当主节点消失时,有一个健康的副本可以故障转移。
- 表单还显示了故障转移策略、同步间隔(秒)和访问模式。默认值——自动故障转移(仍然需要验证的同步副本)、每 300 秒同步一次,以及 ReadWriteOnce,表示一个节点以读写方式挂载——对于第一个卷是合适的;除非您已知需要其他设置,否则请保留它们。
- 选择创建分布式卷。
- 从列表中打开新卷,并从卷名称下方复制其 ID。它看起来像
vol-652e949d,这是部署引用卷的方式。请等待卷的阶段变为 Ready 再继续——部署无法挂载仍在物化的卷。
将其附加到部署。
部署表单的 卷 部分仅涵盖绑定挂载、命名卷和 tmpfs;分布式挂载需在同一屏幕的 YAML 视图中编写,该视图编辑的是整个描述,而非表单暴露的字段。
-
打开部署,选择 编辑,并将表单顶部的切换开关从 表单 切换到 YAML。该框将填入部署的当前状态。
-
将挂载添加到
volumes列表 —type: distributed,即卷在distributedVolumeId中的 ID,以及容器路径在target中。不要写source:分布式挂载通过其 ID 承载其标识,而旁边的source会被拒绝。此框存储的是 API 保存的部署,而非清单文档,且两者对卷的拼写不同:此处挂载需要
type: distributed,标志为readonly,全部小写。YAML 清单选项卡显示另一种拼写。将清单粘贴到此框中不起作用——它会因缺少顶层image而被拒绝。 -
选择 从 YAML 保存。仅发送您更改的字段。挂载在此时检查,而非启动时,因此无法解析的 ID、未就绪的卷或同一卷上的第二个读写声明会作为拒绝返回,并指出相关字段——参见下方的 失败情况。

Steps
-
首先创建卷——部署描述无法凭空创建它。 使用仪表板或
POST /api/v1/dvm/volumes,并记下它返回的类型化 ID。 -
将挂载添加到
spec.volumes。此表面上没有type键:distributedVolumeId的存在使挂载成为分布式挂载,且所有普通清单卷都是绑定挂载。另请注意,此处的只读标志拼写为readOnly,首字母大写。spec.image在每个部署清单中都是必需的,无论您是否更改它。apiVersion: odysseus/v1kind: Deploymentmetadata:name: my-appspec:image: nginx:1.27-alpinevolumes:- distributedVolumeId: vol-652e949dtarget: /var/lib/my-appreadOnly: false -
省略
source。它是绑定挂载或命名卷使用的字段,与distributedVolumeId一起提供会被拒绝,而不是忽略。 -
如果部署还指定了一个明确的节点,即此界面上的
spec.placement.node,它必须命名卷的当前主节点以进行读写挂载。省略它是更好的选择:放置将遵循卷。 -
通过将文档发送到
PUT /api/v1/deployments/{name}并使用Content-Type: application/yaml来应用文档——与 JSON 更新相同的路由和相同的deployments:update权限,通过一个标头选择格式。文档是严格解码的,因此此界面没有的键是一个拒绝,会命名该字段并提供接受的形式,而不是静默忽略的行。字段定义在 部署参考中。
Steps
POST /api/v1/dvm/volumes以创建卷,请求体中包含存储类和副本数。响应会返回类型化 ID。GET /api/v1/dvm/volumes/{id}直到卷的阶段变为Ready。PUT /api/v1/deployments/{name},使用包含分布式挂载的volumes列表。 请记住,发送的列表会完全替换存储的列表,而不是合并到其中,因此 请发送部署最终应包含的所有挂载,而不仅仅是新的那个。GET /api/v1/dvm/volumes/{id}/replicas以读取每个副本的角色、状态和延迟。
Verify
卷正在复制。 打开卷的详情屏幕。副本 表中的每一行都显示状态为 同步中,其中一行角色为 主节点,且主节点命名了您预期持有副本的节点之一。副本卡片显示 n/n 同步中。每行还带有最后同步和同步延迟:在默认的 300 秒间隔下,几分钟的延迟是卷正常工作的表现,而持续增长的延迟则不是。
底层网格已启动。 复制通过节点之间的 WireGuard 网格进行。 从分布式卷屏幕选择网格状态,并确认 WireGuard 对等节点 表列出了持有副本的每个节点,具有最近的最后握手以及非零的数据已发送或 数据已接收。没有握手的对等节点是一个不会复制的卷,无论卷自身的页面看起来多么健康。该屏幕在 分布式卷屏幕参考中描述。
部署已拥有它。 部署的容器正在运行,并且在主节点上的挂载路径写入文件会在下一次同步时显示在副本的本地大小中。
When it fails
副本从未达到同步状态。 分配到的节点没有空间,或无法访问——请在节点屏幕上检查该节点的状态,然后重新创建卷。如果卷看起来健康但没有副本推进,请首先检查网格状态:没有最近握手的对等节点是更常见的原因。
卷创建时没有真正的冗余。 创建表单的副本数默认为 1,这是一个没有故障转移目标的复制卷。在选择创建分布式卷之前,请将其至少提高到 2。
创建卷选项从未出现。 您的角色没有 volumes:manage 权限——请参阅角色参考,并联系您的平台运营商以更改角色。
保存部署时挂载被拒绝。 每次拒绝都会指明字段、接收到的值和期望的值;拒绝参考完整列出了它们。您最可能遇到的情况是:
- ID 无法解析为此租户拥有的卷——请在分布式卷列表中核对,并注意属于另一个租户的卷与不存在的卷显示完全相同;
- 卷未处于 Ready 阶段——请等待它就绪,而不是挂载可能尚未在目标节点上存在的存储;
- 存储类为 shared 或 object——目前只能调度临时卷和复制卷,允许其他类型会静默挂载节点本地存储,而不是存储类所承诺的;
- 另一个部署已经以读写方式挂载它——每个卷保证只有一个写入者,因此请以只读方式挂载或先分离另一个部署;
- 部署固定了一个非卷主副本的
nodeId——在主副本之外进行读写挂载会写入一个副本,而下一次同步会覆盖它,因此请删除固定并让放置跟随卷。
持有副本的节点消失。 接下来发生什么由卷的故障转移策略决定——这是您在创建表单的故障转移策略中选择的设置,之后在卷的规格面板中显示为故障转移策略。有两种结果。
它自动故障转移。 使用自动策略时,一个处于同步状态并且经证明与失败主副本的最后活动相比是最新的副本,无需等待任何人即可被提升。您会看到一个命名旧主副本和新主副本的事件,卷的页面会显示新的主副本。无需操作;之后请检查卷是否已恢复到完整的副本数。
它等待您操作。 使用手动策略时,或者当没有副本足够新可以安全提升时,提升会停止并请求确认。分布式卷屏幕会显示一个等待批准的卷故障转移横幅,每个卷一行,每行都带有审查并批准 →;卷自己的页面会显示一个等待批准的故障转移横幅,命名失败的节点、提议的副本、该副本的滞后以及自动路径拒绝它的原因。选择批准故障转移到该节点,确认会重申后果——批准即提升该副本,即使知道它落后,因此它未赶上同步的任何内容就是您将丢失的内容。批准需要 volumes:manage。
没有等待项,也没有故障转移。 卷未被复制(临时卷没有第二个副本可提升),或者根本不存在副本。请检查存储类和卷页面上的副本数。