删除虚拟机


本文档介绍如何删除虚拟机 (VM) 实例。

如果您不再需要虚拟机,可将其删除,以免虚拟机及其挂接的资源产生费用。如果要保留挂接的资源,请在删除虚拟机之前执行以下一项或多项操作:

准备工作

  • 设置身份验证(如果尚未设置)。身份验证是通过其进行身份验证以访问 Google Cloud 服务和 API 的过程。如需从本地开发环境运行代码或示例,您可以按如下方式向 Compute Engine 进行身份验证。

    选择标签页以了解您打算如何使用本页面上的示例:

    控制台

    当您使用 Google Cloud 控制台访问 Google Cloud 服务和 API 时,无需设置身份验证。

    gcloud

    1. 安装 Google Cloud CLI,然后通过运行以下命令初始化 Google Cloud CLI:

      gcloud init
    2. 设置默认区域和可用区

    C#

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    Go

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    Java

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    Node.js

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    PHP

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    Python

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    Ruby

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

    1. 安装 Google Cloud CLI。
    2. 如需初始化 gcloud CLI,请运行以下命令:

      gcloud init
    3. 为您的 Google 账号创建本地身份验证凭据:

      gcloud auth application-default login

    如需了解详情,请参阅 为本地开发环境设置身份验证

    REST

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

      安装 Google Cloud CLI,然后通过运行以下命令初始化 Google Cloud CLI:

      gcloud init

所需的角色

如需获得删除虚拟机所需的权限,请让管理员向您授予项目的 Compute Instance Admin (v1) (roles/compute.instanceAdmin.v1) IAM 角色。如需详细了解如何授予角色,请参阅管理访问权限

此预定义角色可提供删除虚拟机所需的权限。如需查看所需的确切权限,请展开所需权限部分:

所需权限

您需要具备以下权限才能删除虚拟机:

  • 针对虚拟机的 compute.instances.delete 权限
  • 如需强制删除挂接的永久性磁盘:针对磁盘的 compute.disks.delete 权限

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

结算影响

删除虚拟机后,除非符合以下任何情况,否则 Google Cloud 将不再针对虚拟机及其挂接的资源向您收取费用:

  • 如果您删除在单租户节点上托管的虚拟机,则您将继续为单租户节点本身支付费用,而不是为在该节点上托管的各个虚拟机支付费用。

  • 如果您有承诺使用折扣,则无论您是否使用这些资源,您都需要继续为所承诺的资源付费。

  • 如果您保留了挂接到虚拟机的任何资源,这些资源会继续产生费用,直到您将其删除。例如,如果您删除一个虚拟机,但保留了挂接到该虚拟机的永久性磁盘卷,则这些磁盘会继续产生费用。

如需了解详情,请参阅虚拟机实例价格

删除虚拟机的过程

删除虚拟机时,Compute Engine 会执行以下操作:

  1. Compute Engine 会向虚拟机发送 ACPI 关停信号,然后在几秒钟内将虚拟机状态设置为 STOPPING

  2. Compute Engine 会在虚拟机中启动操作系统 (OS) 的正常关停。根据虚拟机类型,关停期如下所示:

    • 抢占式虚拟机:抢占式虚拟机的关停期为 30 秒,与抢占过程的时长相同。

    • 其他虚拟机类型:任何其他虚拟机类型的关停期至少为 90 秒。

  3. 关停期结束时,Compute Engine 将永久删除虚拟机及其挂接的资源。如果您将永久性磁盘配置为在删除其挂接到的虚拟机时保留,则 Compute Engine 会在删除虚拟机时保留该磁盘。

删除虚拟机

如需删除一个或多个虚拟机,请参阅本文档中的以下部分之一:

删除虚拟机和所有挂接的资源

删除一个虚拟机时,默认情况下,Compute Engine 会删除该虚拟机及其所有挂接的资源。但是,如果您将永久性磁盘配置为在删除虚拟机时保留,则可以使用 gcloud CLI 覆盖此设置并同时删除虚拟机和磁盘。

