インスタンス メタデータの格納と取得

すべてのインスタンスはメタデータをメタデータ サーバーに格納します。このメタデータ サーバーに対してプログラムでクエリを実行することにより、インスタンスに関する情報(インスタンスのホスト名、インスタンス ID、起動スクリプトとシャットダウン スクリプト、カスタム メタデータ、サービス アカウントの情報など)を取得できます。クエリは、インスタンス内から実行することも、Compute Engine API から実行することもできます。インスタンスからメタデータ サーバーの API にアクセスするのに追加の承認は必要ありません。自動的にアクセスできるようになります。

メタデータ サーバーは、起動スクリプトやシャットダウン スクリプトと組み合わせて使用すると特に便利です。これはメタデータ サーバーを使用すると、追加の承認を行わずに、インスタンスに関する固有の情報をプログラムを使用して取得できるためです。たとえば、起動スクリプトでインスタンスの外部 IP のメタデータの Key-Value ペアを取得して、その IP を使用してデータベースを設定できます。デフォルトのメタデータキーはすべてのインスタンスで同じなので、スクリプトはそのまま再利用できます。インスタンスごとに更新する必要はありません。これにより、アプリケーションのコードの安定性が向上します。

メタデータは key:value の形式で格納されます。すべてのインスタンスがアクセスできるメタデータ エントリのデフォルト セットが用意されています。そのほかにカスタム メタデータを設定することもできます。

メタデータ サーバーにアクセスするには、http://metadata.google.internal/computeMetadata/v1/ という URL に対してクエリを実行します。詳細については、メタデータのクエリをご覧ください。

最新バージョン: v1

Compute Engine では、複数のバージョンのメタデータが一度に提供されることがありますが、常に最新のバージョンを使用することをおすすめします。Google Compute Engine では、メタデータ サーバーへの新しいエントリの追加や、レスポンスへの新しいフィールドの追加が常に行われています。定期的に変更の有無を確認してください。

始める前に

このタスクに必要な権限

このタスクを実行するには、次の権限が必要です。

  • インスタンスのメタデータを設定する場合、インスタンスに対する compute.instances.setMetadata
  • プロジェクト全体のメタデータを設定する場合、そのプロジェクトに対する compute.projects.setCommonInstanceMetadata
  • メタデータを取得するだけの場合、プロジェクトに対する compute.projects.get
  • メタデータを取得するだけの場合、インスタンスに対する compute.instances.get

プロジェクトとインスタンスのメタデータ

メタデータは、プロジェクトとインスタンスの両方のレベルで割り当てることができます。プロジェクト レベルのメタデータはそのプロジェクトのすべての仮想マシン インスタンスに反映されますが、インスタンス レベルのメタデータが影響するのはそのインスタンスだけです。

デフォルトのメタデータキー

Google Compute Engine では、インスタンスやプロジェクトの情報を提供するメタデータ エントリのデフォルト セットが定義されています。デフォルト メタデータは常にサーバーによって定義され、設定されます。手動で編集することはできません。

プロジェクトで使用できるデフォルト メタデータを以下に示します。一部のメタデータ エントリは、他のメタデータキーを含むディレクトリです。区別のために、メタデータ名の末尾にスラッシュが付いています。たとえば、attributes/ は他のキーを含むディレクトリで、numeric-project-id は値にマッピングされるメタデータキーです。

パスの基準: http://metadata.google.internal/computeMetadata/v1/project/
メタデータ エントリ 説明
attributes/ このプロジェクトに対して設定されたカスタム メタデータ値のディレクトリ。
attributes/disable-legacy-endpoints プロジェクト内のすべてのインスタンスの、以前のメタデータ サーバー エンドポイントを無効にします。プロジェクトで以前のエンドポイントを使用しない限り、常に disable-legacy-endpoints=TRUE を設定します。v1 エンドポイントを使用するようにアプリケーションを更新します。
attributes/enable-oslogin enable-oslogin=TRUE を設定すると、プロジェクトで OS Login SSH 認証鍵管理機能が有効になります。
attributes/vmdnssetting プロジェクト内のインスタンスの内部 DNS 名のフォーマット方法を設定します。内部 DNS 名の詳細については、DNS 名の構成をご覧ください。
attributes/ssh-keys プロジェクトとインスタンスが、SSH 認証鍵の管理に OS Login を使用するよう構成されていない場合、この属性を使用すると、プロジェクト内のインスタンスに接続できる公開 SSH 認証鍵を構成できます。複数の SSH 認証鍵がある場合は改行文字(\n)で区切ります。この値は文字列です。OS Login によって管理される SSH 認証鍵は、このメタデータ値では表示されません。

