VM 間で永続ディスクを共有する


マルチライター モードで SSD 永続ディスクを同時に最大 2 個の N2 仮想マシン(VM)インスタンスにアタッチできるため、両方の VM でディスクの読み取りと書き込みが可能になります。新しい永続ディスクでマルチライター モードを有効にするには、新しい永続ディスクを作成し、gcloud CLI に --multi-writer フラグを指定するか、Compute Engine API に multiWriter プロパティを指定します。

マルチライター モードの永続ディスクは、共有ブロック ストレージ機能を備えており、分散ストレージ システムなどの高可用性サービスを構築するためのインフラストラクチャ基盤としての役割を果たします。マルチライター モードで永続ディスクを使用する場合は、永続ディスクへのアクセスを複数の VM 間で調整できるスケールアウト ストレージ ソフトウェア システムを使用します。これらのストレージ システムには、Lustre と IBM Spectrum Scale などがあります。EXT4、XFS、NTFS などのほとんどの単一の VM ファイル システムは共有ブロック ストレージ用には設計されていません。詳しくは、このドキュメントのベスト プラクティスをご覧ください。フルマネージドのファイル ストレージが必要な場合は、Compute Engine VM に Filestore ファイル共有をマウントできます。

マルチライター モードの永続ディスクは、SCSI-3 永続予約(SCSI PR)コマンドのサブセットをサポートしています。高可用性アプリケーションは、I/O フェンスとフェイルオーバー構成でこれらのコマンドを使用できます。

次の SCSI PR コマンドがサポートされています。

  • IN {REPORT CAPABILITIES、READ FULL STATUS、READ RESERVATION、READ KEYS}
  • OUT {REGISTER、REGISTER AND IGNORE EXISTING KEY、RESERVE、PREEMPT、CLEAR、RELEASE}

準備

制限事項

  • SSD タイプの永続ディスクでのみ使用できます。
  • 永続ディスクは任意のゾーンのマルチ書き込みモードで作成できますが、VM にアタッチできるのは次のロケーションに限られます。
    • australia-southeast1
    • europe-west1
    • us-central1us-central1-a ゾーン、us-central1-c ゾーンのみ)
    • us-east1us-east1-d ゾーンのみ)
    • us-west1us-west1-b ゾーン、us-west1-c ゾーンのみ)
  • アタッチされた VM には N2 マシンタイプが必要です。
  • 最小サイズ: 10 GB
  • アタッチされた最大インスタンス数: 2
  • マルチライター モードの永続ディスクは、永続ディスクの指標をサポートしていません。
  • マルチライター モードのディスクを読み取り専用モードに変更することはできません。
  • マルチライター モードではディスク イメージやスナップショットを使用して永続ディスクを作成することはできません。
  • マルチライター モードの永続ディスクからスナップショットまたはイメージを作成することはできません。
  • IOPS の上限が低くなります。詳細については、ディスクのパフォーマンスをご覧ください。
  • マルチライター永続ディスクのサイズを変更することはできません。
  • Google Cloud CLI を使用して VM を作成する場合、--create-disk フラグを使用してマルチライター永続ディスクを作成することはできません。

おすすめの方法

  • SCSI PR コマンドを使用した I/O フェンスを使用すると、永続ディスクデータはクラッシュ整合状態になります。一部のファイル システムにはクラッシュ整合性がないため、SCSI PR コマンドを使用すると破損する場合があります。
  • EXT4、XFS、NTFS などの多くのファイル システムは、共有ブロック ストレージ用には設計されておらず、複数の VM インスタンスからのオペレーションを同期、実行するメカニズムはありません。
  • マルチライター モードで永続ディスクを使用する前に、ファイル システムについて理解し、共有ブロック ストレージや、複数の VM からの同時アクセスでファイル システムを安全に使用する方法を確認してください。

パフォーマンス

マルチライター モードで作成された永続ディスクには、特定の IOPS とスループットの上限があります。

