הפסקה או הפעלה מחדש של מכונה של Compute Engine

אפשר להפסיק ידנית מופע של Compute Engine כשכבר לא משתמשים בו, או כדי לשנות את המאפיינים שלו – לדוגמה, כדי לשנות את סוג המכונה או להסיר דיסקים שמצורפים ומותקנים. אחרי שהמופע מפסיק, אפשר להפעיל אותו מחדש כדי להמשיך את עומס העבודה, או למחוק אותו אם הוא כבר לא נחוץ.

במאמר הזה מוסבר איך לעצור או להפעיל מחדש מכונה באופן ידני. כדי להגדיר הפסקה או הפעלה מחדש אוטומטיות של מכונה, אפשר לעיין במאמרים הבאים:

מגבלות

כשמפסיקים מכונת וירטואלית, חלות המגבלות הבאות:

  • אפשר לעצור או להפעיל מחדש מכונה רק אם מצב המכונה מאפשר זאת.

  • אפשר להפעיל מחדש מכונה רק אם יש מספיק משאבים באזור של המכונה.

  • אי אפשר להפעיל מחדש מכונות TPU.

לפני שמתחילים

התפקידים הנדרשים

כדי לקבל את ההרשאות שנדרשות להפסקת או להפעלה מחדש של מכונת Compute, צריך לבקש מהאדמין להקצות לכם ב-IAM את התפקיד אדמין מכונות של Compute ‏ (v1) (roles/compute.instanceAdmin.v1) בפרויקט. כדי לקרוא הסבר על מתן תפקידים, ראו איך מנהלים את הגישה ברמת הפרויקט, התיקייה והארגון.

זהו תפקיד שמוגדר מראש וכולל את ההרשאות שנדרשות להפסקת מכונת Compute או להפעלה מחדש שלה. כדי לראות בדיוק אילו הרשאות נדרשות, אפשר להרחיב את הקטע ההרשאות הנדרשות:

ההרשאות הנדרשות

כדי לעצור או להפעיל מחדש מכונת חישוב, צריך את ההרשאות הבאות:

  • כדי לעצור מופע: compute.instances.stop במופע
  • כדי להפסיק מכונה ממערכת ההפעלה של האורח: compute.instances.setMetadata במכונה אם היא משתמשת במפתחות SSH ציבוריים ברמת המכונה.
  • כדי להפעיל מחדש מכונה: compute.instances.start במכונה
  • כדי להפעיל מחדש מכונה שמשתמשת במפתחות הצפנה: compute.instances.startWithEncryptionKey במכונה

יכול להיות שתקבלו את ההרשאות האלה באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש אחרים.

הפסקת מופע

כשמפסיקים מופע של Compute או כש-Compute Engine עושה זאת עבור פעולה מתוזמנת, המופע שומר על הדיסקים המצורפים, הגדרות התצורה, כתובות ה-IP, כתובות ה-MAC והמטא-נתונים של המופע. אם רוצים לשמור גם את הנתונים בזיכרון ואת מצב האפליקציה, צריך להשהות את המופע.

בהתאם לשאלה אם למכונה מצורפים דיסקים מסוג SSD מקומי, ולאופן שבו רוצים לטפל בסקריפטים של כיבוי, אפשר להפסיק את המכונה באחת מהשיטות הבאות:

  • איך מפסיקים מופע מ- Cloud de Confiance אפשר להפסיק בו-זמנית מופע אחד או יותר מ- Cloud de Confiance. אם למופעים מצורפים דיסקים של Local SSD, אפשר לבחור אם להשליך או לשמור (תצוגה מקדימה) נתונים של Local SSD. סקריפטים להשבתה במכונה צריכים לסיים את הריצה שלהם לפני סיום תקופת ההשבתה שמוגדרת כברירת מחדל.

    הוראות מפורטות זמינות במאמרים הבאים:

  • הפסקת מופע ממערכת ההפעלה של האורח אפשר להפסיק מופע יחיד מתוך מערכת ההפעלה של האורח. הגישה הזו מאפשרת לעצור מופע רק אחרי שהסקריפטים של כיבוי המופע מסיימים לפעול. אם הפעלתם כיבוי מבוקר, תוכלו גם לעצור את המכונה בלי לבצע כיבוי מבוקר, או לסיים כיבוי מבוקר שכבר מתבצע. אלא אם מגבים ידנית נתונים מכל דיסקי ה-SSD המקומיים המצורפים לנפח אחסון עמיד, עצירה של מופע מתוך דיסק מערכת ההפעלה שלו גורמת למחיקת כל הנתונים בדיסקים האלה.

    הוראות מפורטות מופיעות במאמר בנושא הפסקת פעולה של מופע ממערכת ההפעלה של האורח.