例: "user1:ssh-rsa mypublickey user1@host.com\nuser2:ssh-rsa mypublickey user2@host.com"

numeric-project-id インスタンスの数値プロジェクト ID(プロジェクト番号)Google Cloud Platform Console に表示されるプロジェクト名と同じではありません。project-id メタデータ エントリの値とも異なります。
project-id プロジェクト ID

インスタンスのデフォルト メタデータを以下に示します。

パスの基準: http://metadata.google.internal/computeMetadata/v1/instance/
メタデータ エントリ 説明
attributes/ 起動またはシャットダウンの際にインスタンスに渡されるカスタム メタデータ値のディレクトリ。詳しくは、この後のカスタム メタデータの設定をご覧ください。
attributes/enable-oslogin enable-oslogin=TRUE を設定した場合、インスタンスで OS Login SSH 認証鍵管理機能が有効になります。
attributes/vmdnssetting インスタンスの内部 DNS 名のフォーマット方法を設定します。内部 DNS 名の詳細については、DNS 名の構成をご覧ください。
attributes/ssh-keys インスタンスが SSH 認証鍵の管理に OS Login を使用するよう構成されていない場合、この属性を使用すると、インスタンスに接続できる公開 SSH 認証鍵を構成できます。複数の SSH 認証鍵がある場合は改行文字(\n)で区切ります。この値は文字列です。OS Login によって管理される SSH 認証鍵は、このメタデータ値では表示されません。

例: "user1:ssh-rsa mypublickey user1@host.com\nuser2:ssh-rsa mypublickey user2@host.com"

cpu-platform インスタンスの CPU プラットフォーム。
description インスタンスの説明。--description フラグを使用して割り当てるか、API で設定します。
disks/ このインスタンスに接続されているディスクのディレクトリ。
hostname インスタンスのホスト名。
id インスタンスの ID。Google Compute Engine によって生成される一意の数値 ID です。インスタンス名を使わずにインスタンスを識別するのに便利です。
machine-type このインスタンスのマシンタイプのメタデータ値。projects/[NUMERIC_PROJECT_ID]/machineTypes/[MACHINE_TYPE] という形式になります。
name インスタンス名。
network-interfaces/ インスタンスのネットワーク インターフェースのディレクトリ。
network-interfaces/<index>/forwarded-ips/ 現在この仮想マシン インスタンスをネットワーク インターフェース <index> で参照している外部 IP のディレクトリ。具体的には、このインスタンスにパケットを転送する転送ルールによって処理される外部 IP のリストを提供します。
scheduling/ インスタンスのスケジュール オプションを含むディレクトリ。
scheduling/on-host-maintenance インスタンスの透過的メンテナンス イベントの動作の設定。この値は、--on_host_maintenance フラグまたは API を使用して設定します。
scheduling/automatic-restart インスタンスの自動再起動の設定。この値は、‑‑automatic_restart フラグまたは API を使用して設定します。
scheduling/preemptible インスタンスのプリエンプティブの設定。この値が TRUE の場合、インスタンスはプリエンプティブです。この値はインスタンスの作成時に設定され、変更することはできません。
maintenance-event 透過的メンテナンス イベントがこのインスタンスに影響を与えていることを示すパス。詳しくは、透過的メンテナンスの通知をご覧ください。
service-accounts/ インスタンスに関連付けられているサービス アカウントのディレクトリ。
service-accounts/<service-account-name>/identity インスタンスに固有の JSON Web トークン。このインスタンス メタデータ値のリクエストには「audience」パラメータを含める必要があります(例: `?audience=http://www.example.com`)。インスタンス ID トークンのリクエストおよび確認方法の詳細については、インスタンスの ID の確認をご覧ください。
tags インスタンスに関連付けられているタグ
zone このインスタンスが実行されているゾーンのメタデータ値。形式は projects/[NUMERIC_PROJECT_ID]/zones/[ZONE] となります。