ゾーン SSD 永続ディスク マルチライター モード
最大持続 IOPS
読み取り IOPS/GB 30
書き込み IOPS/GB 30
読み取り IOPS/インスタンス 15,000~100,000*
書き込み IOPS/インスタンス 15,000~100,000*
最大持続スループット(MB/秒)
読み取りスループット/GB 0.48
書き込みスループット/GB 0.48
読み取りスループット/インスタンス 240~1,200*
書き込みスループット/インスタンス 240~1,200*
* 永続ディスクの IOPS とスループット パフォーマンスは、ディスクサイズ、インスタンスの vCPU 数、I/O ブロックサイズなどの要因によって決まります。
マルチライター ディスクを複数の仮想マシン インスタンスにアタッチしても、全体的なパフォーマンスや費用に影響はありません。各マシンはディスクごとのパフォーマンス上限を分け合います。

複数の VM 間で永続ディスクを共有する方法については、VM 間での永続ディスクの共有をご覧ください。

VM インスタンス間でゾーン永続ディスクを共有する

このセクションでは、複数の VM 間でゾーン Persistent Disk ボリュームを共有するさまざまな方法について説明します。

ディスクを複数の VM 間で共有する(読み取り専用モード)

非ブート永続ディスクを複数の VM に読み取り専用モードでアタッチし、複数の VM 間で静的データを共有できます。1 つの永続ディスクの静的データを複数の VM で共有することによって、個別インスタンス固有のディスクにデータをレプリケートする場合よりもコストを低減できます。

複数の VM 間で動的保存容量を共有する必要がある場合は、次のいずれかのオプションを使用できます。

Console

  1. Google Cloud コンソールの [VM インスタンス] ページに移動します。

    [VM インスタンス] に移動

  2. プロジェクトのインスタンスのリストで、ディスクをアタッチするインスタンスの名前をクリックします。[VM インスタンスの詳細] ページが開きます。

  3. インスタンスの詳細ページで、[編集] をクリックします。

  4. [追加ディスク] セクションで、次のいずれかをクリックします。

    1. ディスクを追加でディスクを読み取り専用モードでインスタンスに追加します。
    2. [既存のディスクを接続] で既存のディスクを選択し、読み取り専用モードでインスタンスに接続します。
  5. ディスクのその他のオプションを指定します。

  6. [完了] をクリックして変更を適用します。

  7. [保存] をクリックして、インスタンスに変更を適用します。

  8. インスタンスに接続して、ディスクをマウントします。

  9. このプロセスを繰り返して、他のインスタンスに読み取り専用モードでディスクを追加します。

gcloud

gcloud CLI で compute instances attach-disk コマンドを使用し、ro オプションで --mode フラグを指定します。

gcloud compute instances attach-disk INSTANCE_NAME \
  --disk DISK_NAME \
  --mode ro

次のように置き換えます。

  • INSTANCE_NAME: ゾーン永続ディスクをアタッチするインスタンスの名前
  • DISK_NAME: 接続するディスクの名前

ディスクを接続した後、インスタンスに接続してディスクをマウントします。

読み取り専用モードでディスクを追加するインスタンスごとに、このコマンドを繰り返します。

Java

Java

このサンプルを試す前に、Compute Engine クイックスタート: クライアント ライブラリの使用に記載されている Java の設定手順を行います。 詳細については、Compute Engine Java API のリファレンス ドキュメントをご覧ください。

Compute Engine に対して認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。