如需同时删除多个虚拟机,请使用 Google Cloud 控制台或 gcloud CLI(对于位于同一可用区的虚拟机)。否则,如需删除单个虚拟机,请使用本部分中介绍的任何方法。

控制台

如需删除一个或多个虚拟机,请执行以下操作:

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

    转到虚拟机实例

  2. 选择要删除的虚拟机。

  3. 点击 删除,然后再次点击删除进行确认。

gcloud

如需删除一个或多个虚拟机,请使用 gcloud compute instances delete 命令

gcloud compute instances delete VM_NAMES \
    --zone=ZONE

替换以下内容:

  • VM_NAMES:位于同一可用区的虚拟机名称列表(以空格分隔);例如 vm-01 vm-02 vm-03

  • ZONE:虚拟机的可用区。

(可选)如需强制删除挂接到一个或多个虚拟机的永久性磁盘卷,请添加 --delete-disks 标志。

gcloud compute instances delete VM_NAMES \
    --delete-disks=DELETE_DISK_TYPE \
    --zone=ZONE

DELETE_DISK_TYPE 替换为要删除的所挂接永久性磁盘卷的类型。请指定以下某个值:

  • 如需删除所有类型的磁盘:all

  • 如需仅删除启动磁盘:boot

  • 如需仅删除非启动磁盘:data

C#


using Google.Cloud.Compute.V1;
using System.Threading.Tasks;

public class DeleteInstanceAsyncSample
{
    public async Task DeleteInstanceAsync(
        // TODO(developer): Set your own default values for these parameters or pass different values when calling this method.
        string projectId = "your-project-id",
        string zone = "us-central1-a",
        string machineName = "test-machine")
    {

        // Initialize client that will be used to send requests. This client only needs to be created
        // once, and can be reused for multiple requests.
        InstancesClient client = await InstancesClient.CreateAsync();

        // Make the request to delete a VM instance.
        var instanceDeletion = await client.DeleteAsync(projectId, zone, machineName);

        // Wait for the operation to complete using client-side polling.
        await instanceDeletion.PollUntilCompletedAsync();
    }
}

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
)

// deleteInstance sends a delete request to the Compute Engine API and waits for it to complete.
func deleteInstance(w io.Writer, projectID, zone, instanceName string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	req := &computepb.DeleteInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	op, err := instancesClient.Delete(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to delete instance: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Instance deleted\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.DeleteInstanceRequest;
import com.google.cloud.compute.v1.InstancesClient;
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 DeleteInstance {

  public static void main(String[] args)
      throws IOException, InterruptedException, ExecutionException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";
    deleteInstance(project, zone, instanceName);
  }

  // Delete the instance specified by `instanceName`
  // if it's present in the given project and zone.
  public static void deleteInstance(String project, String zone, String instanceName)
      throws IOException, InterruptedException, ExecutionException, 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()) {

      System.out.printf("Deleting instance: %s ", instanceName);

      // Describe which instance is to be deleted.
      DeleteInstanceRequest deleteInstanceRequest = DeleteInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName).build();

      OperationFuture<Operation, Operation> operation = instancesClient.deleteAsync(
          deleteInstanceRequest);
      // Wait for the operation to complete.
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.hasError()) {
        System.out.println("Instance deletion failed ! ! " + response);
        return;
      }
      System.out.println("Operation Status: " + response.getStatus());
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const zone = 'europe-central2-b'
// const instanceName = 'YOUR_INSTANCE_NAME';

const compute = require('@google-cloud/compute');