メタデータの取得

メタデータ サーバーのコンテンツのクエリを実行するには、仮想マシン インスタンスから次のルート URL にリクエストを送信します。メタデータ サーバーにリクエストを送信するには、http://metadata.google.internal/computeMetadata/v1/ という URL を使用します。

すべてのメタデータ値は、これらのルート URL の下のサブパスとして定義されます。

デフォルト メタデータの値のクエリは、関連付けられているインスタンスからのみ実行できます。別のインスタンスから実行したり、直接ローカル コンピュータから実行したりすることはできません。curlwget などの標準のツールを使用して、インスタンスからメタデータ サーバーに接続できます。

メタデータのクエリを実行する際には、すべてのリクエストに次のヘッダーを含める必要があります。

Metadata-Flavor: Google

これにより、そのリクエストがメタデータ値を取得する目的で送信されたものであり、安全でないソースから意図せず送信されたものではないことが示されるため、リクエストしたデータがメタデータ サーバーから返されるようになります。このヘッダーが含まれていないリクエストはメタデータ サーバーで拒否されます。

X-Forwarded-For ヘッダー

X-Forwarded-For ヘッダーを含むリクエストは、メタデータ サーバーで自動的に拒否されます。このヘッダーは、一般に、リクエストにプロキシが使用されていることを示します。この場合、承認されたユーザーからのリクエストではない可能性があります。そのようなリクエストは、セキュリティ上の理由からすべて拒否されます。

メタデータ情報のセキュリティ

メタデータ サーバーにリクエストを送信して情報を取得する際、そのリクエストやそれに対するメタデータ レスポンスが、仮想マシン インスタンスを実行する物理ホストの外に出ることはありません。

ディレクトリ リストのクエリ

メタデータ サーバーでは、一部のメタデータキーを整理するためにディレクトリが使用されています。末尾にスラッシュが付いているメタデータ エントリがディレクトリです。たとえば、disks/ というエントリは、そのインスタンスに接続されているディスクのディレクトリです。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/" -H "Metadata-Flavor: Google"

0/
1/
2/

同様に、1/ ディレクトリに関する詳細情報が必要な場合は、そのディレクトリの URL に対してクエリを実行できます。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/1/" -H "Metadata-Flavor: Google"

device-name
index
mode
type

エンドポイントのクエリ

ディレクトリではないメタデータキーは、1 つ以上の値を返すエンドポイントです。たとえば、特定のディスクのモードを調べるには、次のエンドポイントに対してクエリを実行します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/1/mode" -H "Metadata-Flavor: Google"

READ_WRITE

デフォルトでは、エンドポイントごとにレスポンスの形式があらかじめ定義されています。データを JSON 形式で返すエンドポイントもあれば、文字列として返すエンドポイントもあります。指定されているデフォルトのデータ形式をオーバーライドするには、クエリ パラメータの alt=json(データを JSON 文字列形式で返します)または alt=text(データのプレーンテキスト表現を返します)を使用します。

たとえば、tags キーではデータが自動的に JSON 形式で返されますが、これをテキスト形式で返されるように変更するには、alt=text クエリ パラメータを指定します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags" -H "Metadata-Flavor: Google"

["bread","butter","cheese","cream","lettuce"]
user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?alt=text" -H "Metadata-Flavor: Google"

bread
butter
cheese
cream
lettuce

メタデータの再帰クエリ

ディレクトリ以下のすべての内容が返されるようにするには、リクエストで recursive=true クエリ パラメータを使用します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/?recursive=true" -H "Metadata-Flavor: Google"

[{"deviceName":"boot","index":0,"mode":"READ_WRITE","type":"PERSISTENT"},
{"deviceName":"persistent-disk-1","index":1,"mode":"READ_WRITE","type":"PERSISTENT"},
{"deviceName":"persistent-disk-2","index":2,"mode":"READ_ONLY","type":"PERSISTENT"}]

デフォルトでは、再帰クエリの結果は JSON 形式で返されます。テキスト形式で返されるようにするには、alt=text クエリ パラメータを追加します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/?recursive=true&alt=text" -H "Metadata-Flavor: Google"

