存储和检索实例元数据

每个实例都将其元数据存储在元数据服务器上。您可以通过实例和 Compute Engine API 以编程方式查询此元数据服务器,以获取有关实例的信息,例如实例的主机名、实例 ID、启动和关闭脚本、自定义元数据以及服务帐号信息。您的实例无需任何额外的授权即可自动访问元数据服务器 API。

元数据服务器在与启动关闭脚本结合使用时特别有用,因为您可以使用元数据服务器以编程方式获取实例独有的信息,而无需额外的授权。例如,您可以编写一个启动脚本,以获取实例外部 IP 的元数据键/值对,并在脚本中使用该 IP 来设置数据库。由于每个实例上的默认元数据键都相同,因此您可以重复使用您的脚本,而无需针对每个实例更新该脚本。这有助于您为应用创建不太脆弱的代码。

元数据以格式 key:value 存储。每个实例都可以访问一组默认的元数据条目。您还可以设置自定义元数据

要访问元数据服务器,请查询 http://metadata.google.internal/computeMetadata/v1/ 网址。如需了解详情,请参阅查询元数据

当前版本: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 时,在项目中启用操作系统登录 SSH 密钥管理功能。
attributes/vmdnssetting 配置如何针对项目中的实例设置内部 DNS 名称的格式。如需详细了解内部 DNS 名称,请参阅配置 DNS 名称
attributes/ssh-keys 如果您的项目和实例没有配置为使用操作系统登录进行 SSH 密钥管理,则可以使用此属性配置公共 SSH 密钥,此类密钥可以连接到此项目中的实例。如果有多个 SSH 密钥,则每个密钥将由换行符 (\n) 分隔。此值是一个字符串。由操作系统登录管理的 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 时,在此实例中启用操作系统登录 SSH 密钥管理功能。
attributes/vmdnssetting 配置如何针对此实例设置内部 DNS 名称的格式。如需详细了解内部 DNS 名称,请参阅配置 DNS 名称
attributes/ssh-keys 如果您的实例没有配置为使用操作系统登录进行 SSH 密钥管理,您可以使用此属性配置公共 SSH 密钥,此类密钥可以连接到此实例。如果有多个 SSH 密钥,则每个密钥将由换行符 (\n) 分隔。此值是一个字符串。由操作系统登录管理的 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。如果您不想使用实例名称,则此 ID 对于标识实例非常有用。
machine-type 此实例的计算机类型的元数据值,采用以下格式:projects/[NUMERIC_PROJECT_ID]/machineTypes/[MACHINE_TYPE]
name 实例名称。
network-interfaces/ 实例的网络接口的目录。
network-interfaces/<index>/forwarded-ips/ 当前指向此虚拟机实例的任何外部 IP 的目录(对于 <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 网络令牌。您必须在针对此实例元数据值的请求中添加“audience”参数。例如:“?audience=http://www.example.com”。如需了解如何请求和验证实例身份令牌,请参阅验证实例身份
tags 与实例关联的任何标志
zone 运行此实例的地区的元数据值。该值的格式如下:projects/[NUMERIC_PROJECT_ID]/zones/[ZONE]

获取元数据

您可以通过在虚拟机实例中向以下根网址发出请求,来查询元数据服务器的内容。可使用 http://metadata.google.internal/computeMetadata/v1/ 网址向元数据服务器发出请求。

所有元数据值都被定义为这些根网址下面的子路径。

您只能从关联的实例中查询默认元数据值。您无法从其他实例或者直接从本地计算机查询实例的默认元数据。您可以使用 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/ 目录的更多信息,则可以查询该目录的特定网址:

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

device-name
index
mode
type

查询端点

如果元数据键不是目录,则是返回一个或多个值的端点。例如,要查询特定磁盘的模式,请查询以下端点:

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

READ_WRITE

默认情况下,每个端点都有一种预定义的响应格式。有些端点在默认情况下可能以 JSON 格式返回数据,而其他端点可能以字符串形式返回数据。您可以使用 alt=jsonalt=text 查询参数覆盖默认的数据格式规范,这些参数分别以 JSON 字符串格式或以纯文本表示形式返回数据。

例如,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 等外部位置的文件,并在创建实例时提供启动脚本网址。这些文件将下载到虚拟机实例上,而不是存储在元数据服务器中。

设置实例元数据

可使用 GCP Consolegcloud 工具或 API 设置实例的自定义元数据。实例元数据仅适用于特定实例。

在创建实例期间设置元数据

Console

  1. 在 GCP Console 中,转到“虚拟机实例”页面。

    转到“虚拟机实例”页面

  2. 点击创建实例
  3. 创建新实例页面上,为实例填写所需的属性。
  4. 元数据部分,根据自己的需求为您的自定义元数据填写键值对。
  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. 转到虚拟机实例页面
  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 生成的随机字符串,用于执行乐观锁定。请提供匹配的指纹值以执行您的请求。每次请求后指纹都会更改,因此如果您提供的指纹不匹配,请求将被拒绝。这样,一次只能进行一次更新,以免发生冲突。

要获取实例的当前指纹并查看实例的任何现有键值对,请发送 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 方法发出请求并设置您的自定义元数据键值对。如果实例具有您想要保留的现有键值对,您必须使用新的键值对将其包含在此请求中:

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"
  }
 ]
}