// Delete the instance specified by `instanceName` if it's present in the given project and zone.
async function deleteInstance() {
  const instancesClient = new compute.InstancesClient();

  console.log(`Deleting ${instanceName} from ${zone}...`);

  const [response] = await instancesClient.delete({
    project: projectId,
    zone,
    instance: instanceName,
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

  // Wait for the delete operation to complete.
  while (operation.status !== 'DONE') {
    [operation] = await operationsClient.wait({
      operation: operation.name,
      project: projectId,
      zone: operation.zone.split('/').pop(),
    });
  }

  console.log('Instance deleted.');
}

deleteInstance();

PHP

use Google\Cloud\Compute\V1\Client\InstancesClient;
use Google\Cloud\Compute\V1\DeleteInstanceRequest;

/**
 * Delete an instance.
 *
 * @param string $projectId Your Google Cloud project ID.
 * @param string $zone Zone where the instance you want to delete is (like "us-central1-a").
 * @param string $instanceName Unique name for the Compute instance to delete.
 *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function delete_instance(
    string $projectId,
    string $zone,
    string $instanceName
) {
    // Delete the Compute Engine instance using InstancesClient.
    $instancesClient = new InstancesClient();
    $request = (new DeleteInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->delete($request);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Deleted instance %s' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Failed to delete instance: %s' . PHP_EOL, $error?->getMessage());
    }
}

Python

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 delete_instance(project_id: str, zone: str, machine_name: str) -> None:
    """
    Send an instance deletion request to the Compute Engine API and wait for it to complete.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone you want to use. For example: “us-west3-b”
        machine_name: name of the machine you want to delete.
    """
    instance_client = compute_v1.InstancesClient()

    print(f"Deleting {machine_name} from {zone}...")
    operation = instance_client.delete(
        project=project_id, zone=zone, instance=machine_name
    )
    wait_for_extended_operation(operation, "instance deletion")
    print(f"Instance {machine_name} deleted.")

Ruby


require "google/cloud/compute/v1"

# Sends an instance deletion request to the Compute Engine API and waits for it to complete.
#
# @param [String] project project ID or project number of the Cloud project you want to use.
# @param [String] zone name of the zone you want to use. For example: "us-west3-b"
# @param [String] instance_name name of the instance you want to delete.
def delete_instance project:, zone:, instance_name:
  # Initialize client that will be used to send requests. This client only needs to be created
  # once, and can be reused for multiple requests.
  client = ::Google::Cloud::Compute::V1::Instances::Rest::Client.new

  puts "Deleting #{instance_name} from #{zone}..."
  begin
    # Make the request to delete a VM instance.
    operation = client.delete project: project, zone: zone, instance: instance_name
    # Wait for the delete operation to complete.
    operation = wait_until_done operation: operation

    if operation.error?
      warn "Error during deletion:", operation.error
    else
      compute_operation = operation.operation
      warn "Warning during creation:", compute_operation.warnings unless compute_operation.warnings.empty?
      puts "Instance #{instance_name} deleted."
    end
  rescue ::Google::Cloud::Error => e
    warn "Exception during deletion:", e
  end
end

REST

如需删除虚拟机,请向 instances delete 方法发出 DELETE 请求。

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

替换以下内容:

  • PROJECT_ID:虚拟机所在项目的 ID。

  • ZONE:虚拟机的可用区。

  • VM_NAME:虚拟机名称。

删除虚拟机并保留永久性磁盘卷

默认情况下,删除虚拟机会删除虚拟机及其挂接的资源。但是,使用 gcloud CLI 删除虚拟机时,您可以指定保留挂接的启动磁盘和/或非启动磁盘,而不考虑磁盘的自动删除设置

如需删除位于同一可用区的一个或多个虚拟机,同时保留其挂接的永久性磁盘卷,请使用带有 --keep-disks 标志的 gcloud compute instances delete 命令

gcloud compute instances delete VM_NAMES \
    --keep-disks=KEEP_DISK_TYPE \
    --zone=ZONE

替换以下内容:

  • VM_NAMES:位于同一可用区的虚拟机名称列表(以空格分隔);例如 vm-01 vm-02 vm-03

  • KEEP_DISK_TYPE:要保留的所挂接永久性磁盘卷的类型。请指定以下某个值:

    • 如需保留所有类型的磁盘:all

    • 如需仅保留启动磁盘:boot

    • 如需仅保留非启动磁盘:data

  • ZONE:虚拟机所在的可用区。

后续步骤