עצירה של מכונה ללא כונני SSD מקומיים

בהתאם לפעולה שרוצים לבצע כשמפסיקים מכונה, משתמשים באפשרויות הבאות:

  • אם הפעלתם כיבוי מבוקר במכונה, אתם יכולים להפסיק את המכונה בלי לכבות אותה בצורה מבוקרת או להפסיק כיבוי מבוקר שמתבצע באמצעות המסוף Cloud de Confiance , ה-CLI של gcloud או API בארכיטקטורת REST.

  • כדי להפסיק כמה מכונות בו-זמנית, משתמשים במסוף Cloud de Confiance או ב-CLI של gcloud (למכונות שנמצאות באותו אזור).

כדי לעצור מכונה אחת או יותר, בוחרים באחת מהאפשרויות הבאות:

המסוף

  1. נכנסים לדף VM instances במסוף Cloud de Confiance .

    כניסה לדף VM instances

  2. בוחרים את המופעים הפועלים שרוצים לעצור.

  3. לוחצים על הפסקה. אם אין אפשרות עצירה, לוחצים על עוד פעולות > עצירה.

  4. בתיבת הדו-שיח שמופיעה, מבצעים את הפעולות הבאות:

    1. אופציונלי: כדי לעצור את המופעים בלי לבצע כיבוי תקין, או כדי להפסיק כיבוי תקין שכבר מתבצע, מסמנים את התיבה דילוג על כיבוי תקין (אם רלוונטי).

    2. כדי לאשר, לוחצים על הפסקה.

gcloud

כדי להפסיק מכונה אחת או יותר באותו אזור, משתמשים בפקודה gcloud compute instances stop:

gcloud compute instances stop INSTANCE_NAMES \
    --zone=ZONE

מחליפים את מה שכתוב בשדות הבאים:

  • INSTANCE_NAMES: רשימה של שמות מופרדים ברווחים של מופעים – לדוגמה, instance-01 instance-02 instance-03.

  • ZONE: האזור שבו נמצאים המופעים.

אופציונלי: אם הפעלתם כיבוי חלק במופע אחד או יותר, אתם יכולים להפסיק את המופעים בלי לכבות אותם בצורה חלקה, או לסיים ידנית כיבוי חלק שמתבצע כרגע. כדי לעשות זאת, משתמשים בפקודה gcloud beta compute instances stop עם הדגל --no-graceful-shutdown:

gcloud beta compute instances stop INSTANCE_NAMES \
    --no-graceful-shutdown \
    --zone=ZONE

המשך