要从实例中移除所有元数据键值对,请指定 instances().setMetadata 请求并排除 items 属性。请注意,您必须仍然添加当前的元数据指纹属性,才能使此请求成功:

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

使用 describe 命令查看元数据:

gcloud compute project-info describe

例如,您可能会得到类似如下内容的响应:

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

一个元数据键值对是使用等号指定的,例如 key=value。多个键值对以空格分隔。

您可以选择使用 --metadata-from-file 标志来指定要从中读取元数据的一个或多个文件。可以使用 project-info remove-metadata 命令来移除元数据值。

API

在 API 中,向 projects().setCommonInstanceMetadata 方法发出请求,并提供所有新的元数据值和一个 fingerprint 值。

指纹是 Compute Engine 生成的随机字符串,用于执行乐观锁定。请提供匹配的指纹值以执行您的请求。每次请求后指纹都会更改,因此如果您提供的指纹不匹配,请求将被拒绝。这样,一次只能进行一次更新,以免发生冲突。

要获取实例的当前指纹,请执行 project().get 请求并复制指纹值:

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

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

接下来,向 projects().setCommonInstanceMetadata 方法发出请求并设置您的自定义元数据键值对:

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

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

查询自定义元数据

通过 GCP Console、gcloud 命令行工具或 API 来查询自定义实例或项目元数据。

Console

要查看项目范围的自定义元数据,请转到元数据页面。

要查看实例的自定义元数据,请执行以下操作:

  1. 转到虚拟机实例页面
  2. 点击您想要查看其元数据的实例。
  3. 自定义元数据下方,查看实例的自定义元数据。

gcloud

查询项目范围的元数据:

gcloud compute project-info describe --flatten="commonInstanceMetadata[]"

查询实例元数据:

gcloud compute instances describe example-instance --flatten="metadata[]"

--flatten 标志可用于将输出范围限定为相关的元数据键。以下示例中的实例具有 foo:bar 的自定义元数据键值对。

$ gcloud compute instances describe example-instance

...
metadata:
  fingerprint: Cad2L9eKNR0=
  items:
  - key: foo
    value: bar
  kind: compute#metadata
...

要查询键 foo 的值,请运行以下命令:

$ gcloud compute instances describe example-instance --flatten="metadata[foo]"

---
  bar

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 键执行请求,以使请求仅在标记元数据的内容发生更改时才返回。请求返回后,会提供该元数据键的新值。

要执行 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

然后,您可以在 wait-for-change 请求中使用该 ETag 值:

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 属性收到通知。默认情况下,所有虚拟机实例都设置为实时迁移,以便元数据服务器将在虚拟机实例实时迁移前收到维护事件通知。如果您选择在维护期间终止虚拟机实例,则 Compute Engine 将自动终止您的虚拟机实例并选择性地重启这些实例(如果设置了 automaticRestart 属性)。要详细了解维护事件以及这些事件发生时的实例行为,请参阅时间安排选项和设置

您可以通过定期查询 maintenance-event 属性来了解维护事件何时发生。此属性的值将会在维护事件开始之前 60 秒更改,从而为您的应用代码提供了一种方式来触发您要在维护事件发生之前执行的任何任务,例如备份数据或更新日志。Compute Engine 还提供示例 Python 脚本来演示如何检查是否有维护事件通知。

只有在以下情况下,Compute Engine 才会发出 60 秒警告:

  • 您已将实例的可用性选项设置为在维护事件发生时实时迁移。

  • 自上次维护事件以来,您至少已查询 maintenance-event 属性一次。如果您从未查询过 maintenance-event 属性,或者自上次迁移后未查询该属性,则 Compute Engine 会假定该实例不需要提前收到维护事件警告。维护事件会跳过 60 秒警告,改为立即启动。如果您不想跳过 60 秒警告,请确保您的客户端代码会在两次迁移事件之间至少查询 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. 在整个事件持续期间以及您的虚拟机实时迁移时,该值仍为 MIGRATE_ON_HOST_MAINTENANCE
  3. 在维护事件结束后,该值会恢复为 NONE

您可以将 maintenance-event 属性与等待更新功能结合使用,以在维护事件即将开始和结束时通知您的脚本和应用。这可让您自动执行任何可能要在事件前后运行的操作。以下 Python 示例提供了如何将这两种功能一起实现的示例。

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:
            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 文档