创建和启动抢占式虚拟机实例

本页面介绍了如何创建和使用抢占式虚拟机 (VM) 实例。与常规实例相比,抢占式实例的创建和运行费用要低得多。但是,如果 Compute Engine 需要访问这些资源以执行其他任务,可能会终止(抢占)这些实例。抢占式实例将始终在 24 小时后终止。要详细了解抢占式实例,请参阅抢占式实例文档。

建议仅对可以承受实例抢占的容错型应用使用抢占式实例。在决定创建抢占式实例之前,请确保您的应用可以处理抢占。要了解抢占式实例的风险和价值,请参阅抢占式实例文档。

准备工作

创建抢占式实例

通过 Google Cloud Platform Consolegcloud 工具API 创建抢占式实例。

Console

创建抢占式实例的方式与创建常规实例相同,不过创建抢占式实例时需要启用 preemptible 属性。

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

    转到“虚拟机实例”页面

  2. 点击创建实例
  3. 创建新实例页面上,为实例填写所需的属性。
  4. 点击管理、安全、磁盘、网络、单独租用
  5. 可用性政策下,将抢占选项设置为开启。此设置会对实例停用自动重启功能,并将主机维护操作设置为终止
  6. 点击创建以创建实例。

gcloud

使用 gcloud compute 时,请使用您用于创建常规实例的同一 instances create 命令,不过要添加 --preemptible 标志。

gcloud compute instances create [INSTANCE_NAME] --preemptible

其中 [INSTANCE_NAME] 是实例的名称。

API

在 API 中,构建一个正常请求以创建实例,但在 scheduling 下方添加 preemptible 属性并将其设置为 true。例如:

POST https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances

{
  'machineType': 'zones/[ZONE]/machineTypes/[MACHINE_TYPE]',
  'name': '[INSTANCE_NAME]',
  'scheduling':
  {
    'preemptible': true
  },
  ...
}

抢占式 CPU 配额

与常规实例一样,抢占式实例需要可用的 CPU 配额。为避免抢占式实例用完常规实例的 CPU 配额,您可以请求一种特殊的“抢占式 CPU”配额。当 Compute Engine 在某个区域中为您授予抢占式 CPU 配额后,所有抢占式实例都将自动计入该配额。所有常规实例都将继续计入常规 CPU 配额。

在您没有抢占式 CPU 配额的区域中,您可以使用常规 CPU 配额来启动抢占式实例。像往常一样,您还将需要足够的 IP 和磁盘配额。抢占式 CPU 配额不会显示在 gcloud 工具或 GCP Console 配额页面中,除非 Compute Engine 已授予该配额。

如需详细了解配额,请访问资源配额页面

使用关闭脚本处理抢占

当您的实例被抢占时,您可以使用关闭脚本在实例停止前执行清理操作。例如,您可以顺利地终止正在运行的进程并将检查点文件复制到 Google Cloud Storage

以下是一个关闭脚本,您可以将其添加到正在运行的抢占式实例中,或者在创建新的抢占式实例时将其添加到该实例中。该脚本会在实例开始关闭时运行,然后操作系统的常规 kill 命令会终止所有剩余的进程。在顺利终止所需程序后,该脚本会将检查点文件并行上传到 Google Cloud Storage 存储分区。

#!/bin/bash

MY_PROGRAM="[PROGRAM_NAME]" # For example, "apache2" or "nginx"
MY_USER="[LOCAL_USERNAME]"
CHECKPOINT="/home/$MY_USER/checkpoint.out"
GSUTIL_OPTS="-m -o GSUtil:parallel_composite_upload_threshold=32M"
BUCKET_NAME="[BUCKET_NAME]" # For example, "my-checkpoint-files" (without gs://)

echo "Shutting down!  Seeing if ${MY_PROGRAM} is running."

# Find the newest copy of $MY_PROGRAM
PID="$(pgrep -n "$MY_PROGRAM")"

if [[ "$?" -ne 0 ]]; then
  echo "${MY_PROGRAM} not running, shutting down immediately."
  exit 0
fi

echo "Sending SIGINT to $PID"
kill -2 "$PID"

# Portable waitpid equivalent
while kill -0 "$PID"; do
   sleep 1
done

echo "$PID is done, copying ${CHECKPOINT} to gs://${BUCKET_NAME} as ${MY_USER}"

