永続ディスクのスナップショットを使用して復元可能なコールド ウェブサーバーをデプロイする

Last reviewed 2021-08-04 UTC

このドキュメントでは、マネージド インスタンス グループ永続ディスクのスナップショットを使用して、ウェブサーバーのコールド フェイルオーバー トポロジをデプロイする方法について説明します。このドキュメントは、運用チームと管理チームで作業するアーキテクトと担当者を対象としています。

データを格納する永続ディスクを持つ単一の VM を実行するマネージド インスタンス グループを作成します。永続ディスクの定期的なスナップショットを使用することにより、フェイルオーバーのシナリオでのデータ損失を最小限に抑えます。次の図に示すように、外部アプリケーション ロードバランサは、マネージド インスタンス グループで実行されている VM にユーザーを転送します。

外部アプリケーション ロードバランサによって、ユーザーはマネージド インスタンス グループで実行されている単一の VM に転送されます。リソース ポリシーによって、VM にアタッチされた永続ディスクの通常のスナップショットが作成されます。

インスタンスに障害が発生した場合、マネージド インスタンス グループが同じゾーンに VM の再作成を試みます。ゾーンレベルで障害が発生した場合、Cloud Monitoring などから問題の発生を通知して、別のゾーンまたはリージョンに別のマネージド インスタンス グループを手動で作成できます。どちらのフェイルオーバー シナリオでも、プラットフォームは最新の永続ディスクのスナップショットを使用して交換用ディスクを作成し、インスタンス グループ内の新しい VM にこのディスクをアタッチします。

このドキュメントでは、VM またはロードバランサの外部 IP アドレスを使用して、ウェブサーバーの基本ページを表示します。このアプローチでは、ドメイン名が登録されていない場合に、DNS の変更なしでコールド フェイルオーバーのパターンをテストできます。本番環境では、ロードバランサに割り当てられた外部 IP アドレスに解決される Cloud DNS ゾーンとレコードを作成して構成します。

このパターンでは、一定レベルのデータ保護を維持しながら、複数の VM またはリージョン永続ディスクを実行する費用の差のバランスを取ります。単一の VM と永続ディスクで実行すると、費用は抑えられますが、設定された間隔でのみ永続ディスクのスナップショットが取得されるため、データ損失のリスクがあります。データ損失の可能性を低減するには、代わりにリージョン永続ディスクを使用する復元可能なコールド ウェブサーバーをデプロイすることを検討してください。

次の表は、リージョン永続ディスクの場合と、永続ディスクのスナップショットを使用する復元可能なコールド アプローチの場合のデータ保護オプションの大まかな違いをまとめたものです。詳細については、永続ディスクを使用した高可用性オプションをご覧ください。

リージョン永続ディスク 永続ディスクのスナップショット
データ損失 - リカバリ ポイント目標(RPO) 単一障害(ゾーンの継続的なサービス停止またはネットワークの切断など)の場合は 0。 最後のスナップショット取得(通常、1 時間以上)以降のデータ。

データ損失の可能性は、スナップショットの取得頻度を制御するスナップショット スケジュールによって異なります。
目標復旧時間(RTO) 新しい VM のデプロイ時間とリージョン永続ディスクの再アタッチのかかる秒数。 新しい VM のデプロイ時間、および最新のスナップショットから新しい永続ディスクを作成する時間。

ディスクの作成時間は、スナップショットのサイズによって異なり、数十分から数時間かかることがあります。
費用 リージョン永続ディスクが別のゾーンに継続的に複製されると、ストレージ費用が倍増します。 費用は、消費したスナップショットの容量に対してのみ発生します。
詳細については、ディスクとイメージの料金をご覧ください。

目標

  • マネージド インスタンス グループを作成し、永続ディスクがアタッチされた VM を実行する。
  • 永続ディスクのスナップショットを定期的に取得するように、スナップショットのスケジュールを構成する。
  • インスタンス テンプレートと起動スクリプトを作成する。
  • 外部アプリケーション ロードバランサを作成して構成する。
  • 代わりのマネージド インスタンス グループで、コールド ウェブサーバーのフェイルオーバーをテストする。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Compute Engine API を有効にします。

    API を有効にする

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

    gcloud init
  7. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  8. Google Cloud プロジェクトで課金が有効になっていることを確認します

  9. Compute Engine API を有効にします。

    API を有効にする

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

    gcloud init
  12. Google Cloud CLI をインストールせずに、Google Cloud コンソールで Google Cloud CLI を実行できます。Google Cloud コンソールで gcloud CLI を実行するには、Cloud Shell を使用します。

環境を準備する

このセクションでは、リソース名とロケーションの変数を定義します。これらの変数は、リソースをデプロイするときに Google Cloud CLI コマンドによって使用されます。