import com.google.cloud.compute.v1.AttachDiskInstanceRequest;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AttachDisk {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "your-project-id";

    // Name of the zone in which the instance you want to use resides.
    String zone = "zone-name";

    // Name of the compute instance you want to attach a disk to.
    String instanceName = "instance-name";

    // Full or partial URL of a persistent disk that you want to attach. This can be either
    // be a regional or zonal disk.
    // Valid formats:
    //     * https://www.googleapis.com/compute/v1/projects/{project}/zones/{zone}/disks/{disk_name}
    //     * /projects/{project}/zones/{zone}/disks/{disk_name}
    //     * /projects/{project}/regions/{region}/disks/{disk_name}
    String diskLink = String.format("/projects/%s/zones/%s/disks/%s",
        "project", "zone", "disk_name");

    // Specifies in what mode the disk will be attached to the instance. Available options are
    // `READ_ONLY` and `READ_WRITE`. Disk in `READ_ONLY` mode can be attached to
    // multiple instances at once.
    String mode = "READ_ONLY";

    attachDisk(projectId, zone, instanceName, diskLink, mode);
  }

  // Attaches a non-boot persistent disk to a specified compute instance.
  // The disk might be zonal or regional.
  // You need following permissions to execute this action:
  // https://cloud.google.com/compute/docs/disks/regional-persistent-disk#expandable-1
  public static void attachDisk(String projectId, String zone, String instanceName, String diskLink,
      String mode)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the `instancesClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (InstancesClient instancesClient = InstancesClient.create()) {

      AttachDiskInstanceRequest attachDiskInstanceRequest = AttachDiskInstanceRequest.newBuilder()
          .setProject(projectId)
          .setZone(zone)
          .setInstance(instanceName)
          .setAttachedDiskResource(AttachedDisk.newBuilder()
              .setSource(diskLink)
              .setMode(mode)
              .build())
          .build();

      Operation response = instancesClient.attachDiskAsync(attachDiskInstanceRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Attach disk failed! " + response);
        return;
      }
      System.out.println("Attach disk - operation status: " + response.getStatus());
    }
  }
}

Python

Python

このサンプルを試す前に、Compute Engine クイックスタート: クライアント ライブラリの使用に記載されている Python の設定手順を行います。 詳細については、Compute Engine Python API のリファレンス ドキュメントをご覧ください。

Compute Engine に対して認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証の設定をご覧ください。

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1

def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result

def attach_disk(
    project_id: str, zone: str, instance_name: str, disk_link: str, mode: str
) -> None:
    """
    Attaches a non-boot persistent disk to a specified compute instance. The disk might be zonal or regional.

    You need following permissions to execute this action:
    https://cloud.google.com/compute/docs/disks/regional-persistent-disk#expandable-1

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone:name of the zone in which the instance you want to use resides.
        instance_name: name of the compute instance you want to attach a disk to.
        disk_link: full or partial URL to a persistent disk that you want to attach. This can be either
            regional or zonal disk.
            Expected formats:
                * https://www.googleapis.com/compute/v1/projects/[project]/zones/[zone]/disks/[disk_name]
                * /projects/[project]/zones/[zone]/disks/[disk_name]
                * /projects/[project]/regions/[region]/disks/[disk_name]
        mode: Specifies in what mode the disk will be attached to the instance. Available options are `READ_ONLY`
            and `READ_WRITE`. Disk in `READ_ONLY` mode can be attached to multiple instances at once.
    """
    instances_client = compute_v1.InstancesClient()

    request = compute_v1.AttachDiskInstanceRequest()
    request.project = project_id
    request.zone = zone
    request.instance = instance_name
    request.attached_disk_resource = compute_v1.AttachedDisk()
    request.attached_disk_resource.source = disk_link
    request.attached_disk_resource.mode = mode

    operation = instances_client.attach_disk(request)

    wait_for_extended_operation(operation, "disk attachement")

REST

API で、compute.instances.attachDisk メソッドに対して POST リクエストを作成します。リクエストの本文で、mode パラメータに READ_ONLY を指定します。

POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/attachDisk

{
 "source": "zones/ZONE/disks/DISK_NAME",
 "mode": "READ_ONLY"
}

次のように置き換えます。

  • INSTANCE_NAME: ゾーン永続ディスクをアタッチするインスタンスの名前
  • PROJECT_ID: プロジェクト ID
  • ZONE: ディスクが配置されるゾーン
  • DISK_NAME: アタッチするディスクの名前

ディスクを接続した後、インスタンスに接続してディスクをマウントします。

ディスクを読み取り専用モードで追加するインスタンスごとにこのリクエストを繰り返します。

SSD 永続ディスクを VM インスタンス間で共有する(マルチライター モード)

同じゾーン内の N2 インスタンス間で、マルチライター モードでの SSD 永続ディスクの共有が可能です。このモードの詳細については、永続ディスクのマルチライター モードをご覧ください。マルチライター永続ディスクは、次の手順で作成してアタッチできます。

gcloud

gcloud CLI を使用して、ゾーン永続ディスクを作成してアタッチします。

  1. gcloud beta compute disks create コマンドを使用してゾーン永続ディスクを作成します。--multi-writer フラグを使用して、マルチライター モードでインスタンス間のディスク共有が可能であることを指定します。

    gcloud beta compute disks create DISK_NAME \
       --size DISK_SIZE \
       --type pd-ssd \
       --multi-writer
    

    次のように置き換えます。

    • DISK_NAME: 新しいディスクの名前
    • DISK_SIZE: 新しいディスクのサイズ(GB 単位)。SSD 永続ディスクの場合は 1 GB から 65,536 GB、マルチライター モードの標準永続ディスクの場合は 200 GB から 65,536 GB のサイズを指定できます。
  2. ディスクを作成したら、N2 マシンタイプの実行中または停止しているインスタンスにアタッチします。gcloud compute instances attach-disk コマンドを使用します。

    gcloud compute instances attach-disk INSTANCE_NAME \
       --disk DISK_NAME
    

    次のように置き換えます。

    • INSTANCE_NAME: 新しいゾーン永続ディスクを追加する N2 インスタンスの名前
    • DISK_NAME: インスタンスにアタッチする新しいディスクの名前。
  3. gcloud compute instances attach-disk コマンドを繰り返します。ただし、INSTANCE_NAME は 2 番目のインスタンスの名前に置き換えてください。

新しいディスクを作成してインスタンスにアタッチしたら、共有ディスク ファイル システムを使用し、ディスクをフォーマットしてマウントします。ほとんどのファイル システムでは共有ストレージを使用できません。マルチライター永続ディスクで使用する前に、ファイル システムでこれらの機能がサポートされていることを確認してください。ディスクを単一の VM にマウントする場合に通常使用するのと同じプロセスを使用して、複数の VM にディスクをマウントすることはできません。

REST

Compute Engine API を使用して、マルチライター モードで SSD 永続ディスクを作成し、N2 インスタンスにアタッチします。

  1. API で、disks.insert メソッドを使用して POST リクエストを作成し、ゾーン永続ディスクを作成します。namesizeGbtype プロパティを含めます。新しいディスクを空のフォーマットされていない非ブートディスクとして作成する場合、このディスクにソースイメージやソース スナップショットを指定しないでください。マルチライター モードでインスタンス間のディスク共有が可能であることを示すには、multiWriter プロパティの値を True に設定します。

    POST https://compute.googleapis.com/compute/beta/projects/PROJECT_ID/zones/ZONE/disks
    
    {
    "name": "DISK_NAME",
    "sizeGb": "DISK_SIZE",
    "type": "zones/ZONE/diskTypes/pd-ssd",
    "multiWriter": "True"
    }
    

    次のように置き換えます。

    • PROJECT_ID: プロジェクト ID
    • ZONE: インスタンスと新しいディスクが配置されるゾーン
    • DISK_NAME: 新しいディスクの名前
    • DISK_SIZE: 新しいディスクのサイズ(GB 単位)。SSD 永続ディスクの場合は 1 GB から 65,536 GB、マルチライター モードの標準永続ディスクの場合は 200 GB から 65,536 GB のサイズを指定できます。
  2. compute.instances.attachDisk メソッドに対する POST リクエストを作成し、先ほど作成したゾーン永続ディスクへの URL をリクエスト本文に含めます。

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/attachDisk
    
    {
    "source": "/compute/v1/projects/PROJECT_ID/zones/ZONE/disks/DISK_NAME"
    }
    

    次のように置き換えます。

    • PROJECT_ID: プロジェクト ID
    • ZONE: インスタンスと新しいディスクが配置されるゾーン
    • INSTANCE_NAME: 新しい永続ディスクを追加するインスタンスの名前
    • DISK_NAME: 新しいディスクの名前
  3. disks.insert コマンドを繰り返します。ただし、2 番目のインスタンスを指定します。

新しいディスクを作成してインスタンスにアタッチしたら、共有ディスク ファイル システムを使用し、ディスクをフォーマットしてマウントします。ほとんどのファイル システムでは共有ストレージを使用できません。マルチライター永続ディスクで使用する前に、ファイル システムでこれらの機能がサポートされていることを確認してください。

次のステップ