import (
	"context"
	"fmt"
	"io"

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

// stopInstance stops a started Google Compute Engine instance
func stopInstance(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.StopInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	op, err := instancesClient.Stop(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to stop 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 stopped\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.StopInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class StopInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to stop.
     */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";

    stopInstance(project, zone, instanceName);
  }

  // Stops a started Google Compute Engine instance.
  public static void stopInstance(String project, String zone, String instanceName)
      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()) {

      StopInstanceRequest stopInstanceRequest = StopInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.stopAsync(
          stopInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Instance stopped successfully ! ");
      }
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace 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');

async function stopInstance() {
  const instancesClient = new compute.InstancesClient();

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

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

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

stopInstance();

PHP

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

/**
 * Stops a running Google Compute Engine instance.
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to stop.
  *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function stop_instance(
    string $projectId,
    string $zone,
    string $instanceName
) {
    // Stop the Compute Engine instance using InstancesClient.
    $instancesClient = new InstancesClient();
    $request = (new StopInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->stop($request);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s stopped successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Failed to stop 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 stop_instance(project_id: str, zone: str, instance_name: str) -> None:
    """
    Stops a running Google Compute Engine instance.
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to stop.
    """
    instance_client = compute_v1.InstancesClient()

    operation = instance_client.stop(
        project=project_id, zone=zone, instance=instance_name
    )
    wait_for_extended_operation(operation, "instance stopping")

REST

כדי לעצור מכונה, שולחים בקשת POST אל ה-method‏ instances.stop:

POST https://compute.s3nsapis.fr/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/stop

מחליפים את מה שכתוב בשדות הבאים:

  • INSTANCE_NAME: השם של המכונה.

  • PROJECT_ID: מזהה הפרויקט שבו נמצא המופע.

  • ZONE: האזור שבו נמצאת המכונה.

אם הפעלתם כיבוי חלק במופע, אתם יכולים להפסיק את המופע בלי לכבות אותו בצורה חלקה, או להפסיק ידנית כיבוי חלק שמתבצע כרגע. כדי לעשות את זה, שולחים בקשת POST אל ה-method‏ instances.stop. בכתובת ה-URL של הבקשה, כוללים את פרמטר השאילתה noGracefulShutdown=true:

POST https://compute.s3nsapis.fr/compute/beta/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop?noGracefulShutdown=true

עצירה של מכונה עם דיסקים מקומיים מסוג SSD

בהתאם לפעולה שרוצים לבצע כשמפסיקים מכונת חישוב, משתמשים באפשרויות הבאות:

  • אם הפעלתם כיבוי מבוקר במכונה, אתם יכולים להפסיק את המכונה בלי לכבות אותה בצורה מבוקרת או להפסיק כיבוי מבוקר שמתבצע באמצעות המסוף Cloud de Confiance , ה-CLI של gcloud או API בארכיטקטורת REST.

  • כדי לשמור את הנתונים של דיסקים מקומיים מסוג SSD שמצורפים למופע (לא כולל סוגי מכונות שמשתמשים ב-Titanium SSD), צריך להפסיק את המופע באמצעות ה-CLI של gcloud או API בארכיטקטורת REST.

  • כדי להפסיק כמה מכונות בו-זמנית, משתמשים במסוף Cloud de Confiance או ב-CLI של gcloud (למכונות שנמצאות באותו אזור).

כדי לעצור מכונה אחת או יותר שמחוברים אליהן דיסקים של SSD מקומי, בוחרים באחת מהאפשרויות הבאות:

המסוף

  1. נכנסים לדף VM instances במסוף Cloud de Confiance .

    כניסה לדף VM instances

  2. בוחרים את המופעים הפועלים שרוצים לעצור.

  3. לוחצים על הפסקה. אם אין אפשרות עצירה, לוחצים על עוד פעולות > עצירה.

  4. בתיבת הדו-שיח, מבצעים את הפעולות הבאות:

    1. אופציונלי: כדי לעצור את המופעים בלי לבצע כיבוי תקין, או כדי להפסיק כיבוי תקין שכבר מתבצע, מסמנים את תיבת הסימון דילוג על כיבוי תקין (אם רלוונטי).

    2. כדי לאשר, לוחצים על הפסקה.

gcloud

כשמפסיקים מכונה אחת או יותר באותו אזור עם דיסקים מסוג Local SSD שמחוברים אליהן, צריך לציין אם לבטל את הנתונים של Local SSD או לשמור אותם, באופן הבא:

  • כדי לבטל את הנתונים של ה-SSD המקומי, משתמשים בפקודה gcloud compute instances stop עם הדגל --discard-local-ssd=true:

    gcloud compute instances stop INSTANCE_NAMES \
        --discard-local-ssd=true \
        --zone=ZONE
    
  • כדי לשמור את הנתונים ב-SSD מקומי, משתמשים בפקודה gcloud beta compute instances stop עם הדגל --discard-local-ssd=false:

    gcloud beta compute instances stop INSTANCE_NAMES \
        --discard-local-ssd=false \
        --zone=ZONE
    

מחליפים את מה שכתוב בשדות הבאים:

  • INSTANCE_NAMES: רשימה של שמות מופרדים ברווחים של מופעים – לדוגמה, instance-01 instance-02 instance-03.

  • ZONE: האזור שבו נמצאים המופעים.

אופציונלית, אם הפעלתם כיבוי הדרגתי במופע אחד או יותר, אתם יכולים להפסיק את המופעים בלי לכבות אותם בצורה הדרגתית, או להפסיק כיבוי הדרגתי שמתבצע כרגע. כדי לעשות זאת, משתמשים בפקודה gcloud beta compute instances stop עם הדגל --no-graceful-shutdown:

gcloud beta compute instances stop INSTANCE_NAMES \
    --discard-local-ssd=DISCARD_LOCAL_SSD \
    --no-graceful-shutdown \
    --zone=ZONE

מחליפים את DISCARD_LOCAL_SSD ב-true כדי למחוק את הנתונים בדיסקי ה-SSD המקומיים, או ב-false כדי לשמור את הנתונים.

REST

כשמפסיקים מכונה עם דיסקים מקומיים מסוג SSD שמחוברים אליה, צריך לציין אם רוצים להשליך או לשמור את הנתונים בדיסקים המקומיים מסוג SSD, באופן הבא:

  • כדי לבטל את הנתונים של SSD מקומי, צריך לשלוח בקשת POST ל-method‏ instances.stop. בכתובת ה-URL של הבקשה, כוללים את פרמטר השאילתה discardLocalSsd שמוגדר לערך true:

    POST https://compute.s3nsapis.fr/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/stop?discardLocalSsd=true
    
  • כדי לשמור את הנתונים ב-SSD מקומי, צריך לשלוח בקשת POST ל-method‏ beta.instances.stop. בכתובת ה-URL של הבקשה, כוללים את פרמטר השאילתה discardLocalSsd שמוגדר לערך false:

    POST https://compute.s3nsapis.fr/compute/beta/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/stop?discardLocalSsd=false
    

מחליפים את מה שכתוב בשדות הבאים:

  • PROJECT_ID: מזהה הפרויקט שבו נמצא המופע.

  • ZONE: האזור שבו נמצאת המכונה.

  • INSTANCE_NAME: השם של המכונה.

אם הפעלתם כיבוי תקין במופע, אתם יכולים להפסיק את המופע בלי לכבות אותו בצורה תקינה, או להפסיק ידנית כיבוי תקין שמתבצע. כדי לעשות את זה, שולחים בקשת POST אל ה-method‏ instances.stop. בכתובת ה-URL של הבקשה, כוללים את פרמטר השאילתה noGracefulShutdown=true:

POST https://compute.s3nsapis.fr/compute/beta/projects/PROJECT_ID/zones/ZONE/instances/VM_NAME/stop?discardLocalSsd=DISCARD_LOCAL_SSD&noGracefulShutdown=true

מחליפים את DISCARD_LOCAL_SSD ב-true כדי למחוק את הנתונים בדיסקי ה-SSD המקומיים, או ב-false כדי לשמור את הנתונים.

הפסקת מופע ממערכת ההפעלה של האורח

אם למכונת מחשוב מצורפים דיסקים של SSD מקומי, כיבוי של מערכת ההפעלה האורחת יגרום למחיקה אוטומטית של נתוני ה-SSD המקומי. כדי לשמור את הנתונים האלה, צריך להעתיק אותם באופן ידני לאפשרות אחסון קבוע לפני שמפסיקים את המופע.

כדי להפסיק מופע ממערכת ההפעלה של האורח, בוחרים באחת מהאפשרויות הבאות:

Linux

  1. אם עדיין לא עשיתם זאת, מתחברים למופע.

  2. כדי לעצור את המופע, בוחרים אחת מהשיטות הבאות:

    • כדי לבצע כיבוי נקי שמאפשר למופע להריץ סקריפטים של כיבוי לפני כיבוי מערכת ההפעלה של האורח, מריצים את הפקודה הבאה:

      sudo shutdown -h now
      
    • אחרת, כדי לכפות כיבוי, מריצים את הפקודה הבאה:

      sudo poweroff
      

Windows

  1. אם עדיין לא עשיתם זאת, מתחברים למופע באמצעות אחת מהשיטות הבאות:

  2. כדי לעצור את המופע, בוחרים אחת מהשיטות הבאות:

    • כדי לעצור את המופע בצורה נקייה ולאפשר לו להריץ סקריפטים של כיבוי לפני כיבוי מערכת ההפעלה של האורח, מריצים את הפקודה הבאה:

      shutdown /s
      
    • כדי לכפות כיבוי, מריצים את הפקודה הבאה:

      shutdown /f
      

הפעלה מחדש של מופע

אפשר להפעיל מחדש מופע של מחשוב שהופסק לחלוטין, כלומר כשמצב המופע הוא TERMINATED.

אם בחרתם לשמור את הנתונים של דיסקי ה-SSD המקומיים כשעצרתם את המופע, יכול להיות שתצטרכו להרכיב מחדש את דיסקי ה-SSD המקומיים אחרי שתפעילו אותו מחדש. מידע נוסף על אופן ההרכבה של דיסקים של SSD מקומי זמין במאמר פורמט והרכבה של מכשיר SSD מקומי.

כדי להפעיל מחדש מופע, משתמשים באחת מהשיטות הבאות, בהתאם לשאלה אם למופע יש דיסקים שהוצפנו באמצעות מפתחות הצפנה באספקת הלקוח (CSEK):

הפעלה מחדש של מופע שאין לו דיסקים מוצפנים באמצעות CSEK

כדי להפעיל מחדש כמה מכונות בו-זמנית באזורים שונים, משתמשים בCloud de Confiance מסוף. אם המכונות נמצאות באותו אזור, אפשר להשתמש ב-CLI של gcloud. אחרת, בתרחישי הפעלה מחדש אחרים, בוחרים באחת מהאפשרויות הבאות:

המסוף

  1. נכנסים לדף VM instances במסוף Cloud de Confiance .

    כניסה לדף VM instances

  2. בוחרים מכונה אחת או יותר.

  3. לוחצים על התחלה / המשך.

gcloud

כדי להפעיל מחדש מכונה אחת או יותר באותו אזור, משתמשים בפקודה gcloud compute instances start:

gcloud compute instances start INSTANCE_NAMES \
    --zone=ZONE

מחליפים את מה שכתוב בשדות הבאים:

  • INSTANCE_NAMES: רשימה של שמות מופרדים ברווחים של מופעים – לדוגמה, instance-01 instance-02 instance-03.

  • ZONE: האזור שבו נמצאים המופעים.

המשך

import (
	"context"
	"fmt"
	"io"

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

// startInstance starts a stopped Google Compute Engine instance (with unencrypted disks).
func startInstance(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.StartInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	op, err := instancesClient.Start(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to start 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 started\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.StartInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class StartInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to start. */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";

    startInstance(project, zone, instanceName);
  }

  // Starts a stopped Google Compute Engine instance (with unencrypted disks).
  public static void startInstance(String project, String zone, String instanceName)
      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()) {

      // Create the request.
      StartInstanceRequest startInstanceRequest = StartInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName)
          .build();

      OperationFuture<Operation, Operation> operation = instancesClient.startAsync(
          startInstanceRequest);

      // Wait for the operation to complete.
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Instance started successfully ! ");
      }
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment and replace 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');