このドキュメントを通じて、特に断りのない限り、Cloud Shell またはローカル開発環境ですべてのコマンドを入力します。

  1. PROJECT_ID は実際のプロジェクト ID に置き換えます。必要に応じて、リソースに独自の名前の接尾辞を指定します(app など)。

    リージョン(us-central1 など)と、そのリージョン内の 2 つのゾーン(us-central1-aus-central1-f など)を指定します。これらのゾーンにより、最初の永続ディスクと最初のマネージド インスタンス グループがデプロイされる場所と、必要に応じて手動でフェイルオーバーできる場所が定義されます。

    PROJECT_ID=PROJECT_ID
    NAME_SUFFIX=app
    REGION=us-central1
    ZONE1=us-central1-a
    ZONE2=us-central1-f
    

VPC とサブネットの作成

VM へのネットワーク アクセスを許可するには、Virtual Private Cloud(VPC)とサブネットを作成します。マネージド インスタンス グループは、1 つのリージョン内にある複数のゾーン間で動作するため、作成されるサブネットは 1 つだけです。お客様の環境で使用されている IP アドレスの範囲を管理するためのカスタム サブネット モードの利点については、カスタムモードの VPC ネットワークを使用するをご覧ください。

  1. カスタム サブネット モードで VPC を作成します。

    gcloud compute networks create network-$NAME_SUFFIX \
        --subnet-mode=custom
    

    Cloud Shell プロンプトが表示された場合は、この最初のリクエストを承認して API 呼び出しを行います。

  2. 新しい VPC にサブネットを作成します。ネットワーク範囲に適した独自のアドレス範囲(10.1.0.0/20 など)を定義します。

    gcloud compute networks subnets create subnet-$NAME_SUFFIX-$REGION \
        --network=network-$NAME_SUFFIX \
        --range=10.1.0.0/20 \
        --region=$REGION
    

ファイアウォール ルールの作成

  1. ロードバランサおよびマネージド インスタンス グループ用のウェブ トラフィックとヘルスチェックを許可するファイアウォール ルールを作成します。

    gcloud compute firewall-rules create allow-http-$NAME_SUFFIX \
        --network=network-$NAME_SUFFIX \
        --direction=INGRESS \
        --priority=1000 \
        --action=ALLOW \
        --rules=tcp:80 \
        --source-ranges=0.0.0.0/0 \
        --target-tags=http-server
    
    gcloud compute firewall-rules create allow-health-check-$NAME_SUFFIX \
        --network=network-$NAME_SUFFIX \
        --action=allow \
        --direction=ingress \
        --source-ranges=130.211.0.0/22,35.191.0.0/16 \
        --target-tags=allow-health-check \
        --rules=tcp:80
    

    HTTP ルールでは、http-serverタグが適用されている VM や、0.0.0.0/0 範囲を使用している送信元からのトラフィックを許可します。ヘルスチェック ルールでは、Google Cloud のデフォルトが設定されており、プラットフォームがリソースの健全性を正しくチェックできるようになっています。

  2. ベース VM イメージの初期設定で SSH トラフィックを許可するには、--source-rangeパラメータを使用してファイアウォール ルールを環境に合わせて適用します。組織で使用するソース範囲を決定するには、ネットワーク チームの協力が必要な場合があります。

    IP_ADDRESS_SCOPE を独自の IP アドレス スコープに置き換えます。

    gcloud compute firewall-rules create allow-ssh-$NAME_SUFFIX \
        --network=network-$NAME_SUFFIX \
        --direction=INGRESS \
        --priority=1000 \
        --action=ALLOW \
        --rules=tcp:22 \
        --source-ranges=IP_ADDRESS_SCOPE
    
  3. ファイアウォール ルールを作成したら、3 つのルールが追加されていることを確認します。

    gcloud compute firewall-rules list \
        --project=$PROJECT_ID \
        --filter="NETWORK=network-$NAME_SUFFIX"
    

    次の出力例は、3 つのルールが正しく作成されたことを示しています。

    NAME                    NETWORK      DIRECTION  PRIORITY  ALLOW
    allow-health-check-app  network-app  INGRESS    1000      tcp:80
    allow-http-app          network-app  INGRESS    1000      tcp:80
    allow-ssh-app           network-app  INGRESS    1000      tcp:22
    

ベース VM イメージの作成と構成

追加構成なしでデプロイする同じ VM を作成するには、カスタム VM イメージを使用します。このイメージは、OS と Apache の構成をキャプチャし、次のステップでマネージド インスタンス グループの各 VM を作成するために使用されます。

永続ディスクを使用してアプリケーション データを保存します。このドキュメントでは、アプリケーションの処理に基本の Apache ウェブサイトを使用します。このドキュメントの後半では、この永続ディスクに関連付けられたスナップショット スケジュールを作成して、自動ディスク スナップショットを作成します。

