修改计算实例的机器类型


如果您的虚拟机 (VM) 实例没有附加的本地 SSD 且不属于托管式实例组 (MIG),您可以在停止该实例后更改其机器类型

如果现有机器类型不适合您在虚拟机上运行的工作负载,请更改该虚拟机的机器类型。例如,您可以在设置、开发和测试阶段使用具有较小机器类型的虚拟机,然后在准备好运行生产工作负载时将该虚拟机改为使用较大的机器类型。

您可以在以下情况下使用此过程:

  • 如需更改为类似的机器类型,但在同一机器系列中具有不同的 vCPU 数量或内存,请使用以下示例:
    • 您可以将 n2-highcpu-4 更改为 n2-standard-4
    • 您可以将 c3d-standard-30 更改为 c3d-highmem-30
  • 如需更改机器类型以使用其他机器系列。 仅支持第一代和第二代机器系列,不包括 T2A 和 A2 机器系列。例如:
    • 您可以将 n2-standard-4 更改为 c2-standard-8
    • 您可以将 n1-highmem-4 更改为 n2d-standard-16

如果您要将使用第一代或第二代机器系列(N1、N2、M1 等)的虚拟机的机器类型更改为第三代或更高版本机器系列(M3、C3、N4 等)的机器类型,则必须使用将工作负载迁移到新的计算实例中所述的步骤。

您可以在不影响以下资源的情况下更改机器类型:

  • 虚拟机的 SSH 密钥
  • 虚拟机配置,例如虚拟机元数据
  • 已连接的永久性磁盘或 Hyperdisk 上的数据,包括已安装的应用和应用数据

如需更改 MIG 中的虚拟机的机器类型,请参阅在 MIG 中自动应用虚拟机配置更新

准备工作

  • 了解如何关停虚拟机
  • 了解机器类型
  • 如果您尚未设置身份验证,请进行设置。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以按如下方式向 Compute Engine 进行身份验证。

    Select the tab for how you plan to use the samples on this page:

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    Java

    如需在本地开发环境中使用本页面上的 Java 示例,请安装并初始化 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

    Python

    如需在本地开发环境中使用本页面上的 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

    REST

    如需在本地开发环境中使用本页面上的 REST API 示例,请使用您提供给 gcloud CLI 的凭据。

      Install the Google Cloud CLI, then initialize it by running the following command:

      gcloud init

    如需了解详情,请参阅 Google Cloud 身份验证文档中的使用 REST 时进行身份验证

所需的角色

如需获得更改虚拟机机器类型所需的权限,请让管理员向您授予项目上的以下 IAM 角色:

如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限

这些预定义角色包含更改虚拟机的机器类型所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

如需更改虚拟机的机器类型,您需要具备以下权限:

  • 虚拟机上的 compute.instances.setMachineType
  • 虚拟机上的 compute.instances.start
  • 虚拟机上的 compute.instances.stop

您也可以使用自定义角色或其他预定义角色来获取这些权限。

限制

  • 如果您的计算实例具有一个或多个本地 SSD,您将无法更改该实例的机器类型。
  • 如果您的计算实例使用临时外部 IP 地址,则 IP 地址可能会在您修改实例的机器类型时发生变化。如需保留 IP 地址,请在更改机器类型之前将其升级为静态外部 IP 地址
  • 更改计算实例的机器类型不适用于部分配置:

结算影响

不同机器类型的计费费率不同,因此请确保您了解更改机器类型的价格影响。例如,e2-standard-2 机器类型的费用高于 e2-micro 机器类型。

更改机器类型可能还会影响相关虚拟机的持续使用折扣。系统会针对同一区域中的不同类别单独计算持续使用折扣。如果您要更改机器类型,使新机器类型属于其他类别,则虚拟机的后续运行时间将计入新类别的持续使用折扣。

例如,假设您有一个机器类型为 n2-standard-2 的虚拟机,该虚拟机运行了半个月。然后决定将该机器类型更改为 m1-ultramem-40。在您进行此更改后,Compute Engine 就会开始将虚拟机的运行时间计入内存优化的 vCPU 和内存类别的持续使用折扣。

