Google云使用Pythonapi创建实例时如何启动服务?

Google cloud how to start service when creating instance using Python api?

我在创建实例并使用 Python Google Cloud 的 api.

启动它们时遇到了很多麻烦

基本上我首先创建了所有 VM 并设置了服务。然后,一旦一切正常,我就停止了虚拟机并创建了 Image,这样我就可以使用图像轻松创建实例。

[编辑] 我觉得补充一点很好:

这是我的 Python 脚本:

import googleapiclient.discovery
import argparse
import os
import time

backend_script = """
#! /bin/bash
cd /mse-tsm-cloudsys-lab1/api/
sudo npm install
sudo npx knex migrate:latest
sudo npx knex seed:run
sudo npm run start
"""

frontend_script = """
#! /bin/bash
cd /mse-tsm-cloudsys-lab1/app/
sudo npm install
sudo npm run build
sudo npm run start
"""

def create_instance(compute, project, zone, name, image, machine, ip, ip_public, tags=[], metadata=[]):
    config = {
        'name': name,
        'machineType': "zones/%s/machineTypes/%s" % (zone, machine),
        'disks': [
            {
                'initializeParams': {
                    "sourceImage": image
                },
                "boot": True
            }
        ],
        'tags': {
            "items": tags
        },
        "networkInterfaces": [
            {
                'network': 'global/networks/default',
                'networkIP': ip,
                'accessConfigs': [
                    {
                        'type': 'ONE_TO_ONE_NAT',
                        'name': 'External NAT',
                        'natIP': ip_public
                    }
                ]
            }
        ],
        "metadata": {
            "items": metadata
        }
    }
    return compute.instances().insert(
        project=project,
        zone=zone,
        body=config).execute()

def delete_instance(compute, project, zone, name):
    return compute.instances().delete(
        project=project,
        zone=zone,
        instance=name).execute()

def list_instances(compute, project, zone):
    result = compute.instances().list(project=project, zone=zone).execute()
    return result['items'] if 'items' in result else None

def wait_for_operation(compute, project, zone, operation):
    print('Waiting for operation to finish...')
    while True:
        result = compute.zoneOperations().get(
            project=project,
            zone=zone,
            operation=operation).execute()

        if result['status'] == 'DONE':
            print("done.")
            if 'error' in result:
                raise Exception(result['error'])
            return result

        time.sleep(1)

def main(mode, project, zone, wait=True):
    compute = googleapiclient.discovery.build('compute', 'v1')

    if(mode == 'list'):
        instances = list_instances(compute, project, zone)

        print('Instances in project %s and zone %s:' % (project, zone))
        for instance in instances:
            print(' - ' + instance['name'])

        return

    print("Creating Database")
    instance_name = "postgres-lab1"
    image = "projects/tsm-cloudsys-vial/global/images/image-postgres-lab1"
    machine = "e2-micro"
    ip = "10.132.0.2"
    ip_public = "34.79.195.77"
    tags = ["postgres-lab1"]
    operation1 = create_instance(compute, project, zone, instance_name, image, machine, ip, ip_public)

    print("Creating Backend")
    instance_name = "backend-lab1"
    image = "projects/tsm-cloudsys-vial/global/images/image-backend-lab1"
    machine = "e2-micro"
    ip = "10.132.0.4"
    ip_public = "34.79.111.217"
    metadata = [{
        "key": "startup-script",
        "value": backend_script
    }]
    tags = ["backend-lab1","http-server","https-server"]
    operation2 = create_instance(compute, project, zone, instance_name, image, machine, ip, ip_public, metadata=metadata)

    print("Creating Frontend")
    instance_name = "frontend-lab1"
    image = "projects/tsm-cloudsys-vial/global/images/image-frontend-lab1"
    machine = "e2-micro"
    ip = "10.132.0.3"
    ip_public = "35.187.109.153"
    metadata = [{
        "key": "startup-script",
        "value": frontend_script
    }]
    tags = ["frontend-lab1","http-server","https-server"]
    operation3 = create_instance(compute, project, zone, instance_name, image, machine, ip, ip_public, tags, metadata=metadata)

    print("Waiting for VMs to come online")
    wait_for_operation(compute, project, zone, operation1['name'])
    wait_for_operation(compute, project, zone, operation2['name'])
    wait_for_operation(compute, project, zone, operation3['name'])

    instances = list_instances(compute, project, zone)

    print('Instances in project %s and zone %s:' % (project, zone))
    for instance in instances:
        print(' - ' + instance['name'])

    if wait:
        input()

    print("Deleting DB")
    operation1 = delete_instance(compute, project, zone, "postgres-lab1")
    print("Deleting Backend")
    operation2 = delete_instance(compute, project, zone, "backend-lab1")
    print("Deleting Frontend")
    operation3 = delete_instance(compute, project, zone, "frontend-lab1")
    wait_for_operation(compute, project, zone, operation1['name'])
    wait_for_operation(compute, project, zone, operation2['name'])
    wait_for_operation(compute, project, zone, operation3['name'])

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('--mode', help='Wanted mode', default='list')
    parser.add_argument('project_id', help='Your Google Cloud project ID.')
    parser.add_argument(
        '--zone',
        default='europe-west1-b',
        help='Compute Engine zone to deploy to.')

    args = parser.parse_args()

    main(args.mode, args.project_id, args.zone)