VM で、永続ディスク上に基本的な index.html ファイルを作成し、/var/www/example.comにマウントします。/etc/apache2/sites-available/example.com.conf の Apache 構成ファイルは、マウントされた永続ディスクの場所からウェブ コンテンツを提供します。

次の図は、永続ディスクに保存されている、Apache が提供する基本の HTML ページを示しています。

VM には基本的な HTML ページが永続ディスクに保存されており、マウントされたディスクの場所から読み込む Apache 構成ファイルがあります。

この環境は次の手順で構築します。

  1. 10 GiB の SSD を作成します。ストレージの要件とそれに関連する費用(使用される容量ではなくプロビジョニングされる容量)を把握します。詳細については、永続ディスクの料金をご覧ください。

    gcloud compute disks create disk-$NAME_SUFFIX \
        --zone $ZONE1 \
        --size=10 \
        --type=pd-ssd
    
  2. 永続ディスクがアタッチされたベース VM を作成します。

    gcloud compute instances create vm-base-$NAME_SUFFIX \
        --zone=$ZONE1 \
        --machine-type=n1-standard-1 \
        --subnet=subnet-$NAME_SUFFIX-$REGION \
        --tags=http-server \
        --image=debian-10-buster-v20210721 \
        --image-project=debian-cloud \
        --boot-disk-size=10GB \
        --boot-disk-type=pd-balanced \
        --boot-disk-device-name=vm-base-$NAME_SUFFIX \
        --disk=mode=rw,name=disk-$NAME_SUFFIX,device-name=disk-$NAME_SUFFIX
    

    このドキュメントの冒頭で定義したパラメータを使用して VM に名前を付け、正しいサブネットに接続します。名前はブートディスクとデータディスクのパラメータからも割り当てられます。

  3. シンプルなウェブサイトをインストールして構成するには、まず SSH を使用してベース VM に接続します。

    gcloud compute ssh vm-base-$NAME_SUFFIX --zone=$ZONE1
    
  4. VM への SSH セッションで、任意のエディタで VM を構成するスクリプトを作成します。次の例では、Nano をエディタとして使用しています。

    nano configure-vm.sh
    

    このファイルに次の構成スクリプトを貼り付けます。このドキュメントの冒頭で設定した値(app など)と一致するように NAME_SUFFIX 変数を更新します。

    #!/bin/bash
    
    NAME_SUFFIX=app
    
    # Create directory for the basic website files
    sudo mkdir -p /var/www/example.com
    sudo chmod a+w /var/www/example.com
    sudo chown -R www-data: /var/www/example.com
    
    # Find the disk name, then format and mount it
    DISK_NAME="google-disk-$NAME_SUFFIX"
    DISK_PATH="$(find /dev/disk/by-id -name "${DISK_NAME}" | xargs -I '{}' readlink -f '{}')"
    
    sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard $DISK_PATH
    sudo mount -o discard,defaults $DISK_PATH /var/www/example.com
    
    # Install Apache, additional utilities, and cloud-init
    sudo apt-get update && sudo apt-get -y install apache2 moreutils cloud-init
    
    # Write out a basic HTML file to the mounted persistent disk
    sudo tee -a /var/www/example.com/index.html >/dev/null <<'EOF'
    <!doctype html>
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a test web server with persistent disk snapshots!</p>
    </body>
    </html>
    EOF
    
    # Write out an Apache configuration file
    sudo tee -a /etc/apache2/sites-available/example.com.conf >/dev/null <<'EOF'
    <VirtualHost *:80>
            ServerName www.example.com
    
            ServerAdmin webmaster@localhost
            DocumentRoot /var/www/example.com
    
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    EOF
    
    # Enable the Apache configuration file and reload service
    sudo a2dissite 000-default
    sudo a2ensite example.com.conf
    sudo systemctl reload apache2
    
  5. ファイルを書き出してエディタを終了します。たとえば、Nano では、Ctrl-O を使用してファイルを書き出してから Ctrl-X で終了します。

  6. 構成スクリプトを実行可能にして、実行します。

    chmod +x configure-vm.sh
    ./configure-vm.sh
    
  7. インスタンスに障害が発生し、マネージド インスタンス グループがこのベース VM から交換用ディスクを作成する必要がある場合、アプリケーション データが利用可能である必要があります。新しい VM ごとに次の手順が自動的に実行されます。

    • メタデータ サーバーから情報を取得する。
    • 永続ディスクの最新のスナップショットを取得する。
    • この最新のスナップショットからディスクを作成する。
    • 新しいディスクを VM にアタッチする。
    • ディスクを VM 内にマウントする。

    VM で必要な手順を実行する app-startup.sh という名前の起動スクリプトを作成します。この起動スクリプトは、次のステップでインスタンス テンプレートに適用されます。

    sudo mkdir /opt/cloud-init-scripts
    
    sudo tee -a /opt/cloud-init-scripts/app-startup.sh >/dev/null <<'EOF'
    #!/bin/bash
    
    # Install jq and get an access token for API requests
    apt-get install -y jq
    OAUTH_TOKEN=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
        -H "Metadata-Flavor: Google" --silent | jq -r '.access_token')
    
    # Make a request against the metadata server to determine the project name,
    # instance name, and what zone it's running in
    ZONE_INFO=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone \
        -H "Metadata-Flavor: Google" --silent)
    PROJECT_NAME=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone \
        -H "Metadata-Flavor: Google" --silent | awk -v FS="/" '{print $2}')
    ZONE_NAME=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone \
        -H "Metadata-Flavor: Google" --silent | sed 's:.*/::')
    INSTANCE_NAME=$(curl http://metadata.google.internal/computeMetadata/v1/instance/name \
        -H "Metadata-Flavor: Google" --silent)
    
    # Get the latest snapshot of the app disk
    LATEST_SNAPSHOT=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
        https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/global/snapshots \
        --silent | jq -s '.[].items[] | select(.name | contains("disk-$NAME")) | .name' \
        | sort -r | head -n 1 | tr -d '"')
    
    # Create a persistent disk using the latest persistent disk snapshot
    curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json; charset=utf-8" \
        https://compute.googleapis.com/compute/v1/$ZONE_INFO/disks \
        --data '{"name":"'$LATEST_SNAPSHOT'-restored","sizeGb":"10","type":"zones/'$ZONE_NAME'/diskTypes/pd-ssd","sourceSnapshot":"https://www.googleapis.com/compute/v1/projects/'$PROJECT_NAME'/global/snapshots/'$LATEST_SNAPSHOT'"}'
    
    # Wait for the persistent disk to be created from the disk snapshot
    DISK_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
        https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/disks/$LATEST_SNAPSHOT-restored \
        --silent | jq -r .status)
    
    while [ $DISK_STATUS != "READY" ]
    do
        sleep 2
        DISK_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
            https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/disks/$LATEST_SNAPSHOT-restored \
            --silent | jq -r .status)
    done
    
    # Attach the new persistent disk created from the snapshot to the VM
    curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json; charset=utf-8" \
        https://compute.googleapis.com/compute/v1/$ZONE_INFO/instances/$INSTANCE_NAME/attachDisk \
        --data '{ "source": "/compute/v1/'$ZONE_INFO'/disks/'$LATEST_SNAPSHOT'-restored"}'
    
    # Wait for the persistent disk to be attached before mounting
    ATTACH_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
        https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/instances/$INSTANCE_NAME \
        --silent | jq '.disks[] | select(.source | contains("disk-"))')
    
    while [ -z "$ATTACH_STATUS" ]
    do
        sleep 2
        ATTACH_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" GET \
            https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/instances/$INSTANCE_NAME \
            --silent | jq '.disks[] | select(.source | contains("disk-"))')
    done
    
    # With the disk attached, mount the disk and restart Apache
    echo UUID=`blkid -s UUID -o value /dev/sdb` /var/www/example.com ext4 discard,defaults,nofail 0 2 \
        | tee -a /etc/fstab
    mount -a
    systemctl reload apache2
    
    # Remove jq so it's not left on the VM
    apt-get remove -y jq
    EOF
    
  8. app などのドキュメントの開始時に定義した NAME_SUFFIX 変数を起動スクリプトに適用するには、envsubst コマンドを使用します。

    export NAME=app
    envsubst '$NAME' < "/opt/cloud-init-scripts/app-startup.sh" \
        | sudo sponge "/opt/cloud-init-scripts/app-startup.sh"
    
  9. VM への SSH セッションを終了します。

    exit
    
  10. VM の IP アドレスを取得し、curl を使用して基本的なウェブページを表示します。

    curl $(gcloud compute instances describe vm-base-$NAME_SUFFIX \
        --zone $ZONE1 \
        --format="value(networkInterfaces.accessConfigs.[0].natIP)")
    

    次の出力例に示すように、基本のウェブサイトが返されます。

    <!doctype html>
    
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a test web server with persistent disk snapshots!</p>
    </body>
    </html>
    

    このステップでは、Apache が正しく構成され、アタッチされた永続ディスクからページが読み込まれることを確認します。以降のセクションでは、このベース VM を使用してイメージを作成し、起動スクリプトでインスタンス テンプレートを構成します。

