获取实时迁移通知


元数据服务器通过 scheduling/ 元数据目录列表和 maintenance-event 元数据键提供有关虚拟机实例的调度选项和设置的信息。您可以使用这些元数据键了解虚拟机的调度选项,并在维护事件即将发生时通知您。

默认情况下,所有虚拟机(Z3 除外)都设置为实时迁移,并且元数据服务器会在实时迁移虚拟机实例之前收到维护事件通知。但如果您选择不同的时间安排选项,维护事件和虚拟机行为可能会有所不同。如需详细了解维护事件以及这些事件发生时的虚拟机行为,请参阅主机维护概览

准备工作

  • 对于 Windows Server 虚拟机,请使用 PowerShell 3.0 或更高版本。我们建议您使用 ctrl+v 来粘贴复制的代码块。
  • 如果您尚未设置身份验证,请进行设置。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以按如下方式向 Compute Engine 进行身份验证。

    如需在本地开发环境中使用本页面上的 Python 示例,请安装并初始化 gcloud CLI,然后使用您的用户凭据设置应用默认凭据。

    1. Install the Google Cloud CLI.
    2. To initialize the gcloud CLI, run the following command:

      gcloud init
    3. If you're using a local shell, then create local authentication credentials for your user account:

      gcloud auth application-default login

      You don't need to do this if you're using Cloud Shell.

    如需了解详情,请参阅 Set up authentication for a local development environment

获取实时迁移通知

您可以定期查询 maintenance-event 元数据键,以了解维护事件会在何时发生。

只有在您已将虚拟机的调度选项设置为 migrate 或者您的虚拟机挂接了 GPU 时,系统才会针对维护事件填充 maintenance-event 元数据。

此元数据键的值会在维护事件开始前 60 秒发生更改,让您的应用代码能够在维护事件之前触发您要执行的任何任务,例如备份数据或更新日志。

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

  • 您已将虚拟机的可用性选项设置为在维护事件期间实时迁移。

  • 自上次维护事件以来,您已查询 maintenance-event 元数据键至少一次。

    • 如果您从未查询过 maintenance-event 元数据键,或者自上次迁移后未查询过元数据键,则 Compute Engine 会假定虚拟机不需要接收维护事件的提前警告。维护事件会跳过 60 秒的警告期而立即启动。

    • 如果您不想跳过 60 秒的警告期,请确保您的客户端代码会在两次迁移事件之间至少查询一次 maintenance-event 元数据键。您必须直接查询 maintenance-event 元数据键,以便 Compute Engine 确定您是否在监控此元数据键。查询更高级层的元数据不会触发提前通知。

对于挂接了 GPU 的虚拟机,该值会在虚拟机停止前 60 分钟发生更改,让您有时间关停虚拟机并在其他宿主机上再次重启虚拟机。挂接了 GPU 的虚拟机不会实时迁移,而是会停止并视情况重启。如需了解详情,请参阅处理 GPU 宿主机维护事件

对于一组特定的虚拟机,您的虚拟机维护选项更加灵活。如需了解详情,请参阅监控和规划主机维护事件

查询维护事件元数据键

Linux 虚拟机

如需查询 Linux 虚拟机上的 maintenance-event 元数据键,请运行以下命令:

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

输出类似于以下内容:

NONE

您还可以使用 wait-for-change 选项。指定此选项后,仅当维护事件即将开始和结束时,请求才会返回输出。

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

Windows 虚拟机

如需查询 Windows 虚拟机上的 maintenance-event 元数据键,请运行以下命令:

PS C:\> 
$value = (Invoke-RestMethod `
         -Headers @{'Metadata-Flavor' = 'Google'} `
         -Uri "http://metadata.google.internal/computeMetadata/v1/instance/maintenance-event")
$value

输出类似于以下内容:

NONE

您还可以使用 wait-for-change 选项。指定此选项后,仅当维护事件即将开始和结束时,请求才会返回输出。

PS C:\> 
$value = (Invoke-RestMethod `
         -Headers @{'Metadata-Flavor' = 'Google'} `
         -Uri "http://metadata.google.internal/computeMetadata/v1/instance/maintenance-event?wait_for_change=true")
$value

Python

您可以将 maintenance-event 元数据键与等待更新功能搭配使用,以便在维护事件即将开始和即将结束时向您的脚本和应用发送通知。这样,您就能自动执行可能需要在该事件前后运行的任意操作。

以下 Python 示例演示了如何将这两种功能一起实现。


import time
from typing import Callable, NoReturn, Optional

import requests


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


def wait_for_maintenance(callback: Callable[[Optional[str]], None]) -> NoReturn:
    """
    Start an infinite loop waiting for maintenance signal.

    Args:
        callback: Function to be called when a maintenance is scheduled.

    Returns:
        Never returns, unless there's an error.
    """
    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: Optional[str]) -> None:
    """
    Example callback function to handle the maintenance event.

    Args:
        event: details about scheduled maintenance.
    """
    if event:
        print(f"Undergoing host maintenance: {event}")
    else:
        print("Finished host maintenance")


def main():
    wait_for_maintenance(maintenance_callback)


if __name__ == "__main__":
    main()

查看输出

maintenance-event 元数据键的初始默认值为 NONE

  • 对于挂接了 GPU 的虚拟机,在维护事件期间,该值会从 NONE 更改为 TERMINATE_ON_HOST_MAINTENANCE。此值会在终结事件开始前 60 分钟更新。

  • 对于调度选项为 migrate 的非 GPU 虚拟机,maintenance-event 值会发生如下变化:

    1. 在迁移事件开始时,值会从 NONE 更改为 MIGRATE_ON_HOST_MAINTENANCE。此值会在终结事件开始前 60 秒更新。
    2. 在整个事件持续期间以及您的虚拟机实时迁移期间,该值保持为 MIGRATE_ON_HOST_MAINTENANCE
    3. 在维护事件结束后,该值会恢复为 NONE
  • 对于单租户虚拟机,在主机维护事件期间,maintenance-event 元数据键值对不会更改,并且从事件开始到事件结束都保持为 NONE

后续步骤