0/device-name boot
0/index 0
0/mode READ_WRITE
0/type PERSISTENT
1/device-name persistent-disk-1
1/index 1
1/mode READ_WRITE
1/type PERSISTENT
2/device-name persistent-disk-1
2/index 2
2/mode READ_ONLY
2/type PERSISTENT

カスタム メタデータの設定

インスタンスやプロジェクトのカスタム メタデータは、Google Cloud Platform Consolegcloud コマンドライン ツールまたは Compute Engine API から設定できます。カスタム メタデータは、プロジェクトやインスタンスに任意の値を渡したり、起動スクリプトやシャットダウン スクリプトを設定したりする場合に便利です。

カスタム メタデータ サイズの制限

Google Compute Engine では、カスタム メタデータ値の長さに次の制限が適用されます。

  • 個々のメタデータ エントリごとに 256 KB
  • インスタンスあたりのすべてのメタデータ エントリの合計 512 KB

特に、SSH 認証鍵は ssh-keys キーの下にカスタム メタデータとして保存されます。このキーのメタデータ コンテンツが 256 KB の制限を超えると、SSH キーを追加できなくなります。この制限に達した場合は、新しいキーのメタデータ スペースを解放するために未使用のキーを削除することを検討してください。

起動スクリプトまたはシャットダウン スクリプトの内容を直接指定した場合、起動スクリプトとシャットダウン スクリプトの内容もカスタム メタデータとして保存され、これらのサイズ制限のカウントの対象になることがあります。これを避けるには、起動スクリプトまたはシャットダウン スクリプトを Google Cloud Storage などの外部の場所にホストされたファイルとして保存し、インスタンスを作成するときに起動スクリプトの URL を指定します。これらのファイルは、メタデータ サーバーに保存される代わりに VM インスタンスにダウンロードされます。

インスタンス メタデータの設定

GCP Consolegcloud ツール、API で、インスタンスのカスタム メタデータを設定します。インスタンス メタデータは、特定のインスタンスにのみ適用されます。

インスタンス作成時のメタデータの設定

Console

  1. GCP Console の [VM インスタンス] ページに移動します。

    [VM インスタンス] ページに移動

  2. [インスタンスを作成] をクリックします。
  3. [新しいインスタンスの作成] ページで、インスタンス向けに希望するプロパティを入力します。
  4. [メタデータ] セクションで、カスタム メタデータの Key-Value ペアを必要な数だけ入力します。
  5. [作成] をクリックしてインスタンスを作成します。

gcloud

gcloud コマンドライン ツールで --metadata フラグを使用してカスタム メタデータを設定します。

gcloud compute instances create example-instance --metadata foo=bar

API

API では、リクエストのメタデータ プロパティの一部としてカスタム メタデータを渡します。

POST https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances

{
  "...
        }
      ]
    }
  ],
  "metadata": {
    "items": [
      {
       "key": "foo",
       "value": "bar"
      }
    ]
  },
  ..
}

実行中のインスタンスのメタデータの更新

Console

  1. [VM インスタンス] ページに移動します。
  2. メタデータを更新するインスタンスをクリックします。
  3. ページの上部にある [編集] ボタンをクリックします。
  4. [カスタム メタデータ] で、[項目を追加] をクリックするか、既存のメタデータ エントリを編集します。
  5. 変更を保存します。

gcloud

gcloud ツールでは、追加アクションを使用してインスタンス メタデータを更新します。追加または変更するメタデータキーのみを指定します。指定したキーがすでに存在する場合は、そのキーの値が新しい値で更新されます。

gcloud コマンドライン ツールで instances add-metadata コマンドを使用します。

gcloud compute instances add-metadata INSTANCE \
  --metadata bread=mayo,cheese=cheddar,lettuce=romaine

lettuce=romaine エントリを lettuce=green に変更するには、次のコマンドを使用します。

gcloud compute instances add-metadata INSTANCE --metadata lettuce=green

lettuce=romaine エントリを削除するには、値を含めずにこの既存のキーを指定します。

gcloud compute instances remove-metadata INSTANCE --keys lettuce

API

API では、instances().setMetadata メソッドにリクエストを送信します。新しいメタデータ値一覧と、最新の fingerprint 値を渡します。