永続ディスクのスナップショット スケジュールの作成

マネージド インスタンス グループ内に作成された VM が、永続ディスクの最新データを常に保持するには、スナップショット スケジュールを作成します。このスケジュールは、定義された時点で永続ディスクのスナップショットを自動的に取得し、スナップショットを保持する期間を制御します。次の図は、このスナップショット プロセスの仕組みを示しています。

スナップショット スケジュールを定義するリソース ポリシーが作成され、定期的なスナップショットを取得するために永続ディスクに接続されます。

スナップショットの取得頻度に関して、アプリケーションのニーズとビジネス目標を検討します。たとえば静的なウェブサイトの場合、スナップショットを取得する必要がある頻度は、ディスクにデータを書き込むアクティブ アプリケーションと比較して低くなります。

お客様のアプリケーションに最適なアプローチを判断する方法と、どの復旧方法を使用するかについては、障害復旧計画ガイドをご覧ください。

  1. このシナリオでは、スナップショット スケジュールを使用して、通常の永続ディスクのスナップショットを作成します。このスナップショット スケジュールはリソース ポリシーで定義します。リソース ポリシーを使用すると、実行するアクションを定義して、そのアクションを環境内のリソースにアタッチできます。

    このリソース ポリシーでは、次の設定を使用して、スナップショットを作成するスケジュールを定義します。

    • 22:00 UTC から 4 時間ごとにスナップショットを取得する
    • スナップショットを 1 日間保持する

    このスケジュールを、環境で必要に応じて構成します(開始時刻やスナップショットの取得頻度など)。

    gcloud compute resource-policies create snapshot-schedule snapshot-schedule-$NAME_SUFFIX \
        --description "Snapshot persistent disk every 4 hours" \
        --max-retention-days 1 \
        --start-time 22:00 \
        --hourly-schedule 4 \
        --region $REGION
    

    詳細については、永続ディスクのスケジュールされたスナップショットを使用する方法をご覧ください。

  2. スナップショット スケジュールを使用するには、リソース ポリシーを永続ディスクに接続します。永続ディスクの名前と、前の手順で作成したリソース ポリシーを指定します。

    gcloud compute disks add-resource-policies disk-$NAME_SUFFIX \
        --resource-policies snapshot-schedule-$NAME_SUFFIX \
        --zone $ZONE1
    
  3. 最初のディスク スナップショットが作成されるまでは、このドキュメントの残りの部分を完了してマネージド インスタンス グループの動作を確認することはできません。この時点でディスク スナップショットを手動で作成し、リソース ポリシーのスナップショット スケジュールで定義どおりに追加のスナップショットが作成されるようにします。

    gcloud compute disks snapshot disk-$NAME_SUFFIX \
        --zone=$ZONE1 \
        --snapshot-names=disk-$NAME_SUFFIX-$(date "+%Y%m%d%H%M%S")
    