async function startInstance() {
  const instancesClient = new compute.InstancesClient();

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

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

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

startInstance();

PHP

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

/**
 * Starts a stopped Google Compute Engine instance (with unencrypted disks).
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to stop.
  *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function start_instance(
    string $projectId,
    string $zone,
    string $instanceName
) {
    // Start the Compute Engine instance using InstancesClient.
    $instancesClient = new InstancesClient();
    $request = (new StartInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->start($request);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s started successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Failed to start 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 start_instance(project_id: str, zone: str, instance_name: str) -> None:
    """
    Starts a stopped Google Compute Engine instance (with unencrypted disks).
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to start.
    """
    instance_client = compute_v1.InstancesClient()

    operation = instance_client.start(
        project=project_id, zone=zone, instance=instance_name
    )

    wait_for_extended_operation(operation, "instance start")

REST

כדי להפעיל מחדש מכונה, שולחים בקשת POST אל ה-method‏ instances.start:

 POST https://compute.s3nsapis.fr/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/start

מחליפים את מה שכתוב בשדות הבאים:

  • INSTANCE_NAME: השם של המכונה להפעלה מחדש.

  • PROJECT_ID: מזהה הפרויקט שבו נמצא המופע.

  • ZONE: האזור שבו נמצאת המכונה.

הפעלה מחדש של מכונה עם דיסקים מוצפנים באמצעות CSEK

כשמפעילים מחדש מופע חישוב שהופסק וצורפו אליו דיסקים שהוצפנו באמצעות מפתחות הצפנה באספקת הלקוח (CSEK), צריך לספק את פרטי מפתח ההצפנה.

כדי להפעיל מחדש כמה מכונות בו-זמנית באזורים שונים, משתמשים בCloud de Confiance מסוף. אם המכונות נמצאות באותו אזור, אפשר להשתמש ב-CLI של gcloud. אחרת, בתרחישי הפעלה מחדש אחרים, בוחרים באחת מהאפשרויות הבאות:

המסוף

  1. נכנסים לדף VM instances במסוף Cloud de Confiance .

    כניסה לדף VM instances

  2. בוחרים את המכונות להפעלה מחדש.

  3. לוחצים על התחלה / המשך.

  4. מציינים מפתחות הצפנה לכל אחד מהדיסקים המוצפנים שמצורפים למופעים, ואז לוחצים על התחלה.

gcloud

כדי להפעיל מחדש מכונה אחת או יותר שמשתמשות בדיסקים מוצפנים באותו אזור, משתמשים בפקודה gcloud compute instances start עם הדגל --csek-key-file. אם משתמשים במפתח שעטוף ב-RSA, צריך להשתמש בפקודה gcloud beta compute instances start עם הדגל --csek-key-file:

gcloud compute instances start INSTANCE_NAMES \
    --csek-key-file=ENCRYPTION_KEY_FILE \
    --zone=ZONE

מחליפים את מה שכתוב בשדות הבאים:

  • INSTANCE_NAMES: רשימה של שמות מופרדים ברווחים של מופעים – לדוגמה, instance-01 instance-02 instance-03.

  • ENCRYPTION_KEY_FILE: הנתיב היחסי לקובץ ה-JSON שמכיל את מפתח הצפנה מטעם הלקוח (CSEK). אפשר להפעיל מחדש כמה מכונות בו-זמנית רק אם המכונות משתמשות באותו מפתח הצפנה מטעם הלקוח (CSEK). הפורמט של הקובץ מתואר במאמר בנושא פורמט של קובץ מפתח.

  • ZONE: האזור שבו נמצאים המופעים.

המשך

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	computepb "cloud.google.com/go/compute/apiv1/computepb"
	"google.golang.org/protobuf/proto"
)

// startInstanceWithEncKey starts a stopped Google Compute Engine instance (with encrypted disks).
func startInstanceWithEncKey(w io.Writer, projectID, zone, instanceName, key string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// key := "your_encryption_key"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	instanceReq := &computepb.GetInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	instance, err := instancesClient.Get(ctx, instanceReq)
	if err != nil {
		return fmt.Errorf("unable to get instance: %w", err)
	}

	req := &computepb.StartWithEncryptionKeyInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
		InstancesStartWithEncryptionKeyRequestResource: &computepb.InstancesStartWithEncryptionKeyRequest{
			Disks: []*computepb.CustomerEncryptionKeyProtectedDisk{
				{
					Source: proto.String(instance.GetDisks()[0].GetSource()),
					DiskEncryptionKey: &computepb.CustomerEncryptionKey{
						RawKey: proto.String(key),
					},
				},
			},
		},
	}

	op, err := instancesClient.StartWithEncryptionKey(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to start instance with encryption key: %w", err)
	}

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

	fmt.Fprintf(w, "Instance with encryption key started\n")

	return nil
}

Java


import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.compute.v1.CustomerEncryptionKey;
import com.google.cloud.compute.v1.CustomerEncryptionKeyProtectedDisk;
import com.google.cloud.compute.v1.GetInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.InstancesStartWithEncryptionKeyRequest;
import com.google.cloud.compute.v1.Operation;
import com.google.cloud.compute.v1.Operation.Status;
import com.google.cloud.compute.v1.StartWithEncryptionKeyInstanceRequest;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class StartEncryptedInstance {

  public static void main(String[] args)
      throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    /* project: project ID or project number of the Cloud project your instance belongs to.
       zone: name of the zone your instance belongs to.
       instanceName: name of the instance your want to start.
       key: bytes object representing a raw base64 encoded key to your machines boot disk.
            For more information about disk encryption see:
            https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications
     */
    String project = "your-project-id";
    String zone = "zone-name";
    String instanceName = "instance-name";
    String key = "raw-key";

    startEncryptedInstance(project, zone, instanceName, key);
  }

  // Starts a stopped Google Compute Engine instance (with encrypted disks).
  public static void startEncryptedInstance(String project, String zone, String instanceName,
      String key)
      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()) {

      GetInstanceRequest getInstanceRequest = GetInstanceRequest.newBuilder()
          .setProject(project)
          .setZone(zone)
          .setInstance(instanceName).build();

      Instance instance = instancesClient.get(getInstanceRequest);

      // Prepare the information about disk encryption.
      CustomerEncryptionKeyProtectedDisk protectedDisk = CustomerEncryptionKeyProtectedDisk
          .newBuilder()
          /* Use raw_key to send over the key to unlock the disk
             To use a key stored in KMS, you need to provide:
             `kms_key_name` and `kms_key_service_account`
           */
          .setDiskEncryptionKey(CustomerEncryptionKey.newBuilder()
              .setRawKey(key).build())
          .setSource(instance.getDisks(0).getSource())
          .build();

      InstancesStartWithEncryptionKeyRequest startWithEncryptionKeyRequest =
          InstancesStartWithEncryptionKeyRequest.newBuilder()
              .addDisks(protectedDisk).build();

      StartWithEncryptionKeyInstanceRequest encryptionKeyInstanceRequest =
          StartWithEncryptionKeyInstanceRequest.newBuilder()
              .setProject(project)
              .setZone(zone)
              .setInstance(instanceName)
              .setInstancesStartWithEncryptionKeyRequestResource(startWithEncryptionKeyRequest)
              .build();

      OperationFuture<Operation, Operation> operation = instancesClient.startWithEncryptionKeyAsync(
          encryptionKeyInstanceRequest);
      Operation response = operation.get(3, TimeUnit.MINUTES);

      if (response.getStatus() == Status.DONE) {
        System.out.println("Encrypted instance started successfully ! ");
      }
    }
  }

}

