VM 間で Persistent Disk ボリュームを共有する


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

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

マルチライター モードの Persistent Disk ボリュームは、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}

始める前に

  • まだ設定していない場合は、認証を設定します。認証とは、Google Cloud サービスと API にアクセスするために ID を確認するプロセスです。ローカル開発環境からコードまたはサンプルを実行するには、次のように Compute Engine に対する認証を行います。

    このページのサンプルをどのように使うかに応じて、タブを選択してください。

    コンソール

    Google Cloud コンソールを使用して Google Cloud サービスと API にアクセスする場合、認証を設定する必要はありません。

    gcloud

    1. Google Cloud CLI をインストールし、次のコマンドを実行して初期化します。

      gcloud init
    2. デフォルトのリージョンとゾーンを設定します

    Java

    このページの Java サンプルをローカル開発環境から使用するには、gcloud CLI をインストールして初期化し、自身のユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定してください。

    1. Google Cloud CLI をインストールします。
    2. gcloud CLI を初期化するには:

      gcloud init
    3. Google アカウントのローカル認証情報を作成します。

      gcloud auth application-default login

    詳細については、 ローカル開発環境の認証の設定 をご覧ください。

    Python

    このページの Python サンプルをローカル開発環境から使用するには、gcloud CLI をインストールして初期化し、自身のユーザー認証情報を使用してアプリケーションのデフォルト認証情報を設定してください。

    1. Google Cloud CLI をインストールします。
    2. gcloud CLI を初期化するには:

      gcloud init
    3. Google アカウントのローカル認証情報を作成します。

      gcloud auth application-default login

    詳細については、 ローカル開発環境の認証の設定 をご覧ください。

    REST

    このページの REST API サンプルをローカル開発環境で使用するには、gcloud CLI に指定した認証情報を使用します。

      Google Cloud CLI をインストールし、次のコマンドを実行して初期化します。

      gcloud init

制限事項

  • SSD タイプの Persistent Disk ボリュームでのみ使用できます。
  • Persistent Disk ボリュームは任意のゾーンのマルチ書き込みモードで作成できますが、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
  • アタッチされた最大 VM 数: 2
  • マルチライター モードの Persistent Disk ボリュームは、Persistent Disk の指標をサポートしていません。
  • マルチライター モードのディスクを読み取り専用モードに変更することはできません。
  • マルチライター モードではディスク イメージやスナップショットを使用して Persistent Disk ボリュームを作成することはできません。
  • マルチライター モードの Persistent Disk ボリュームからスナップショットまたはイメージを作成することはできません。
  • IOPS の上限が低くなります。詳細については、ディスクのパフォーマンスをご覧ください。
  • マルチライター Persistent Disk ボリュームのサイズを変更することはできません。
  • Google Cloud CLI を使用して VM を作成する場合、--create-disk フラグを使用してマルチライター Persistent Disk ボリュームを作成することはできません。

ベスト プラクティス

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

パフォーマンス

マルチライター モードで作成された Persistent Disk ボリュームには、特定の 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 インスタンス間でゾーン Persistent Disk ボリュームを共有する

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

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

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

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

コンソール

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

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

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

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

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

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

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

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

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

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

gcloud

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

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

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

  • INSTANCE_NAME: ゾーン Persistent Disk ボリュームをアタッチする VM の名前
  • DISK_NAME: アタッチするディスクの名前

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

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

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: ゾーン Persistent Disk ボリュームをアタッチする VM の名前
  • PROJECT_ID: プロジェクト ID
  • ZONE: ディスクが配置されるゾーン
  • DISK_NAME: アタッチするディスクの名前

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

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

SSD Persistent Disk ボリュームを VM 間で共有する(マルチライター モード)

同じゾーン内の N2 VM 間で、マルチライター モードでの SSD Persistent Disk ボリュームの共有が可能です。このモードの詳細については、Persistent Disk のマルチライター モードをご覧ください。マルチライター Persistent Disk ボリュームは、次の手順で作成してアタッチできます。

gcloud

gcloud CLI を使用して、ゾーン Persistent Disk ボリュームを作成してアタッチします。

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

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

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

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

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

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

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

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

REST

Compute Engine API を使用して、マルチライター モードで SSD Persistent Disk ボリュームを作成し、N2 VM にアタッチします。

  1. API で、disks.insert メソッドを使用して POST リクエストを作成し、ゾーン Persistent Disk ボリュームを作成します。namesizeGbtype プロパティを含めます。新しいディスクを空のフォーマットされていない非ブートディスクとして作成する場合、このディスクにソースイメージやソース スナップショットを指定しないでください。マルチライター モードで VM 間のディスク共有が可能であることを示すには、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: VM と新しいディスクが配置されるゾーン
    • DISK_NAME: 新しいディスクの名前
    • DISK_SIZE: 新しいディスクのサイズ(GB 単位)。SSD Persistent Disk ボリュームの場合は 1 GB から 65,536 GB、マルチライター モードの標準 Persistent Disk ボリュームの場合は 200 GB から 65,536 GB のサイズを指定できます。
  2. compute.instances.attachDisk メソッドに対する POST リクエストを作成し、先ほど作成したゾーン Persistent Disk ボリュームへの 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: VM と新しいディスクが配置されるゾーン
    • INSTANCE_NAME: 新しい Persistent Disk ボリュームを追加する VM の名前。
    • DISK_NAME: 新しいディスクの名前
  3. disks.insert コマンドを繰り返します。ただし、2 番目の VM を指定します。

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

次のステップ