サービス アカウントを作成する

次の手順で作成するマネージド インスタンス グループ内の各 VM は、起動スクリプトを実行する必要があります。この起動スクリプトは、スナップショットから永続ディスクを作成して VM にアタッチします。セキュリティのベスト プラクティスとして、これらのディスク オペレーションを実行するために必要な権限のみを持つ新しいサービス アカウントを作成します。その後、このサービス アカウントを VM に割り当てます。

  1. マネージド インスタンス グループの VM で使用するサービス アカウントを作成します。

    gcloud iam service-accounts create instance-sa-$NAME_SUFFIX \
        --description="Service account for HA/DR example" \
        --display-name="HA/DR for VM instances"
    
  2. 次にカスタムロールを作成し、ディスク管理タスクの実行に必要な権限のみを割り当てます。次の権限が必要です。

    • compute.snapshots.list
    • compute.snapshots.useReadOnly
    • compute.disks.get
    • compute.disks.create
    • compute.instances.get
    • compute.instances.attachDisk
    • compute.disks.use
    gcloud iam roles create instance_snapshot_management_$NAME_SUFFIX \
        --project=$PROJECT_ID \
        --title="Snapshot management for VM instances" \
        --description="Custom role to allow an instance to create a persistent disk from a snapshot and attach to VM." \
        --permissions=compute.snapshots.list,compute.snapshots.useReadOnly,compute.disks.get,compute.disks.create,compute.instances.get,compute.instances.attachDisk,compute.disks.use \
        --stage=GA
    
  3. 新しいサービス アカウントに必要なロール バインディングを追加します。

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com" \
        --role="projects/$PROJECT_ID/roles/instance_snapshot_management_$NAME_SUFFIX"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com" \
        --role="roles/iam.serviceAccountUser"
    

VM イメージとインスタンス テンプレートの作成

