使用 Python 版 Cloud 客户端库

本文档演示了如何将 Python 版 Cloud 客户端库用于 Compute Engine。其中介绍了如何为请求授权以及如何创建、列出和删除实例。本练习将讨论如何使用 google-api-python-client 库访问 Compute Engine 资源。如果您已正确地为示例授权,则可在本地机器或某个虚拟机实例上运行此示例。

如需查看可用客户端库(包括其他 Google 客户端库和第三方开源库)的完整列表,请参阅“客户端库”页面

如需查看包含所有必要导入的完整代码示例,请访问 GoogleCloudPlatform/python-docs-samples GitHub 页面。

目标

  • 使用 oauth2client 库进行 OAuth 2.0 授权
  • 使用 google-python-client 库创建实例
  • 使用 google-python-client 库列出实例
  • 使用 google-python-client 库删除实例

费用

本教程使用 Google Cloud 的收费组件,包括 Compute Engine。

Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册一个新帐号

  2. 在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。

    转到项目选择器页面

  3. 确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能

  4. 安装 Cloud SDK
  5. 安装 SDK 后,运行 gcloud auth application-default login
  6. 安装 google-api-python-client 库。您通常可运行:
    $ pip install --upgrade google-api-python-client

    如需详细了解如何安装此库,请参阅安装说明。您还需要具备 Python 2.7 或 3.3 及以上版本才能运行 Python 版 Cloud 客户端库。

  7. 启用 Cloud Storage API。
  8. 创建一个 Cloud Storage 存储分区并记下存储分区名称以供稍后使用。

向请求授权

此示例采用 OAuth 2.0 授权。许多方法可以通过 OAuth 2.0 对请求进行授权,但对于此示例,请使用应用默认凭据。这样做的好处是:如果您在本地工作站上运行该示例,则可以通过 gcloud 工具重复使用这些凭据;或者,如果您在 Compute Engine 或 App Engine 中运行该示例,则可以通过服务帐号重复使用这些凭据。您应该已在准备工作部分中安装 gcloud 工具并向此工具授权。

Google API 客户端库会自动提供应用默认凭据。您只需构建并初始化 API 即可:

compute = googleapiclient.discovery.build('compute', 'v1')

例如,以下代码段是本示例的主要方法,它构建并初始化 API,然后进行一些调用以创建、列出和删除实例:

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

    print('Creating instance.')

    operation = create_instance(compute, project, zone, instance_name, bucket)
    wait_for_operation(compute, project, zone, operation['name'])

    instances = list_instances(compute, project, zone)

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

    print("""
Instance created.
It will take a minute or two for the instance to complete work.
Check this URL: http://storage.googleapis.com/{}/output.png
Once the image is uploaded press enter to delete the instance.
""".format(bucket))

    if wait:
        input()

    print('Deleting instance.')

    operation = delete_instance(compute, project, zone, instance_name)
    wait_for_operation(compute, project, zone, operation['name'])

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('project_id', help='Your Google Cloud project ID.')
    parser.add_argument(
        'bucket_name', help='Your Google Cloud Storage bucket name.')
    parser.add_argument(
        '--zone',
        default='us-central1-f',
        help='Compute Engine zone to deploy to.')
    parser.add_argument(
        '--name', default='demo-instance', help='New instance name.')

    args = parser.parse_args()

    main(args.project_id, args.bucket_name, args.zone, args.name)

列出实例

使用 Python 版 Cloud 客户端库,您可以通过 compute.instances().list 方法列出实例。您需要提供项目 ID 以及要列出其实例的地区。例如:

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

添加实例

如需添加实例,请使用 instances().insert 方法并指定该新实例的属性。这些属性是在请求正文中指定的;如需详细了解每个属性,请参阅 instances.insert 的 API 参考

创建新实例时,您的请求至少必须提供以下属性的值:

  • 实例名称
  • 根级永久性磁盘
  • 机器类型
  • 地区
  • 网络接口

本示例会在您所选的地区中启动一个具有以下属性的实例:

  • 机器类型:e2-standard-2
  • 根级永久性磁盘:基于最新 Debian 8 映像的新永久性磁盘
  • Compute Engine 默认服务帐号的权限范围如下:

    • https://www.googleapis.com/auth/devstorage.read_write,因此实例可以对 Cloud Storage 中的文件执行读取和写入操作
    • https://www.googleapis.com/auth/logging.write,因此实例日志可以上传到 Cloud Logging
  • 元数据,用于指定实例在启动时应执行的命令

