Расписание для остановки и запуска экземпляра на Google Cloud Platform - Cloud Scheduler это облачная функция

У меня следующая потребность. Я хотел бы каждый день в 5:00 перезапускать свой экземпляр, поэтому я прочитал, что лучший способ автоматизировать его - использовать облачный планировщик и облачную функцию, но я не знаю об этих двух функциях GCP.

Я создал два расписания в Cloud Scheduler, где мой экземпляр виртуальной машины STOP в 5:00 утра, а другой - START в 5:10 утра, но я не знаю, как чтобы продолжить в Cloud Function, чтобы завершить мой процесс.

Может ли кто-нибудь помочь мне с этим? обнимаю всех!

Посмотрите, как у меня журнал ошибок проекта при попытке реализовать

ОШИБКА

{ "jobName": "projects/my-project/locations/us-central1/jobs/Stop", "@type": "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished", "status": "INTERNAL", "url": "https://us-central1-my-project.cloudfunctions.net/power/stop?zone=us-central1-a&instance=my-instance", "targetType": "HTTP" }

###############

    {
insertId: "1klx7n3g18eq5zs"
jsonPayload: {
jobName: "projects/my-project/locations/us-central1/jobs/Stop"
@type: "type.googleapis.com/google.cloud.scheduler.logging.AttemptFinished"
status: "INTERNAL"
url: "https://us-central1-my-project.cloudfunctions.net/power/stop?zone=us-central1-a&instance=my-instance"
targetType: "HTTP"
}
httpRequest: {
status: 500
}
resource: {
type: "cloud_scheduler_job"
labels: {
location: "us-central1"
project_id: "my-project"
job_id: "Stop"
}
}
timestamp: "2020-08-07T08:00:06.896367090Z"
severity: "ERROR"
logName: "projects/my-project/logs/cloudscheduler.googleapis.com%2Fexecutions"
receiveTimestamp: "2020-08-07T08:00:06.896367090Z"
}

person Jarciano    schedule 28.07.2020    source источник


Ответы (1)


У меня такой же вариант использования в моем проекте, и я использую эту функцию python для запуска и остановки виртуальной машины, моя функция может обрабатывать пути start и stop

from flask import Flask, request, abort
import os
import logging

app = Flask(__name__)


@app.route('/')
@app.route('/<path:path>')
def power(path=None):
    #this libraries are mandatory to reach compute engine api
    from googleapiclient import discovery
    from oauth2client.client import GoogleCredentials


    #the function will take the service account of your function
    credentials = GoogleCredentials.get_application_default()

    #this line is to specify the api that we gonna use, in this case compute engine    
    service = discovery.build('compute', 'v1', credentials=credentials, cache_discovery=False)
    logging.getLogger('googleapiclient.discovery_cache').setLevel(logging.ERROR)

    # Project ID for this request.
    project = yourprojectID  # Update placeholder value.
    zone = request.args.get('zone', None)
    instance = request.args.get('instance', None)

    #call the method to start or stop the instance
    if (request.path == "/stop"):
        req = service.instances().stop(project=project, zone=zone, instance=instance)

    elif (request.path == "/start"):
        req = service.instances().start(project=project, zone=zone, instance=instance)
    else:
        abort(418)
    #execute the command
    response = req.execute()

    print(response)
    return ("OK")


if __name__ == '__main__':
    app.run(port=3000, debug=True)

файл requirements.txt

google-api-python-client
oauth2client
flask

Конфигурация планировщика

  1. Создайте учетную запись службы с помощью разрешение functions.invoker в вашей функции
  2. Создать новое задание облачного планировщика
  3. Укажите частоту в формате cron.
  4. В качестве целевого типа укажите HTTP.
  5. Добавьте URL-адрес вашей облачной функции и метода, как всегда.
  6. Выберите OIDC токена из раскрывающегося списка Auth header.
  7. Добавьте адрес электронной почты учетной записи службы в текстовое поле Учетная запись службы.
  8. В audience field вам нужно только написать URL-адрес функции без каких-либо дополнительных параметров

В облачном планировщике я нажимаю свою функцию, используя эти URL-адреса

https://us-central1-yourprojectID.cloudfunctions.net/power/stop?zone=us-central1-a&instance=instance-1

https://us-central1-yourprojectID.cloudfunctions.net/power/stop?zone=us-central1-a&instance=instance-1

и я использовал эту аудиторию

https://us-central1-yourprojectID.cloudfunctions.net/power

замените yourprojectID в коде и в URL

us-central1 - это область, в которой расположена моя функция, power - это имя моей функции, us-central1-a - это зона, в которой находится мой экземпляр, а instance-1 - это имя моего экземпляра

обновление для java

Облачные функции поддерживают java11 и maven, но это бета-версия

сначала вам нужны эти зависимости, добавьте следующие строки в свой файл pom.xml:

    <dependency>
      <groupId>com.google.apis</groupId>
      <artifactId>google-api-services-compute</artifactId>
      <version>beta-rev20200629-1.30.10</version>
    </dependency>
    <dependency>
      <groupId>com.google.api-client</groupId>
      <artifactId>google-api-client</artifactId>
      <version>1.30.10</version>
    </dependency>

