[GCP工具集] 省钱小工具:自动启动抢占型机器

前言

GCP的抢占型(preemptible)机器就类似与AWS的Spot Instance(竞价型机器)。同样的配置,抢占型机器机器能便宜差不多1/3!

但是有一个物理限制:每次开机最长24小时就会被关机。

因此,如果我们有一个小工具能监控这些机器,并且自动启动,岂不美哉?

方式1:使用实例组( Instance Group Manager )

原理:在创建实例组的时候设置 实例数下限 。比如可以设置成 1 . 当这个实例被关闭之后,实例组会 将其删除并重新创建

操作步骤:(因为不是重点, 在此简单写写)

  1. 创建 实例模板

    . 这一步就按照正常的要求创建就好了。

    补充: 如何使用当前实例作为模板?

    回答:先把当前实例做成一个快照(snapshot), 在创建模板的时候, 设置使用相应的快照来创建即可

  2. 创建 实例组

    看了一下相关设定, 正常设置即可。

方式2:自建监控+启动的Python脚本

  1. 安装相应的类库

    pip install -U google-api-python-client

  2. 准备credentials文件

  3. 在你的定时调度任务调用下面的python script

    def start_instance_if_stopped(name=None, ip=None):
       """
       如果目标机器(name or ip)关闭了,将其启动
       :param name:
       :param ip:
       :return:
       """
       credentials = service_account.Credentials.from_service_account_file(
           'your-service-account-file.json',
       )
       compute = googleapiclient.discovery.build(serviceName='compute', version='v1', credentials=credentials)
       project = "your-project-id"
     
       avaiable_zones = ["us-east4-c", "us-east4-a", "us-east4-b"]
     
       for zone in avaiable_zones:
           result = compute.instances().list(project=project, zone=zone).execute()
           instances = result['items'] if 'items' in result else []
     
           for instance in instances:
               cur_name = instance['name']
               cur_ip = instance['networkInterfaces'][0]['networkIP']
               status = instance['status']
               if (name == cur_name or ip == cur_ip) and status != "RUNNING":
                   print("##################", instance)
                   compute.instances().start(project=project, zone=zone, instance=cur_name).execute()
                   # TODO:可以参考这个实现,等待操作完成 https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/compute/api/create_instance.py#L128
                   break
     
    

    注意:在GCP之中, 没有直接列出所有Zone的instance的方法。 zone必须指定。因此如果你的机器在多个zone, 要么简单粗暴直接hardcode, 要么通过下面的参考脚本列出所有的zone

    参考: https://cloud.google.com/compute/docs/reference/rest/v1/zones/list

    from pprint import pprint
     
    from googleapiclient import discovery
    # 注意:下面这个方式我没有试用成功,credentials的使用方法可以参考上面的脚本
    from oauth2client.client import GoogleCredentials
     
    credentials = GoogleCredentials.get_application_default()
     
    service = discovery.build('compute', 'v1', credentials=credentials)
     
    # Project ID for this request.
    project = 'my-project'  # TODO: Update placeholder value.
     
    request = service.zones().list(project=project)
    while request is not None:
       response = request.execute()
     
       for zone in response['items']:
           # TODO: Change code below to process each `zone` resource:
           pprint(zone)
     
       request = service.zones().list_next(previous_request=request, previous_response=response)