Node.js

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

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

async function startInstanceWithEncryptionKey() {
  const instancesClient = new compute.InstancesClient();

  const [instance] = await instancesClient.get({
    project: projectId,
    zone,
    instance: instanceName,
  });

  const [response] = await instancesClient.startWithEncryptionKey({
    project: projectId,
    zone,
    instance: instanceName,
    instancesStartWithEncryptionKeyRequestResource: {
      disks: [
        {
          source: instance.disks[0].source,
          diskEncryptionKey: {
            rawKey: key,
          },
        },
      ],
    },
  });
  let operation = response.latestResponse;
  const operationsClient = new compute.ZoneOperationsClient();

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

  console.log('Instance with encryption key started.');
}

startInstanceWithEncryptionKey();

PHP

use Google\Cloud\Compute\V1\Client\InstancesClient;
use Google\Cloud\Compute\V1\CustomerEncryptionKey;
use Google\Cloud\Compute\V1\CustomerEncryptionKeyProtectedDisk;
use Google\Cloud\Compute\V1\GetInstanceRequest;
use Google\Cloud\Compute\V1\InstancesStartWithEncryptionKeyRequest;
use Google\Cloud\Compute\V1\StartWithEncryptionKeyInstanceRequest;

/**
 * Starts a stopped Google Compute Engine instance (with encrypted disks).
 *
 * @param string $projectId Project ID or project number of the Cloud project your instance belongs to.
 * @param string $zone Name of the zone your instance belongs to.
 * @param string $instanceName Name of the instance you want to stop.
 * @param string $key Bytes object representing a raw base64 encoded key to your instance's boot disk.
 *                    For more information about disk encryption see:
 *                    https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications
 *
 * @throws \Google\ApiCore\ApiException if the remote call fails.
 * @throws \Google\ApiCore\ValidationException if local error occurs before remote call.
 */