追加の構成を必要とせずに自動的にデプロイ可能な同一の VM を作成するには、カスタム VM イメージを使用します。このイメージでは、OS と Apache の構成がキャプチャされます。このイメージは、次の手順でマネージド インスタンス グループに作成する各 VM によって使用されます。

  1. イメージを作成する前に、VM を停止する必要があります。

    gcloud compute instances stop vm-base-$NAME_SUFFIX --zone=$ZONE1
    
  2. 次に、前のセクションで構成したベース VM のイメージを作成します。

    gcloud compute images create image-$NAME_SUFFIX \
        --source-disk=vm-base-$NAME_SUFFIX \
        --source-disk-zone=$ZONE1 \
        --storage-location=$REGION
    
  3. マネージド インスタンス グループの VM が初めて起動するときに、cloud-init を使用して以前の起動スクリプトを実行します。更新後に VM を再起動する場合など、VM を起動するたびに、VM に適用される通常の起動スクリプトが実行されます。

    インスタンス テンプレートで使用する cloud-init 構成ファイルを作成します。

    tee -a cloud-init.yaml >/dev/null <<'EOF'
    #cloud-config
    
    runcmd:
     - [ bash, /opt/cloud-init-scripts/app-startup.sh ]
    EOF
    
  4. cloud-init 構成を適用して、スナップショットからディスクを作成しディスクを VM にアタッチおよびマウントする起動スクリプトを実行するインスタンス テンプレートを作成します。

    gcloud compute instance-templates create template-$NAME_SUFFIX \
        --machine-type=n1-standard-1 \
        --subnet=projects/$PROJECT_ID/regions/$REGION/subnetworks/subnet-$NAME_SUFFIX-$REGION \
        --tags=http-server \
        --image=image-$NAME_SUFFIX \
        --scopes cloud-platform \
        --service-account="instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com" \
        --metadata-from-file user-data=cloud-init.yaml
    

マネージド インスタンス グループを作成する

マネージド インスタンス グループが VM を実行します。このマネージド インスタンス グループは定義されたゾーンで実行され、VM の状態をモニタリングします。障害が発生し、VM が動作しなくなった場合、マネージド インスタンス グループは、同じゾーン内に別の VM を作成して最新のスナップショットから永続ディスクを作成しようとします。ゾーンレベルで障害が発生した場合は、コールド フェイルオーバーを手動で実行し、別のゾーンに別のマネージド インスタンス グループを作成する必要があります。同じカスタム イメージとインスタンス テンプレートを使用して、同じ方法で VM が自動的に構成されます。

  1. マネージド インスタンス グループ内の VM をモニタリングするヘルスチェックを作成します。このヘルスチェックは、VM がポート 80 で応答していることを確認します。独自のアプリケーションの場合は、適切なポートをモニタリングして VM の状態を確認します。

    gcloud compute health-checks create http http-basic-check-$NAME_SUFFIX --port 80
    
  2. VM が 1 つだけのマネージド インスタンス グループを作成します。この単一の VM が起動すると、最新のスナップショットから永続ディスクが作成され、この永続ディスクがマウントされ、ウェブ トラフィックの処理が開始されます。

    gcloud compute instance-groups managed create instance-group-$NAME_SUFFIX-$ZONE1 \
        --base-instance-name=instance-vm-$NAME_SUFFIX \
        --template=template-$NAME_SUFFIX \
        --size=1 \
        --zone=$ZONE1 \
        --health-check=http-basic-check-$NAME_SUFFIX
    

ロードバランサの作成と構成

ユーザーがお客様のウェブサイトにアクセスできるようにするには、マネージド インスタンス グループで実行されている VM へのトラフィックを許可する必要があります。また、マネージド インスタンス グループにゾーン障害がある場合、トラフィックを新しい VM に自動的にリダイレクトする必要もあります。

次のセクションでは、80 番ポートの HTTP トラフィック用のバックエンド サービスを備えた外部ロードバランサを作成し、前のステップで作成したヘルスチェックを使用して、外部 IP アドレスをバックエンド サービスにマッピングします。

詳細については、シンプルな外部 HTTP ロードバランサの設定方法をご覧ください。

  1. アプリケーション用のロードバランサを作成して構成します

    # Configure port rules for HTTP port 80
    gcloud compute instance-groups set-named-ports \
        instance-group-$NAME_SUFFIX-$ZONE1 \
        --named-ports http:80 \
        --zone $ZONE1
    
    # Create a backend service and add the managed instance group to it
    gcloud compute backend-services create \
        web-backend-service-$NAME_SUFFIX \
        --protocol=HTTP \
        --port-name=http \
        --health-checks=http-basic-check-$NAME_SUFFIX \
        --global
    
    gcloud compute backend-services add-backend \
        web-backend-service-$NAME_SUFFIX \
        --instance-group=instance-group-$NAME_SUFFIX-$ZONE1 \
        --instance-group-zone=$ZONE1 \
        --global
    
    # Create a URL map for the backend service
    gcloud compute url-maps create web-map-http-$NAME_SUFFIX \
        --default-service web-backend-service-$NAME_SUFFIX
    
    # Configure forwarding for the HTTP traffic
    gcloud compute target-http-proxies create \
        http-lb-proxy-$NAME_SUFFIX \
        --url-map web-map-http-$NAME_SUFFIX
    
    gcloud compute forwarding-rules create \
        http-content-rule-$NAME_SUFFIX \
        --global \
        --target-http-proxy=http-lb-proxy-$NAME_SUFFIX \
        --ports=80
    
  2. ウェブ トラフィックの転送ルールの IP アドレスを取得します。

    IP_ADDRESS=$(gcloud compute forwarding-rules describe http-content-rule-$NAME_SUFFIX \
        --global \
        --format="value(IPAddress)")
    
  3. curl を使用するか、ウェブブラウザを開いて、前のステップで作成したロードバランサの IP アドレスを使用してウェブサイトを表示します。

    curl $IP_ADDRESS
    

    ロードバランサがデプロイを完了し、バックエンドにトラフィックが正しく転送されるまでに数分かかります。ロードバランサがまだデプロイ中の場合は、HTTP 404 または 502 エラーが返されます。必要に応じて、数分待ってからもう一度ウェブサイトにアクセスしてください。

    次の出力例に示すように、基本のウェブサイトが返されます。

    <!doctype html>
    
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a Compute Engine website with warm failover to Cloud Storage!</p>
    </body>
    </html>
    