创建了 3 个实例,运行,我可以 ping 通所有实例。 (是的,一个已关闭,因为我正在尝试重新启动它) 但我有两个主要问题:

  1. 无法在 Google 云仪表板上使用 SSH 连接到实例,这需要很长时间...
  2. 我觉得我的 startup-script 不正确,因为即使这 3 个实例是 运行,我也无法像以前手动创建它们时那样访问它们。例如 frontend-lab1 应该在端口 3000 上响应,但当我使用我的脚本创建它时却不是

我主要关心的是问题 2,因为我认为它会解决问题 1。有人可以帮我解决 startup-script 吗?

[编辑2] 这是日志:

ct  6 19:24:23 frontend-lab1 systemd[1]: Starting Google Compute Engine Startup Scripts...
Oct  6 19:24:23 frontend-lab1 google_metadata_script_runner[795]: 2021/10/06 19:24:23 logging client: rpc error: code = Unauthenticated desc = transport: metadata: GCE metadata "instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Flogging.write" not defined
Oct  6 19:24:37 frontend-lab1 systemd[1]: systemd-fsckd.service: Succeeded.
Oct  6 19:24:51 frontend-lab1 systemd[1]: systemd-hostnamed.service: Succeeded.
Oct  6 19:25:21 frontend-lab1 GCEGuestAgent[539]: 2021-10-06T19:25:21.4654Z GCEGuestAgent Info: Removing user jeromevialhes.
Oct  6 19:25:22 frontend-lab1 google_guest_agent[539]: 2021/10/06 19:25:22 logging client: rpc error: code = Unauthenticated desc = transport: metadata: GCE metadata "instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Flogging.write" not defined
Oct  6 19:25:22 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:22 GCEMetadataScripts: startup-script: /tmp/metadata-scripts111777770/startup-script: line 3: cd: /mse-tsm-cloudsys-lab1/app/: No such file or directory
Oct  6 19:25:23 frontend-lab1 google_metadata_script_runner[795]: 2021/10/06 19:25:23 logging client: rpc error: code = Unauthenticated desc = transport: metadata: GCE metadata "instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Flogging.write" not defined
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: npm WARN saveError ENOENT: no such file or directory, open '/package.json'
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: npm WARN enoent ENOENT: no such file or directory, open '/package.json'
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: npm WARN !invalid#2 No description
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: npm WARN !invalid#2 No repository field.
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: npm WARN !invalid#2 No README data
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: npm WARN !invalid#2 No license field.
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: 
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: up to date in 0.489s
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: found 0 vulnerabilities
Oct  6 19:25:27 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:27 GCEMetadataScripts: startup-script: 
Oct  6 19:25:27 frontend-lab1 google_metadata_script_runner[795]: 2021/10/06 19:25:27 logging client: rpc error: code = Unauthenticated desc = transport: metadata: GCE metadata "instance/service-accounts/default/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Flogging.write" not defined
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! code ENOENT
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! syscall open
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! path /package.json
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! errno -2
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! enoent ENOENT: no such file or directory, open '/package.json'
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! enoent This is related to npm not being able to find a file.
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! enoent 
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: 
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR! A complete log of this run can be found in:
Oct  6 19:25:28 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:28 GCEMetadataScripts: startup-script: npm ERR!     /root/.npm/_logs/2021-10-06T19_25_28_453Z-debug.log
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! code ENOENT
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! syscall open
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! path /package.json
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! errno -2
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! enoent ENOENT: no such file or directory, open '/package.json'
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! enoent This is related to npm not being able to find a file.
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! enoent 
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: 
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR! A complete log of this run can be found in:
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script: npm ERR!     /root/.npm/_logs/2021-10-06T19_25_29_171Z-debug.log
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: startup-script exit status 254
Oct  6 19:25:29 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:29 GCEMetadataScripts: Finished running startup scripts.
Oct  6 19:25:29 frontend-lab1 systemd[1]: google-startup-scripts.service: Succeeded.
Oct  6 19:25:29 frontend-lab1 systemd[1]: Finished Google Compute Engine Startup Scripts.

但是你可以看到存储库存在:

jeromevialhes@frontend-lab1:~$ ls
mse-tsm-cloudsys-lab1

查看问题中包含的日志,您的 custom 图像似乎有问题。在日志文件的第 7 行,它警告找不到目录“/mse-tsm-cloudsys-labl1/app/”:

Oct  6 19:25:22 frontend-lab1 GCEMetadataScripts[795]: 2021/10/06 19:25:22 GCEMetadataScripts: startup-script: /tmp/metadata-scripts111777770/startup-script: line 3: cd: /mse-tsm-cloudsys-lab1/app/: No such file or directory

如果此目录用于包含您的应用程序文件,这将导致与 NPM 相关的后续错误无法找到文件,例如 package.json 和其他属于您的应用程序的文件。

您应该确认应用程序路径是否正确或图像是否正确创建。您可以按照 this guide about creating custom images from your existing VM instances, and use the Node.js and Python 指南来确保您遵循的是正确的步骤。