def create_instance(compute, project, zone, name, bucket):
    # Get the latest Debian Jessie image.
    image_response = compute.images().getFromFamily(
        project='debian-cloud', family='debian-9').execute()
    source_disk_image = image_response['selfLink']

    # Configure the machine
    machine_type = "zones/%s/machineTypes/n1-standard-1" % zone
    startup_script = open(
        os.path.join(
            os.path.dirname(__file__), 'startup-script.sh'), 'r').read()
    image_url = "http://storage.googleapis.com/gce-demo-input/photo.jpg"
    image_caption = "Ready for dessert?"

    config = {
        'name': name,
        'machineType': machine_type,

        # Specify the boot disk and the image to use as a source.
        'disks': [
            {
                'boot': True,
                'autoDelete': True,
                'initializeParams': {
                    'sourceImage': source_disk_image,
                }
            }
        ],

        # Specify a network interface with NAT to access the public
        # internet.
        'networkInterfaces': [{
            'network': 'global/networks/default',
            'accessConfigs': [
                {'type': 'ONE_TO_ONE_NAT', 'name': 'External NAT'}
            ]
        }],

        # Allow the instance to access cloud storage and logging.
        'serviceAccounts': [{
            'email': 'default',
            'scopes': [
                'https://www.googleapis.com/auth/devstorage.read_write',
                'https://www.googleapis.com/auth/logging.write'
            ]
        }],

        # Metadata is readable from the instance and allows you to
        # pass configuration from deployment scripts to instances.
        'metadata': {
            'items': [{
                # Startup script is automatically executed by the
                # instance upon startup.
                'key': 'startup-script',
                'value': startup_script
            }, {
                'key': 'url',
                'value': image_url
            }, {
                'key': 'text',
                'value': image_caption
            }, {
                'key': 'bucket',
                'value': bucket
            }]
        }
    }

    return compute.instances().insert(
        project=project,
        zone=zone,
        body=config).execute()

以下各部分介绍了实例创建参数。

根级永久性磁盘

所有实例必须从根级永久性磁盘启动。根级永久性磁盘包含启动实例所需的所有必要文件。创建根级永久性磁盘时,您必须选择要应用于该磁盘的公共映像或自定义映像。在上面的示例中,在创建实例的同时,您创建了一个基于 Debian 8 的新的根级永久性磁盘。但是,您也可以先创建一个磁盘,然后再将其挂接到实例。

实例元数据

在创建实例时,您可能想要包含实例元数据,例如启动脚本、配置变量和 SSH 密钥。在上述示例中,您在请求正文中使用了 metadata 字段指定实例的启动脚本,并以键值对的形式指定了一些配置变量。下面所列的启动脚本显示了如何读取这些变量并使用它们将文本应用于映像以及上传到 Cloud Storage

apt-get update
apt-get -y install imagemagick

# Use the metadata server to get the configuration specified during
# instance creation. Read more about metadata here:
# https://cloud.google.com/compute/docs/metadata#querying
IMAGE_URL=$(curl http://metadata/computeMetadata/v1/instance/attributes/url -H "Metadata-Flavor: Google")
TEXT=$(curl http://metadata/computeMetadata/v1/instance/attributes/text -H "Metadata-Flavor: Google")
CS_BUCKET=$(curl http://metadata/computeMetadata/v1/instance/attributes/bucket -H "Metadata-Flavor: Google")

mkdir image-output
cd image-output
wget $IMAGE_URL
convert * -pointsize 30 -fill white -stroke black -gravity center -annotate +10+40 "$TEXT" output.png

# Create a Google Cloud Storage bucket.
gsutil mb gs://$CS_BUCKET

# Store the image in the Google Cloud Storage bucket and allow all users
# to read it.
gsutil cp -a public-read output.png gs://$CS_BUCKET/output.png

删除实例

要删除某个实例,您需要调用 instances().delete 方法并提供要删除的实例的名称、地区和项目 ID。由于您为启动磁盘设置了 autoDelete 参数,因此在删除实例时启动磁盘也会一并删除。此设置默认关闭,但在磁盘和实例要一起删除使用情况下非常有用。

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

运行示例

您可以下载代码并在命令行上运行,从而运行完整的示例。请务必下载 create_instance.py 文件和 startup-script.sh 文件。如需运行该示例,请执行以下操作:

python create_instance.py --name [INSTANCE_NAME] --zone [ZONE] [PROJECT_ID] [CLOUD_STORAGE_BUCKET]

其中:

  • [INSTANCE_NAME] 是要创建的实例的名称。
  • [ZONE] 是此请求所需的地区。
  • [PROJECT_ID] 是我们的项目 ID。
  • [CLOUD_STORAGE_BUCKET] 是您最初设置的存储分区的名称,但不含 gs:// 前缀。

例如:

python python-example.py --name example-instance --zone us-central1-a example-project my-gcs-bucket

等待操作完成

要求 Compute Engine API 修改资源(如实例)的请求会立即返回响应,确认您的请求。通过确认,您可以检查所请求操作的状态。操作需要几分钟就能完成,通常等待操作完成再继续会更容易。此辅助方法会等到操作完成后再返回:

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)

清理

为避免因本教程中使用的资源而导致系统向您的 Google Cloud Platform 帐号收取费用,请执行以下操作:

删除您的 Cloud Storage 存储分区

如需删除 Cloud Storage 存储分区,请执行以下操作:

  1. 在 Cloud Console 中,转到 Cloud Storage 浏览器页面。

    转到“Cloud Storage 浏览器”页面

  2. 点击要删除的存储分区对应的复选框。
  3. 如需删除存储分区,请点击删除

后续步骤

  • 下载并查看完整的代码示例。 完整的示例中包含了一个同时使用所有这些方法的小例子。您可以根据自己的需求随意下载、更改并运行该示例。
  • 查看 API 参考文档以了解如何通过 API 执行其他任务。