su "${MY_USER}" -c "gsutil $GSUTIL_OPTS cp $CHECKPOINT gs://${BUCKET_NAME}/"

echo "Done uploading, shutting down."

要将此脚本添加到实例中,请将此脚本配置为与实例上的应用搭配使用,并将其添加到实例元数据中。

  1. 关闭脚本复制或下载到本地工作站。
  2. 打开要修改的文件,并更改以下变量:
    • [PROGRAM_NAME] 是您要关闭的进程或程序的名称。例如 apache2nginx
    • [LOCAL_USER] 是您用于登录虚拟机的用户名。
    • [BUCKET_NAME] 是您要在其中保存程序检查点文件的 Google Cloud Storage 存储分区的名称。请注意,在这种情况下,存储分区名称不以 gs:// 开头。
  3. 保存更改。
  4. 将关闭脚本添加到新实例现有实例

此脚本假设:

  • 创建的实例至少拥有对 Google Cloud Storage 的读写权限。如需了解有关如何创建具有适当权限范围的实例的说明,请参阅身份验证文档

  • 您拥有现有的 Google Cloud Storage 存储分区并且具有该存储分区的写入权限。

检查实例是否为抢占式实例

您可以使用 GCP Consolegcloud 工具API 来检查实例是否被配置为抢占式实例。

Console


通过查看实例属性来检查实例是否为抢占式实例。

  1. 转到“虚拟机实例”页面。

    转到“虚拟机实例”页面

  2. 选择您的项目并点击继续
  3. 点击您要检查的实例的名称。此时将打开实例详细信息页面。
  4. 抢占式状态是在实例详情的可用性政策部分指定的。

gcloud


gcloud compute 中,使用 instances describe 来获取有关实例的信息,包括实例是否为抢占式实例。

gcloud compute instances describe [INSTANCE_NAME]

其中 [INSTANCE_NAME] 是实例的名称。

抢占式状态包含在响应信息的 scheduling 部分。

...
scheduling:
  automaticRestart: false
  onHostMaintenance: TERMINATE
  preemptible: true
...

API


要检查实例是否为抢占式实例,请使用 API 向实例的 URI 发送 GET 请求。

GET https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances/[INSTANCE_NAME]

抢占式状态包含在响应信息的 scheduling 下方。

{
    "kind": "compute#instance",
    "id": "4468501694759003918",
    "creationTimestamp": "2015-04-15T15:40:59.004-07:00",
    "zone": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f",
    "status": "RUNNING",
    "name": "example-instance",
    "scheduling":
    {
       "preemptible": true
    },
    ...
 }

或者,您可以从实例本身内部确定实例是否为抢占式实例。只需在元数据服务器中检查实例的默认实例元数据中的 scheduling/preemptible 值即可。

例如,在实例中使用 curl 来获取 scheduling/preemptible 的值:

curl "http://metadata.google.internal/computeMetadata/v1/instance/scheduling/preemptible" -H "Metadata-Flavor: Google"
TRUE

如果此值为 TRUE,则表示实例为抢占式实例。

检测实例是否已被抢占

使用 Google Cloud Platform Consolegcloud 工具API 来确定实例是否已被抢占。

Console


您可以通过查看系统活动日志来检查实例是否已被抢占。

  1. 转到“日志”页面。

    转到“日志”页面

  2. 选择您的项目并点击继续
  3. 按标签过滤或搜索文字字段中添加 compute.instances.preempted
  4. (可选)如果您要查看特定实例的抢占操作,也可以输入实例名称。
  5. 按 Enter 键以应用指定的过滤条件。GCP Console 会更新日志列表以仅显示实例被抢占的操作。
  6. 在列表中选择一项操作以查看有关被抢占的实例的详细信息。

gcloud


使用带有 filter 参数的 gcloud compute operations list 命令获取项目中的抢占事件列表。

gcloud compute operations list \
    --filter="operationType=compute.instances.preempted"

您可以使用 filter 参数来进一步确定结果的范围。例如,要仅查看托管实例组中的实例的抢占事件,请执行以下命令:

gcloud compute operations list \
    --filter="operationType=compute.instances.preempted AND targetLink:instances/[BASE_INSTANCE_NAME]"

gcloud 会返回类似于以下内容的响应:

NAME                  TYPE                         TARGET                                   HTTP_STATUS STATUS TIMESTAMP
systemevent-xxxxxxxx  compute.instances.preempted  us-central1-f/instances/example-instance-xxx  200         DONE   2015-04-02T12:12:10.881-07:00

类型为 compute.instances.preempted 的操作会指示实例已被抢占。您可以使用 operations describe 命令来获取有关特定抢占操作的详细信息。

gcloud compute operations describe \
    systemevent-xxxxxxxx

gcloud 会返回类似于以下内容的响应:

...
operationType: compute.instances.preempted
progress: 100
selfLink: https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f/operations/systemevent-xxxxxxxx
startTime: '2015-04-02T12:12:10.881-07:00'
status: DONE
statusMessage: Instance was preempted.
...

API


要获取最近的系统操作列表,请向地区操作的 URI 发送 GET 请求。

GET https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/operations

该响应包含最近的操作列表。

{
  "kind": "compute#operation",
  "id": "15041793718812375371",
  "name": "systemevent-xxxxxxxx",
  "zone": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f",
  "operationType": "compute.instances.preempted",
  "targetLink": "https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-f/instances/example-instance",
  "targetId": "12820389800990687210",
  "status": "DONE",
  "statusMessage": "Instance was preempted.",
  ...
}

要将响应结果限制为仅显示抢占操作,可以向 API 请求添加过滤器:operationType="compute.instances.preempted"。要查看特定实例的抢占操作,请将 targetLink 参数添加到过滤器:operationType="compute.instances.preempted" AND targetLink="https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/[ZONE]/instances/[INSTANCE_NAME]"

或者,您可以从实例本身内部确定实例是否已被抢占。如果您要处理由于 Compute Engine 抢占而导致的关闭(与处理关闭脚本中的正常关闭的方式不同),那么这种做法非常有用。为此,只需在元数据服务器中检查实例的默认实例元数据中的 preempted 值即可。

例如,在实例中使用 curl 来获取 preempted 的值:

curl "http://metadata.google.internal/computeMetadata/v1/instance/preempted" -H "Metadata-Flavor: Google"
TRUE

如果此值为 TRUE,则表示实例已被 Compute Engine 抢占,否则此值将为 FALSE

如果您要在关闭脚本外部使用此命令,则可以将 ?wait_for_change=true 附加到该网址。这将执行挂起 HTTP GET 请求,该请求仅在元数据发生变化并且实例已被抢占时才会返回响应。

curl "http://metadata.google.internal/computeMetadata/v1/instance/preempted?wait_for_change=true" -H "Metadata-Flavor: Google"
TRUE

最佳做法

以下是一些可帮助您充分利用抢占式虚拟机实例的最佳做法。

选择较小的机器形状

抢占式虚拟机实例需要的资源会超出额外及备用 Google Cloud Platform 容量。与较大的机器类型相比,使用较小的机器类型通常更容易获得大量抢占式容量。一直以来,核心数少于 32 个的较小机器类型的抢占率也低于较大机器类型的抢占率。

通过使用介于预定义类型之间的自定义机器类型,您还可以获取更多的备用容量。例如,与 n1-standard-64 相比,配备 48 个 vCPU 的自定义机器类型可能具有更多容量。

在非高峰时段运行大型抢占式虚拟机集群

Google Cloud Platform 数据中心的负载因地点和时段而异,但通常夜晚和周末的负载最低。因此,夜晚和周末是运行大型抢占式虚拟机集群的最佳时间。

将您的应用设计成容错和容抢占型应用

请务必应对以下情况:抢占模式会随着时间点的不同而发生变化。例如,如果某个地区受到部分中断影响,则大量抢占式实例可能会被抢占,以便为需要在恢复过程中迁移的常规实例腾出空间。在这一小段时间内,抢占率会看起来与其他任何一天完全不同。如果您的应用假设抢占始终以小组形式完成,您可能无法应对此类事件。您可以通过停止虚拟机实例来测试在发生抢占事件时的应用行为。

重新尝试创建已被抢占的实例

如果您的实例已被抢占,建议您重试抢占式实例一到两次,然后再回退为常规实例。根据您的要求,建议在您的集群中将常规实例和抢占式实例合并,以确保工作以适当的速度进行。

使用关闭脚本

使用可保存作业进度的关闭脚本来管理关闭和抢占通知,以便作业可以从停止的位置继续执行,而不是从头开始。

后续事项

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
Compute Engine 文档