フィンガープリントとは、Compute Engine によって生成されるランダムな文字列で、楽観的ロックを実行するために使用されます。リクエストを実行するには、一致するフィンガープリント値を指定する必要があります。フィンガープリントはリクエストのたびに変更され、一致しないフィンガープリントを指定するとリクエストが拒否されます。これにより、一度に実行できる更新が 1 つだけになるため、競合が防止されます。

インスタンスの最新のフィンガープリントを取得して、そのインスタンスの既存の Key-Value ペアを表示するには、instances().get リクエストを送信します。

GET https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance

{
 ...
 "name": "example-instance",
 "metadata": {
  "kind": "compute#metadata",
  "fingerprint": "zhma6O1w2l8="
  "items": [
   {
    "key": "foo",
    "value": "bar"
   }
  ]
 },
 ...
}

次に、instances().setMetadata メソッドにリクエストを送信して、カスタム メタデータの Key-Value ペアを設定します。インスタンスの既存の Key-Value ペアを保持する場合は、新しい Key-Value ペアとともにこのリクエストに含める必要があります。

POST https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance/setMetadata

{
 "fingerprint": "zhma6O1w2l8=",
 "items": [
  {
   "key": "foo",
   "value": "bar"
  },
  {
   "key": "baz",
   "value": "bat"
  }
 ]
}

インスタンスのすべてのメタデータの Key-Value ペアを削除するには、items プロパティを含めずに instances().setMetadata リクエストを指定します。リクエストには最新のフィンガープリントを含める必要があります。含まれていないとリクエストが失敗します。

POST https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance/setMetadata

{
 "fingerprint": "5rC_DXxBUZw="
}

プロジェクト全体のカスタム メタデータの設定

プロジェクト全体のメタデータを設定すると、そのメタデータがプロジェクトのすべてのインスタンスに適用されます。たとえば、baz=bat というプロジェクト全体のメタデータペアを定義すると、そのメタデータペアは、プロジェクトのすべてのインスタンスに自動的に適用されます。

Console

  1. [メタデータ] ページに移動します。
  2. [編集] をクリックします。
  3. メタデータ エントリを追加または編集します。
  4. 変更を保存します。

gcloud

gcloud コマンドライン ツールで project-info add-metadata コマンドを使用します。次に例を示します。

gcloud compute project-info add-metadata --metadata foo=bar,baz=bat
gcloud compute project-info describe

...
commonInstanceMetadata:
  fingerprint: RfOFY_-eS64=
  items:
  - key: baz
    value: bat
  - key: foo
    value: bar
  - key: ssh-keys
...

等号を使用して、メタデータの Key-Value ペアを 1 つ指定します(例: key=value)。複数の Key-Value ペアを指定するにはスペースで区切ります。

--metadata-from-file フラグを使用して、メタデータの読み取り元のファイルを指定することもできます。メタデータ値を削除するには project-info remove-metadata コマンドを使用します。

API

API では、projects().setCommonInstanceMetadata メソッドにリクエストを送信して、すべての新しいメタデータ値と fingerprint 値を渡します。

フィンガープリントとは、Compute Engine によって生成されるランダムな文字列で、楽観的ロックを実行するために使用されます。リクエストを実行するには、一致するフィンガープリント値を指定する必要があります。フィンガープリントはリクエストのたびに変更され、一致しないフィンガープリントを指定するとリクエストが拒否されます。これにより、一度に実行できる更新が 1 つだけになるため、競合が防止されます。

インスタンスの最新のフィンガープリントを取得するには、project().get リクエストを実行して、フィンガープリント値をコピーします。

GET https://www.googleapis.com/compute/v1/projects/myproject