在您的账单上,您会看到机器类型更改之前应用于 n2-standard-2 机器类型的持续使用折扣,以及针对 m1-ultramem-40 的单独持续使用折扣(如果您的虚拟机在 m1-ultramem-40 上保持运行的时间至少占本月剩余时间的 25%)。

迁移到较小的机器类型

如果您弃用配备更多资源的机器类型而改用配备较少资源的机器类型(如弃用 e2-standard-8 机器类型而改用 e2-standard-2),可能会遇到硬件资源问题或性能限制,因为较小机器类型不如较大机器类型功能强大。请确保新的机器类型能够支持正在当前虚拟机上运行的所有应用和服务,或者更新您的服务和应用以便在较小的机器类型上运行。

在更改机器类型之前,请查阅合理容量建议。如需了解 Compute Engine 的容量建议,请参阅为虚拟机实例应用机器类型建议

最佳做法

以下是一些可帮助您成功更改虚拟机机器类型的最佳实践。

  • 使用快照定期备份永久性磁盘数据。在更改机器类型之前,考虑截取永久性磁盘数据的快照。如果您要确保新机器类型能够支持现有虚拟机上的数据,可以截取永久性磁盘快照,并使用该快照来启动第二个运行新机器类型的虚拟机,以确认该虚拟机将成功启动。

  • 将其他磁盘添加到 /etc/fstab 文件中。如果您已将其他磁盘挂接到虚拟机,请确保将它们添加到 /etc/fstab 文件中,以便在虚拟机重新启动时自动装载这些磁盘。

  • 在更改机器类型之前创建预留。为避免与资源可用性相关的错误,请在新机器类型可用时为它们创建 Compute Engine 预留,以便在区域内进行预留。预留有助于确保资源在您需要时可用。

如需创建预留,请完成以下步骤:

  1. 创建预留(或标识现有预留),其属性与计划虚拟机相同。预留的虚拟机数量必须大于或等于您要更改的虚拟机数量。(可选)为了防止其他虚拟机使用此预留,请使用 specificReservationRequired 选项。

  2. 验证计划的虚拟机是否可以使用该预留:

    1. 验证虚拟机是否具有正确的预留亲和性
    2. 在更改虚拟机之前,立即确保预留具有足够的容量

更改机器类型

您只能更改已停止虚拟机的机器类型。只有当虚拟机处于 TERMINATED 状态时,才会被视为已停止。您无法更改正在运行的虚拟机的机器类型。

如果您要将机器类型升级到最新一代,请先查看评估虚拟机迁移选项,然后再继续操作。

控制台

  1. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    转到虚拟机实例

  2. 名称列中,点击您要更改其机器类型的虚拟机的名称。

  3. 虚拟机实例详情页面中,完成以下步骤:

    1. 如果虚拟机正在运行,请在页面顶部的菜单中选择停止以停止虚拟机。
    2. 如需修改虚拟机,请点击 修改
    3. 机器配置部分中,选择要使用的机器类型,或创建自定义机器类型

    4. 要保存更改,请点击保存

    5. 重启虚拟机。

gcloud

  1. 使用 gcloud compute instances stop 命令停止虚拟机:

    gcloud compute instances stop VM_NAME
    

    VM_NAME 替换为包含要更改的机器类型的虚拟机。

  2. 使用 gcloud compute instances set-machine-type 命令更改机器类型。

    gcloud compute instances set-machine-type VM_NAME \
        --machine-type NEW_MACHINE_TYPE
    

    NEW_MACHINE_TYPE 替换为虚拟机的新机器类型。机器类型可以是以下类型之一:

  3. 使用 gcloud compute instances start 命令启动虚拟机:

    gcloud compute instances start VM_NAME
    

    VM_NAME 替换为您更改的虚拟机的名称。

Java

Java

试用此示例之前,请按照《Compute Engine 快速入门:使用客户端库》中的 Java 设置说明进行操作。 如需了解详情,请参阅 Compute Engine Java API 参考文档