Облачная функция для ЗАПУСКА ВМ

package com.example;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.BufferedWriter;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Operation;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;

public class Example implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception, IOException, GeneralSecurityException {
    
    
    // Project ID for this request.
    String project = "my-project"; // TODO: Update placeholder value.

    // The name of the zone for this request.
    String zone = "my-zone"; // TODO: Update placeholder value.

    // Name of the instance resource to start.
    String instance = "my-instance"; // TODO: Update placeholder value.

    Compute computeService = createComputeService();

    // you can change the method start to stop 
    Compute.Instances.Start request = computeService.instances().start(project, zone, instance);
    
    Operation xresponse = xrequest.execute();

    // TODO: Change code below to process the `response` object:
    System.out.println(xresponse);

    BufferedWriter writer = response.getWriter();
    writer.write("Done");


  }

  public static Compute createComputeService() throws IOException, GeneralSecurityException {
    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

    GoogleCredential credential = GoogleCredential.getApplicationDefault();
    if (credential.createScopedRequired()) {
      credential =
          credential.createScoped(Arrays.asList("https://www.googleapis.com/auth/cloud-platform"));
    }

    return new Compute.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("Google-ComputeSample/0.1")
        .build();
  }

}

Дополнительную информацию можно найти в документе. в этом документе приведены несколько примеров на разных языках программирования.

person Jan Hernandez    schedule 28.07.2020
comment
JAHernández спасибо за подсказку, я проанализирую ваш ответ, есть ли у кого-нибудь что-нибудь на java? - person Jarciano; 28.07.2020
comment
в этом документе вы можете узнать, как вызвать api движка приложения, используя java cloud.google.com/compute/docs/reference/rest/beta/instances/ - person Jan Hernandez; 28.07.2020
comment
@ JAHernández спасибо, быстро работали поздравления, я постараюсь реализовать любые сомнения обратно. - person Jarciano; 28.07.2020
comment
@ JAHernández Я обновил свой вопрос, добавив журнал и файлы - person Jarciano; 30.07.2020
comment
@Jarciano, как указано в вашем журнале ошибок, необходимо переименовать переменные request & response в service, пожалуйста, проверьте обновленный код в моем ответе, теперь эти переменные называются xrequest & xresponse - person Jan Hernandez; 30.07.2020
comment
@ JAHernández Я обновил свой журнал вопросов после внесения предложенных вами исправлений - person Jarciano; 30.07.2020
comment
@Jarciano, пожалуйста, используйте полный код, который я опубликовал в ответе, я тестировал его в своем проекте и работает без проблем. - person Jan Hernandez; 31.07.2020
comment
@ JAHernández Мне удалось развернуть проект, но я обновил журнал ошибок в тот момент, когда попытался запустить процесс в Cloud Scheduler, это выдает ошибку PERMISSION_DENIED. где нам нужно выпустить? - person Jarciano; 31.07.2020
comment
@Jarciano в этом ответе я опубликовал, как аутентифицировать ваш запрос планировщика, часть планировщика находится в конце ответа. stackoverflow.com/a/62285013/11529321 - person Jan Hernandez; 31.07.2020
comment
Позвольте нам продолжить это обсуждение в чате. - person Jarciano; 31.07.2020
comment
@ JAHernández Не могли бы вы поделиться изображениями того, как это устроено? потому что я считаю, что упускаю одну маленькую деталь. - person Jarciano; 31.07.2020
comment
@Jarciano Target: `HTTP`, URL: https://us-central1-projectID.cloudfunctions.net/poweron, HTTP method: get, Auth header: Add OIDC token, Service account: [email protected] , Audiencie: https://us-central1-projectID.cloudfunctions.net/poweron, в audience field вам нужно только написать URL-адрес функции без каких-либо дополнительных параметров - person Jan Hernandez; 31.07.2020
comment
@ JAHernández Я обновил изображение, чтобы вы могли увидеть, что я получаю. - person Jarciano; 31.07.2020
comment
@Jarciano нужно поставить Auth header: OIDC token, я в чате - person Jan Hernandez; 31.07.2020
comment
@ JAHernández добавить изображение чата из журнала при попытке запустить - person Jarciano; 31.07.2020
comment
@ JAHernández См. Запись журнала функций, нужно ли мне выполнять какие-либо команды на моей виртуальной машине, чтобы принять вызов остановки и запуска? imgur.com/q05mKZP - person Jarciano; 01.08.2020
comment
Привет, @ JAHernández Я обновил свой вопрос, потому что теперь ошибка показывает что-то другое, я считаю, что это некоторая деталь сервера, принимающего вызов функции - person Jarciano; 07.08.2020
comment
@Jarciano, вы можете поделиться журналом выполнения облачной функции? - person Jan Hernandez; 07.08.2020
comment
@ JAHernández А эти журналы будут? imgur.com/pjjwzpe | imgur.com/oZhmbXR - person Jarciano; 07.08.2020
comment
@Jarciano, я рекомендую вам подать заявку в службу поддержки, поскольку я уже упоминал, что это отлично работает в моем продуктивном проекте, и служба поддержки дает больше информации о том, что падает. cloud.google.com/support/docs/issue-trackers - person Jan Hernandez; 07.08.2020