{
 "name": "myproject",
 "commonInstanceMetadata": {
  "kind": "compute#metadata",
  "fingerprint": "FikclA7UBC0=",
  ...
}

次に、projects().setCommonInstanceMetadata メソッドにリクエストを送信して、カスタム メタデータの Key-Value ペアを設定します。

POST https://www.googleapis.com/compute/v1/projects/myproject

{
 "fingerprint": "FikclA7UBC0=",
 "items": [
  {
   "key": "foo",
   "value": "bar"
  }
 ]
}

カスタム メタデータのクエリ

インスタンスまたはプロジェクトのカスタム メタデータのクエリを実行するには、GCP Console、gcloud コマンドライン ツール、または API を使用します。

Console

プロジェクト全体のカスタム メタデータを表示するには、[メタデータ] ページに移動します。

インスタンスのカスタム メタデータを表示するには:

  1. [VM インスタンス] ページに移動します。
  2. メタデータを表示するインスタンスをクリックします。
  3. [カスタム メタデータ] にインスタンスのカスタム メタデータが表示されます。

gcloud

プロジェクト全体のメタデータのクエリを実行するには、次のコマンドを使用します。

gcloud compute project-info describe

commonInstanceMetadata:
  fingerprint: FikclA7UBC0=
  items:
  - key: peanut
    value: butter
  kind: compute#metadata
creationTimestamp: '2014-07-08T10:32:36.417-07:00'
...
name: example-instance
quotas:
...
selfLink: https://www.googleapis.com/compute/v1/projects/example-instance

インスタンス メタデータのクエリを実行するには、次のコマンドを使用します。

gcloud compute instances describe example-instance

canIpForward: false
cpuPlatform: Intel Sandy Bridge
...
metadata:
  fingerprint: xLQdf0brGqE=
  items:
  - key: peanut
    value: butter
  kind: compute#metadata
name: example-instance
networkInterfaces:
...

API

プロジェクト メタデータのクエリを実行するには、projects().get メソッドに対する空のリクエストを実行します。

GET https://www.googleapis.com/compute/v1/projects/myproject

インスタンス メタデータのクエリを実行するには、instance().get メソッドに対する空のリクエストを実行します。

GET https://www.googleapis.com/compute/v1/projects/myproject/zones/us-central1-a/instances/example-instance

更新の待機

メタデータ値はインスタンスの実行中に変更される可能性があるため、メタデータ サーバーには、メタデータが変更された場合に通知を受けられるように wait-for-change 機能が用意されています。この機能を使用すると、指定したメタデータが変更されていた場合にのみ結果が返される、待機 HTTP GET リクエストを実行できます。この機能は、カスタム メタデータやサーバー定義メタデータでも使用できます。したがって、インスタンスやプロジェクトに変更が加えられた場合でも、カスタム メタデータが更新された場合でも、プログラムでその変更に対処できます。たとえば、tags キーに対するリクエストを実行すると、tags メタデータの内容が変更されていた場合にのみ結果が返されます。返される結果には、そのメタデータキーの新しい値が含まれます。

wait-for-change リクエストを実行するには、メタデータキーをクエリし、?wait_for_change=true クエリ パラメータを追加します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true" -H "Metadata-Flavor: Google"

指定したメタデータキーが変更されると、クエリで新しい値が返されるようになります。この例では、setInstanceTags メソッドにリクエストが送信されると新しい値が返されるようになります。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true" -H "Metadata-Flavor: Google"

cheese
lettuce

wait-for-change リクエストは、ディレクトリの内容に対して再帰的に実行することもできます。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&wait_for_change=true" -H "Metadata-Flavor: Google"

変更があった場合は、新しい内容が返されます。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&wait_for_change=true" -H "Metadata-Flavor: Google"

{"cheese":"lettuce","cookies":"cream"}

wait-for-change 機能では、リクエストとの照合タイムアウトの設定もできます。

ETag の使用

単純な wait-for-change クエリを送信すると、そのメタデータの内容が変更されていた場合にレスポンスが返されます。しかし、メタデータの更新と wait-for-change リクエストの送信の間には固有の競合状態があるため、取得するメタデータ値が最新であることを確認できる確実な方法があると便利です。

その方法として使用できるのが last_etag クエリ パラメータです。このクエリ パラメータは、リクエストで指定された ETag 値と、メタデータ サーバーに保存されている ETag 値を比較します。ETag 値が一致した場合は、wait-for-change リクエストが受け入れられます。ETag 値が一致しない場合は、前回 ETag 値を取得してからメタデータの内容が変更されていることになります。この場合は、その最新の値が直ちに返されます。

メタデータキーの最新の ETag 値を取得するには、そのキーに対するリクエストを送信して、ヘッダーを表示します。CURL では -v フラグを使用します。

user@myinst:~$ curl -v "http://metadata.google.internal/computeMetadata/v1/instance/tags" -H "Metadata-Flavor: Google"
* About to connect() to metadata port 80 (#0)
*   Trying 169.254.169.254... connected
* Connected to metadata (169.254.169.254) port 80 (#0)
> GET /computeMetadata/v1/instance/tags HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-pc-linux-gnu) libcurl/7.19.7 OpenSSL/0.9.8k zlib/1.2.3.3 libidn/1.15
> Host: metadata
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/text
< ETag: 411261ca6c9e654e
< Date: Wed, 13 Feb 2013 22:43:45 GMT
< Server: Metadata Server for VM
< Content-Length: 26
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
<
cheese
lettuce

次に、その ETag 値を使用して wait-for-change リクエストを送信します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true&last_etag=411261ca6c9e654e" -H "Metadata-Flavor: Google"

指定した ETag 値が照合されて、値が変更されていた場合はメタデータキーの新しい内容が返されます。

次の Python サンプルは、メタデータ サーバーの変更をプログラムで監視する方法を示しています。

last_etag = '0'

while True:
    r = requests.get(
        url,
        params={'last_etag': last_etag, 'wait_for_change': True},
        headers=METADATA_HEADERS)

    # During maintenance the service can return a 503, so these should
    # be retried.
    if r.status_code == 503:
        time.sleep(1)
        continue
    r.raise_for_status()

    last_etag = r.headers['etag']

タイムアウトの設定

wait-for-change リクエストで、一定の秒数が経過するとリクエストがタイムアウトになるようにするには、timeout_sec=<timeout-in-seconds> クエリ パラメータを設定します。timeout_sec パラメータは、リクエストの待機時間を指定の秒数に制限します。その制限に達すると、メタデータキーの現在の内容が返されます。360 秒後にタイムアウトになるように設定された wait-for-change リクエストの例を次に示します。

user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/tags?wait_for_change=true&timeout_sec=360" -H "Metadata-Flavor: Google"

timeout_sec パラメータを設定した場合、指定の秒数が経過すると、メタデータ値が実際に変更されているかどうかに関係なく、常に結果が返されます。タイムアウトに設定できるのは整数値だけです。

ステータス コード

wait-for-change リクエストを実行すると、リクエストが成功したかどうかを示す標準の HTTP ステータス コードが返されます。結果がエラーになる場合は、ネットワークの状態が原因でリクエストが失敗して、エラーコードが返されている可能性があります。そのような場合は、それらのエラーが認識されて適切に処理されるようにして、アプリケーションをフォールト トレラントにする必要があります。

メタデータ サーバーから返される可能性があるステータスを以下に示します。

ステータス 説明
HTTP 200 成功です。値が変更されたか、指定した timeout_sec に達してリクエストが正常に終了しました。
Error 400 リクエストが無効です。クエリを修正してリクエストを再試行してください。
Error 404 指定したメタデータ値は存在しません。このエラーは、変更の待機中にメタデータが削除された場合にも返されます。
Error 503 一時的なサーバーエラーか一時的なメンテナンス イベントが発生しました。リクエストを再試行してください。

ライブ マイグレーションの通知取得

メタデータ サーバーは、scheduling/ ディレクトリや maintenance-event 属性を通じて、インスタンスのスケジュールのオプションや設定に関する情報を提供します。これらの属性を使用すると、仮想マシンのインスタンスのスケジュール オプションに関する情報を確認できます。また、このメタデータを使用すると、maintenance-event 属性を通じてメンテナンス イベントがいつ実施されるかを確認できます。デフォルトでは、すべての仮想マシン インスタンスにライブ マイグレーションが設定されています。このため、VM インスタンスにライブ マイグレーションが行われる前に、メタデータ サーバーがメンテナンス イベントを受信します。メンテナンス時に VM インスタンスを終了するように選択している場合には、Compute Engine は VM インスタンスを自動的に終了します。automaticRestart 属性が設定されている場合には、インスタンスを再起動します。メンテナンス イベントとイベント発生時のインスタンスの動作については、スケジュール オプションと設定をご覧ください。

メンテナンス イベントが発生した際に通知を受けるようにするには、maintenance-event 属性に対するクエリを定期的に実行します。この属性の値は、メンテナンス イベントが開始される 60 秒前に変更されるため、アプリケーションのコードで、メンテナンス イベントの前に実行するタスク(データのバックアップ、ログの更新など)をトリガーするために使用できます。Compute Engine には、メンテナンス イベントの通知を確認できる Python スクリプトのサンプルが用意されています。

Compute Engine は、次の場合にのみ 60 秒警告を表示します。

  • メンテナンス イベントの発生時にライブ マイグレーションを実行するように、インスタンスの可用性オプションが設定されている。

  • 最後のメンテナンス イベントの後に 1 回以上 maintenance-event 属性に対するクエリを実行している。maintenance-event 属性に対するクエリが一度も実行されていない場合や、前回のマイグレーションから実行されていない場合は、そのインスタンスではメンテナンス イベントに関する事前の警告は不要と見なされます。この場合、60 秒警告はスキップされて、直ちにメンテナンス イベントが開始されます。60 秒警告がスキップされないようにするには、クライアント コードでマイグレーション イベントの間に少なくとも 1 回は maintenance-event 属性に対するクエリが実行されるようにしてください。

maintenance-event 属性に対するクエリを実行するには、次のコマンドを使用します。

user@myinst:~$ curl http://metadata.google.internal/computeMetadata/v1/instance/maintenance-event -H "Metadata-Flavor: Google"

NONE

maintenance-event 属性の初期値とデフォルト値は NONE です。透過的メンテナンス イベントの前後の maintenance-event 値の変化は次のとおりです。

  1. NONE から MIGRATE_ON_HOST_MAINTENANCE に変更されます。
  2. イベントの間と VM のライブ マイグレーションの実行中は、MIGRATE_ON_HOST_MAINTENANCE のままです。
  3. メンテナンス イベントが終了すると NONE に戻ります。

maintenance-event 属性を更新の待機機能とともに使用すると、メンテナンス イベントの開始と終了をスクリプトやアプリケーションに通知できます。これにより、イベントの前後に実行するアクションを自動化できます。次の Python サンプルは、この 2 つの機能を組み合わせて実装する方法を示しています。

import time

import requests

METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/'
METADATA_HEADERS = {'Metadata-Flavor': 'Google'}

def wait_for_maintenance(callback):
    url = METADATA_URL + 'instance/maintenance-event'
    last_maintenance_event = None
    last_etag = '0'

    while True:
        r = requests.get(
            url,
            params={'last_etag': last_etag, 'wait_for_change': True},
            headers=METADATA_HEADERS)

        # During maintenance the service can return a 503, so these should
        # be retried.
        if r.status_code == 503:
            time.sleep(1)
            continue
        r.raise_for_status()

        last_etag = r.headers['etag']

        if r.text == 'NONE':
            maintenance_event = None
        else:
            # Possible events:
            #   MIGRATE_ON_HOST_MAINTENANCE: instance will be migrated
            #   SHUTDOWN_ON_HOST_MAINTENANCE: instance will be shut down
            maintenance_event = r.text

        if maintenance_event != last_maintenance_event:
            last_maintenance_event = maintenance_event
            callback(maintenance_event)

def maintenance_callback(event):
    if event:
        print('Undergoing host maintenance: {}'.format(event))
    else:
        print('Finished host maintenance')

def main():
    wait_for_maintenance(maintenance_callback)

if __name__ == '__main__':
    main()

v1 への移行

v1 のメタデータ サーバーは、前の v1beta1 のサーバーと動作が少し異なります。新しいメタデータ サーバーに必要な変更を以下に示します。

  • Metadata-Flavor: Google ヘッダーが含まれるようにメタデータ リクエストを更新する

    新しいメタデータ サーバーでは、すべてのリクエストに Metadata-Flavor: Google ヘッダーが含まれている必要があります。このヘッダーは、リクエストがメタデータ値の取得を目的としていることを示します。この新しいヘッダーが含まれるようにリクエストを更新してください。たとえば、disks/ 属性に対するリクエストは次のようになります。

    user@myinst:~$ curl "http://metadata.google.internal/computeMetadata/v1/instance/disks/" -H "Metadata-Flavor: Google"
    

  • X-Forwarded-For ヘッダーが使用されているリクエストを更新する

    このヘッダーは、一般に、リクエストでプロキシが使用されていることを示します。そのため、これらのリクエストはサーバーで自動的に拒否されます。このヘッダーが含まれないようにリクエストを更新してください。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Compute Engine ドキュメント