如需向 Compute Engine 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.Instance.Status;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.InstancesSetMachineTypeRequest;
import com.google.cloud.compute.v1.Operation;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ChangeInstanceMachineType {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Cloud project you want to use.
    String projectId = "your-project-id";
    // Name of the zone your instance belongs to.
    String zone = "zone-name";
    // Name of the VM you want to modify.
    String instanceName = "instance-name";
    // The new machine type you want to use for the VM.
    // For example: "e2-standard-8", "e2-custom-4-2048" or "m1-ultramem-40"
    // More about machine types: https://cloud.google.com/compute/docs/machine-resource
    String newMachineType = "e2-standard-8";
    changeMachineType(projectId, zone, instanceName, newMachineType);
  }

  // Changes the machine type of VM.
  // The VM needs to be in the 'TERMINATED' state for this operation to be successful.
  public static void changeMachineType(String projectId, String zone, String instanceName,
      String newMachineType)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the `instancesClient.close()` method on the client to safely
    // clean up any remaining background resources.
    try (InstancesClient instancesClient = InstancesClient.create()) {

      Instance instance = instancesClient.get(projectId, zone, instanceName);
      if (!instance.getStatus().equals(Status.TERMINATED.name())) {
        throw new Error(String.format(
            "Only machines in TERMINATED state can have their machine type changed. "
                + "%s is in %s state.", instance.getName(), instance.getStatus()));
      }

      InstancesSetMachineTypeRequest machineTypeRequest =
          InstancesSetMachineTypeRequest.newBuilder()
              .setMachineType(String.format("projects/%s/zones/%s/machineTypes/%s",
                  projectId, zone, newMachineType))
              .build();

      Operation response = instancesClient
          .setMachineTypeAsync(projectId, zone, instanceName, machineTypeRequest)
          .get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Machine type update failed! " + response);
        return;
      }
      System.out.println("Machine type update - operation status: " + response.getStatus());
    }
  }
}

Python

Python

试用此示例之前,请按照《Compute Engine 快速入门:使用客户端库》中的 Python 设置说明进行操作。 如需了解详情,请参阅 Compute Engine Python API 参考文档

如需向 Compute Engine 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

from __future__ import annotations

import sys
from typing import Any

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def change_machine_type(
    project_id: str, zone: str, instance_name: str, new_machine_type: str
) -> None:
    """
    Changes the machine type of VM. The VM needs to be in the 'TERMINATED' state for this operation to be successful.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone your instance belongs to.
        instance_name: name of the VM you want to modify.
        new_machine_type: the new machine type you want to use for the VM.
            For example: `e2-standard-8`, `e2-custom-4-2048` or `m1-ultramem-40`
            More about machine types: https://cloud.google.com/compute/docs/machine-resource
    """
    client = compute_v1.InstancesClient()
    instance = client.get(project=project_id, zone=zone, instance=instance_name)

    if instance.status != compute_v1.Instance.Status.TERMINATED.name:
        raise RuntimeError(
            f"Only machines in TERMINATED state can have their machine type changed. "
            f"{instance.name} is in {instance.status}({instance.status_message}) state."
        )

    machine_type = compute_v1.InstancesSetMachineTypeRequest()
    machine_type.machine_type = (
        f"projects/{project_id}/zones/{zone}/machineTypes/{new_machine_type}"
    )
    operation = client.set_machine_type(
        project=project_id,
        zone=zone,
        instance=instance_name,
        instances_set_machine_type_request_resource=machine_type,
    )

    wait_for_extended_operation(operation, "changing machine type")

REST

  1. 使用 instances.stop 方法停止虚拟机:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop
    

    请替换以下内容:

    • PROJECT_ID:项目 ID

    • ZONE:包含虚拟机的可用区

    • VM_NAME:包含要更改的机器类型的虚拟机

  2. 使用 instances.setMachineType 方法更改机器类型:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/setMachineType
    

    在请求正文中,提供更新后的 machineType

    {
        machineType: "zones/MACHINE_TYPE_ZONE/machineTypes/NEW_MACHINE_TYPE"
    }
    

    替换以下内容:

    • MACHINE_TYPE_ZONE:包含机器类型的可用区

    • NEW_MACHINE_TYPE:虚拟机的新机器类型

      机器类型可以是以下类型之一:

  3. 使用 instances.start 方法创建虚拟机:

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/start
    

    请替换以下内容:

    • PROJECT_ID:项目 ID
    • ZONE:包含虚拟机的可用区
    • VM_NAME:您更改的虚拟机的名称

后续步骤