ゾーン障害と復旧をシミュレーションする

ゾーンレベルで障害をシミュレーションする前に、リソースのデプロイメントを確認します。すべてのリソースは、次の環境をサポートするために作成されました。

外部アプリケーション ロードバランサによって、ユーザーはマネージド インスタンス グループで実行されている単一の VM に転送されます。リソース ポリシーによって、VM にアタッチされた永続ディスクの通常のスナップショットが作成されます。

  • 1 つの VM が、基本的なウェブサイトを格納しているアタッチされた永続ディスクを使用して、マネージド インスタンス グループで実行されます。
  • スナップショットは、リソース ポリシーのスナップショット スケジュールを使用して定期的に永続ディスクから取得されます。
  • 起動スクリプトがインスタンス テンプレートに適用されるため、マネージド インスタンス グループに作成された VM は、最後のディスク スナップショットから永続ディスクを作成してアタッチします。
  • ヘルスチェックでは、マネージド インスタンス グループ内の VM のステータスがモニタリングされます。
  • 外部アプリケーション ロードバランサは、マネージド インスタンス グループで実行されている VM にユーザーを転送します。
  • VM に障害が発生すると、マネージド インスタンス グループは同じゾーンで VM の再作成を試みます。ゾーンレベルで障害が発生した場合は、別の作業ゾーンに代替のマネージド インスタンス グループを手動で作成する必要があります。

本番環境では、Cloud Monitoring または他のモニタリング ソリューションを使用して、問題発生時にアラートが表示されることがあります。このアラートは、別の作業ゾーンで代替マネージド インスタンス グループを手動で作成する前に、障害の範囲を理解するように促します。別の方法としては、モニタリング ソリューションを使用して、マネージド インスタンス グループの障害に自動的に対応する方法があります。

ユーザーまたはモニタリング ソリューションで、フェイルオーバーが最適なアクションと判断されると、代替マネージド インスタンス グループが作成されます。このドキュメントでは、この代替リソースを手動で作成します。

  1. ゾーンレベルでの障害をシミュレートするには、ロードバランサのバックエンドとマネージド インスタンス グループを削除します。

    gcloud compute backend-services remove-backend \
        web-backend-service-$NAME_SUFFIX \
        --instance-group=instance-group-$NAME_SUFFIX-$ZONE1 \
        --instance-group-zone=$ZONE1 \
        --global
    
    gcloud compute instance-groups managed delete instance-group-$NAME_SUFFIX-$ZONE1 \
          --zone=$ZONE1
    

    プロンプトが表示されたら、マネージド インスタンス グループの削除リクエストを確定します。

    本番環境では、モニタリング システムによってコールド フェイルオーバーのアクションを直ちに促すアラートが生成されます。

  2. curl またはウェブブラウザを再度使用して、ロードバランサの IP アドレスにアクセスします。

    curl $IP_ADDRESS --max-time 5
    

    ロードバランサ用の正常なターゲットがないため、curl リクエストは失敗します。

  3. コールド フェイルオーバーをシミュレートするには、別のゾーンにマネージド インスタンス グループを作成します。

    gcloud compute instance-groups managed create instance-group-$NAME_SUFFIX-$ZONE2 \
        --template=template-$NAME_SUFFIX \
        --size=1 \
        --zone=$ZONE2 \
        --health-check=http-basic-check-$NAME_SUFFIX
    

    VM イメージ、インスタンス テンプレート、永続ディスクによって、アプリケーション インスタンスのすべての構成が保持されます。

  4. ロードバランサを更新して、新しいマネージド インスタンス グループと VM を追加します。

    gcloud compute instance-groups set-named-ports \
        instance-group-$NAME_SUFFIX-$ZONE2 \
        --named-ports http:80 \
        --zone $ZONE2
    
    gcloud compute backend-services add-backend \
        web-backend-service-$NAME_SUFFIX \
        --instance-group=instance-group-$NAME_SUFFIX-$ZONE2 \
        --instance-group-zone=$ZONE2 \
        --global
    
  5. curl またはウェブブラウザをもう一度使用して、マネージド インスタンス グループで実行されている VM にトラフィックを転送するロードバランサの IP アドレスにアクセスします。

    curl $IP_ADDRESS
    

    VM がデプロイを完了して最新の永続ディスクのスナップショットからデータを復元するまでに数分かかります。VM がまだデプロイされている場合は HTTP 404 または 502 エラーが返され、まだデータを復元している場合はデフォルトの Apache が表示されます。必要に応じて、数分待ってからもう一度ウェブサイトにアクセスしてください。

    次のレスポンス例は、再作成された VM で正しく動作しているウェブページを示しています。

    <!doctype html>
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a test web server with persistent disk snapshots!</p>
    </body>
    </html>
    
  6. マネージド インスタンス グループのヘルス ステータスを確認します。

    gcloud compute instance-groups managed list-instances instance-group-$NAME_SUFFIX-$ZONE2 \
        --zone $ZONE2
    

    次の出力例では、VM のステータスとして RUNNINGHEALTHY が示されています。

    NAME             ZONE           STATUS   HEALTH_STATE  ACTION
    instance-vm-app  us-central1-f  RUNNING  HEALTHY       NONE
    
  7. アタッチされた永続ディスクがスナップショットから作成されたことを確認するには、ソースを確認します。前の list-instances コマンドで表示されたインスタンス NAME を指定します。

    gcloud compute instances describe NAME \
        --zone=$ZONE2 \
        --format="value(disks.[1].source)"
    

    次の出力例では、永続ディスクの名前が disk-app-us-central1-a-20210630165529-umopkt17-restored であることが示されています。起動スクリプトによって接尾辞 -restored が最新のディスク スナップショットの名前に追加されます。

    https://www.googleapis.com/compute/v1/projects/project/zones/us-central1-f/disks/disk-app-us-central1-a-20210630165529-umopkt17-restored
    

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