function start_instance_with_encryption_key(
    string $projectId,
    string $zone,
    string $instanceName,
    string $key
) {
    // Initiate the InstancesClient.
    $instancesClient = new InstancesClient();

    // Get data about the instance.
    $request = (new GetInstanceRequest())
        ->setInstance($instanceName)
        ->setProject($projectId)
        ->setZone($zone);
    $instanceData = $instancesClient->get($request);

    // Use `setRawKey` to send over the key to unlock the disk
    // To use a key stored in KMS, you need to use `setKmsKeyName` and `setKmsKeyServiceAccount`
    $customerEncryptionKey = (new CustomerEncryptionKey())
        ->setRawKey($key);

    /** @var \Google\Cloud\Compute\V1\AttachedDisk */
    $disk = $instanceData->getDisks()[0];

    // Prepare the information about disk encryption.
    $diskData = (new CustomerEncryptionKeyProtectedDisk())
        ->setSource($disk->getSource())
        ->setDiskEncryptionKey($customerEncryptionKey);

    // Set request with one disk.
    $instancesStartWithEncryptionKeyRequest = (new InstancesStartWithEncryptionKeyRequest())
        ->setDisks(array($diskData));

    // Start the instance with encrypted disk.
    $request2 = (new StartWithEncryptionKeyInstanceRequest())
        ->setInstance($instanceName)
        ->setInstancesStartWithEncryptionKeyRequestResource($instancesStartWithEncryptionKeyRequest)
        ->setProject($projectId)
        ->setZone($zone);
    $operation = $instancesClient->startWithEncryptionKey($request2);

    // Wait for the operation to complete.
    $operation->pollUntilComplete();
    if ($operation->operationSucceeded()) {
        printf('Instance %s started successfully' . PHP_EOL, $instanceName);
    } else {
        $error = $operation->getError();
        printf('Starting instance failed: %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 start_instance_with_encryption_key(
    project_id: str, zone: str, instance_name: str, key: bytes
) -> None:
    """
    Starts a stopped Google Compute Engine instance (with encrypted disks).
    Args:
        project_id: project ID or project number of the Cloud project your instance belongs to.
        zone: name of the zone your instance belongs to.
        instance_name: name of the instance your want to start.
        key: bytes object representing a raw base64 encoded key to your machines boot disk.
            For more information about disk encryption see:
            https://cloud.google.com/compute/docs/disks/customer-supplied-encryption#specifications
    """
    instance_client = compute_v1.InstancesClient()

    instance_data = instance_client.get(
        project=project_id, zone=zone, instance=instance_name
    )

    # Prepare the information about disk encryption
    disk_data = compute_v1.CustomerEncryptionKeyProtectedDisk()
    disk_data.source = instance_data.disks[0].source
    disk_data.disk_encryption_key = compute_v1.CustomerEncryptionKey()
    # Use raw_key to send over the key to unlock the disk
    # To use a key stored in KMS, you need to provide `kms_key_name` and `kms_key_service_account`
    disk_data.disk_encryption_key.raw_key = key
    enc_data = compute_v1.InstancesStartWithEncryptionKeyRequest()
    enc_data.disks = [disk_data]

    operation = instance_client.start_with_encryption_key(
        project=project_id,
        zone=zone,
        instance=instance_name,
        instances_start_with_encryption_key_request_resource=enc_data,
    )

    wait_for_extended_operation(operation, "instance start (with encrypted disk)")

REST

כדי להפעיל מחדש מכונה שמשתמשת בדיסקים מוצפנים, שולחים בקשת POST אל ה-method‏ instances.startWithEncryptionKey:

POST  https://compute.s3nsapis.fr/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/startWithEncryptionKey

{
  "disks": [
    {
      "source": "DISK_URL",
      "diskEncryptionKey": {
        "ENCRYPTION_TYPE": "ENCRYPTION_KEY"
      }
    }
  ]
}

מחליפים את מה שכתוב בשדות הבאים:

  • PROJECT_ID: מזהה הפרויקט שבו נמצא המופע.

  • ZONE: האזור שבו נמצאת המכונה.

  • INSTANCE_NAME: השם של המכונה.

  • DISK_URL: כתובת ה-URL של המשאב שמתאימה לשם המשאב המלא של הדיסק המצורף שמוצפן באמצעות מפתח הצפנה מטעם הלקוח (CSEK).

  • ENCRYPTION_TYPE: סוג ההצפנה של הדיסק שבו אתם משתמשים, שיכול להיות אחד מהסוגים הבאים: rawKey,‏ kmsKeyName או rsaEncryptedKey. אם משתמשים בסוג rsaEncryptedKey, צריך לשלוח בקשת POST ל-method‏ beta.instances.startWithEncryptionKey.

  • ENCRYPTION_KEY: מפתח ההצפנה שמשמש להצפנת דיסקי האחסון המתמיד שמצורפים למופע. המפתחות rawKey או rsaEncryptedKey חייבים להיות בקידוד base64. בנוסף, כדי להכין מפתח rsaEncryptedKey, אפשר לעיין במאמר בנושא עטיפת מפתח RSA.

המאמרים הבאים