このドキュメントで作成した個別のリソースを削除するには、次の手順を行います。

  1. ロードバランサの構成を削除します。

    gcloud compute forwarding-rules delete \
        http-content-rule-$NAME_SUFFIX --global --quiet
    
    gcloud compute target-http-proxies delete \
        http-lb-proxy-$NAME_SUFFIX --quiet
    
    gcloud compute url-maps delete web-map-http-$NAME_SUFFIX --quiet
    
    gcloud compute backend-services delete \
        web-backend-service-$NAME_SUFFIX --global --quiet
    
  2. マネージド インスタンス グループとヘルスチェックを削除します。

    gcloud compute instance-groups managed delete instance-group-$NAME_SUFFIX-$ZONE2 \
        --zone=$ZONE2 --quiet
    
    gcloud compute health-checks delete http-basic-check-$NAME_SUFFIX --quiet
    
  3. インスタンス テンプレート、cloud-init 構成、イメージ、ベース VM、永続ディスク、スナップショット スケジュールを削除します。

    gcloud compute instance-templates delete template-$NAME_SUFFIX --quiet
    
    rm cloud-init.yaml
    
    gcloud compute images delete image-$NAME_SUFFIX --quiet
    
    gcloud compute instances delete vm-base-$NAME_SUFFIX --zone=$ZONE1 --quiet
    
    gcloud compute disks delete disk-$NAME_SUFFIX --zone=$ZONE1 --quiet
    
    gcloud compute resource-policies delete \
        snapshot-schedule-$NAME_SUFFIX --region $REGION --quiet
    
  4. インスタンスによって作成されたスナップショットとディスクを一覧表示してから削除します。

    gcloud compute disks list --filter="name:disk-$NAME_SUFFIX" \
        --uri | xargs gcloud compute disks delete
    
    gcloud compute snapshots list --filter="name:disk-$NAME_SUFFIX" \
        --uri | xargs gcloud compute snapshots delete
    
  5. カスタムロールとサービス アカウントを削除します。

    gcloud iam roles delete instance_snapshot_management_$NAME_SUFFIX \
      --project=$PROJECT_ID --quiet
    
    gcloud iam service-accounts delete \
        instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com --quiet
    
  6. ファイアウォール ルールを削除します。

    gcloud compute firewall-rules delete allow-health-check-$NAME_SUFFIX --quiet
    
    gcloud compute firewall-rules delete allow-ssh-$NAME_SUFFIX --quiet
    
    gcloud compute firewall-rules delete allow-http-$NAME_SUFFIX --quiet
    
  7. サブネットと VPC を削除します。

    gcloud compute networks subnets delete \
        subnet-$NAME_SUFFIX-$REGION --region=$REGION --quiet
    
    gcloud compute networks delete network-$NAME_SUFFIX --quiet
    

次のステップ