您的应用可以使用服务帐号运行自动任务,并与其他 Google Cloud API 交互。允许应用管理自己的 SSH 密钥并连接到实例对自动执行系统管理流程非常有用。本教程介绍了如何配置应用,使其通过 SSH 连接访问您的实例。本教程中的示例应用使用服务帐号和 OS Login 进行 SSH 密钥管理。
本教程中使用的所有代码都托管在 GoogleCloudPlatform/python-docs-samples GitHub 页面上。
目标
本教程介绍了以下任务:
- 创建服务帐号并对其进行配置,以便为连接到您的实例的应用提供 OS Login SSH 访问权限。
- 创建与您的服务帐号关联的实例。
- 在您的实例上配置示例应用,使其使用服务帐号管理其专属的 SSH 密钥并建立 SSH 连接。
- 在服务帐号关联的实例上运行应用。
- 在 Compute Engine 之外运行应用,在此情况下,您必须手动提供服务帐号密钥并指定其他 SSH 参数。
费用
本教程使用 Google Cloud 的收费组件,包括 Compute Engine。
Google Cloud 新用户可能有资格申请免费试用。准备工作
- 登录您的 Google Cloud 帐号。如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
-
在 Google Cloud Console 的项目选择器页面上,选择或创建一个 Google Cloud 项目。
-
确保您的 Cloud 项目已启用结算功能。 了解如何确认您的项目是否已启用结算功能。
-
在您的个人用户帐号中,为您的项目获取以下 IAM 角色:
compute.instanceAdmin.v1
compute.networkAdmin
compute.osAdminLogin
iam.serviceAccountAdmin
iam.serviceAccountKeyAdmin
iam.serviceAccountUser
-
了解如何使用 Cloud Shell 运行
gcloud
命令行工具命令。
创建和配置服务帐号及示例实例
创建一个服务帐号和两个实例供本教程使用。您可以使用服务帐号向应用授予 SSH 访问权限,该应用将通过 SSH 从一个实例连接到另一个实例。
按照以下步骤配置测试环境:
在 Google Cloud Console 中,打开 Cloud Shell。
导出环境变量以为将来的命令设置项目 ID:
export PROJECT_ID='[PROJECT_ID]'
创建名为
ssh-account
的新服务帐号:gcloud iam service-accounts create ssh-account --project $PROJECT_ID \ --display-name "ssh-account"
创建一个名为
ssh-example
的网络,供本教程使用:gcloud compute networks create ssh-example --project $PROJECT_ID
创建一条防火墙规则,允许通过 SSH 连接到
ssh-example
网络中的实例的流量:gcloud compute firewall-rules create ssh-all --project $PROJECT_ID \ --network ssh-example --allow tcp:22
在
us-central1-f
中创建一个名为target
的实例。此实例用作您的服务帐号将通过 SSH 连接的远程实例。使用--metadata
标志在此特定实例上启用 OS Login。添加--no-service-account
和--no-scopes
标志,因为此实例不需要为该特定示例运行任何 API 请求:gcloud compute instances create target --project $PROJECT_ID \ --zone us-central1-f --network ssh-example \ --no-service-account --no-scopes \ --machine-type e2-micro --metadata=enable-oslogin=TRUE
将
compute.osAdminLogin
IAM 角色授予该服务帐号,使其能够专门为名为target
的实例建立 SSH 连接。compute.osAdminLogin
角色还会授予该服务帐号对该实例的超级用户权限。虽然您可以在项目级层授予此角色,使其可应用于项目中的所有实例,但在实例级层授予此角色可以更精细地控制 SSH 访问权限。以后,如果您发现应用需要访问您的项目中的其他资源,则可以向服务帐号授予更多权限:gcloud compute instances add-iam-policy-binding target \ --project $PROJECT_ID --zone us-central1-f \ --member serviceAccount:ssh-account@$PROJECT_ID.iam.gserviceaccount.com \ --role roles/compute.osAdminLogin
在
us-central1-f
中创建一个名为source
的实例。将该实例与ssh-account
服务帐号相关联。另外,指定cloud-platform
范围,该服务帐号在此实例上执行 API 请求需要使用该范围:gcloud compute instances create source \ --project $PROJECT_ID --zone us-central1-f \ --service-account ssh-account@$PROJECT_ID.iam.gserviceaccount.com \ --scopes https://www.googleapis.com/auth/cloud-platform \ --network ssh-example --machine-type e2-micro
该服务帐号现在可以管理其专属的 SSH 密钥对,并且可以使用 SSH 专门连接到 target
实例。由于 source
实例与您创建的 ssh-account
服务帐号关联,因此 Python 版 Cloud 客户端库可使用应用默认凭据以服务帐号的身份进行身份验证,并使用您之前授予该服务帐号的角色。
接下来,配置并运行应用,以便可以通过 SSH 从一个实例连接到另一个实例。
在实例上运行 SSH 应用
当您的实例上运行的应用需要对其他实例的 SSH 访问权限时,您可以管理服务帐号的 SSH 密钥对并以编程方式执行 SSH 命令。对于此示例,按照以下步骤运行示例应用:
使用
gcloud
命令行工具连接到source
实例:gcloud compute ssh source --project $PROJECT_ID --zone us-central1-f
在
source
实例上,安装pip
和 Python 客户端库:my-username@source:~$ sudo apt update && sudo apt install python-pip -y && pip install --upgrade google-api-python-client
从 GoogleCloudPlatform/python-docs-samples 下载
service_account_ssh.py
示例应用:my-username@source:~$ curl -O https://raw.githubusercontent.com/GoogleCloudPlatform/python-docs-samples/master/compute/oslogin/service_account_ssh.py
运行该示例应用,该应用使用
argparse
从命令行接受变量。在此示例中,指示应用在target
实例上安装并运行cowsay
。对于此命令,请手动添加项目 ID:my-username@source:~$ python service_account_ssh.py \ --cmd 'sudo apt install cowsay -y && cowsay "It works!"' \ --project [PROJECT_ID] --zone us-central1-f --instance target ⋮ ___________ It works! ----------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
如果应用正常运行,您会收到来自 cowsay
应用的输出。您可以修改 --cmd
标志以包含所需的任何命令。或者,您可以编写自己的应用来导入 service_account_ssh.py
并直接对其进行调用。
运行 exit
以断开与 source
实例的连接并返回到 Cloud Shell。
在 Compute Engine 之外运行 SSH 应用
在上述示例中,您在 Compute Engine 实例上运行应用,此时 Python 版 Cloud 客户端库可通过应用默认凭据使用与 source
实例关联的服务帐号。如果您在 Compute Engine 实例之外运行此应用,则除非您手动提供服务帐号密钥,否则客户端库无法访问服务帐号及其权限。
获取您在本教程前面创建的
target
实例的外部 IP 地址。您可以在控制台中的实例页面上找到此地址,也可以从gcloud
命令行工具运行以下命令找到此地址:gcloud compute instances describe target \ --project $PROJECT_ID --zone us-central1-f
为您在上述示例中使用的
ssh-account
服务帐号创建服务帐号密钥,并将密钥文件下载到本地工作站。将该服务帐号密钥复制到您要运行此示例的系统。
在您要运行此示例的系统上打开终端。
将
GOOGLE_APPLICATION_CREDENTIALS
环境变量设置为指向服务帐号密钥.json
文件所在的路径。如果密钥位于Downloads
文件夹中,则可按以下示例所示设置环境变量:$ export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/key.json"
在该系统上安装必备组件:
下载示例应用:
$ curl -O https://raw.githubusercontent.com/GoogleCloudPlatform/python-docs-samples/master/compute/oslogin/service_account_ssh.py
运行示例应用。在 Compute Engine 之外运行应用时,元数据服务器不可用,因此您必须手动指定服务帐号电子邮件地址。您还必须指定前面获取的
target
实例的外部 IP 地址。$ python service_account_ssh.py \ --cmd 'sudo apt install cowsay -y && cowsay "It works!"' \ --account ssh-account@[PROJECT_ID].iam.gserviceaccount.com \ --project [PROJECT_ID] --hostname [TARGET_EXTERNAL_IP] ⋮ ___________ It works! ----------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
如果应用正常运行,您将收到来自 cowsay
应用的输出。
示例应用的工作原理
service_account_ssh.py
示例应用按照以下步骤运行:
- 初始化 OS Login API 对象。
- 如果您未手动提供服务帐号电子邮件地址,则该应用将读取实例元数据以确定与实例关联的服务帐号。如果您在 Compute Engine 之外运行此应用,则必须手动提供服务帐号地址。
- 调用
create_ssh_key()
方法为运行此示例的实例上的服务帐号生成一个临时 SSH 密钥,并将公钥添加到服务帐号,同时使用您可以指定的到期计时器。 - 从 OS Login API 调用
getLoginProfile()
方法来获取服务帐号使用的 POSIX 用户名。 - 调用
run_ssh()
方法,以服务帐号身份执行远程 SSH 命令。 - 从远程 SSH 命令输出响应。
- 移除临时 SSH 密钥文件。
- OS Login 会在公钥文件到期后自动将其移除。
create_ssh_key()
方法会生成新的 SSH 密钥对。然后,该方法从 OS Login API 调用 users().importSshPublicKey()
以将公钥与服务帐号关联。users().importSshPublicKey()
方法也接受到期值,该值指示公钥的有效时间。
最佳做法是配置您的服务帐号,使其定期为自己生成新的密钥对。在此示例中,服务帐号为其建立的每个 SSH 连接创建一个新密钥对,但您可以将其修改为按计划运行以更好地满足应用的需求。
users().importSshPublicKey()
的请求正文包含 expirationTimeUsec
值,该值会告知 OS Login 密钥应何时到期。每个帐号最多只能有 32 KB 的 SSH 密钥数据,因此最好将公共 SSH 密钥配置为在服务帐号完成其操作后不久到期。
在服务帐号配置其 SSH 密钥后,它便可以执行远程命令。在此示例中,应用使用 run_ssh()
方法在远程实例上执行命令并返回命令输出。
清理
为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
在 Google Cloud Console 中,打开 Cloud Shell。
删除名为
source
的实例:gcloud compute instances delete source \ --project $PROJECT_ID --zone us-central1-f
删除名为
target
的实例:gcloud compute instances delete target \ --project $PROJECT_ID --zone us-central1-f
删除
ssh-account
服务帐号:gcloud iam service-accounts delete ssh-account --project $PROJECT_ID
删除名为
ssh-example
的网络:gcloud compute networks delete ssh-example --project $PROJECT_ID
后续步骤
- 下载并查看完整的代码示例。 完整的示例中包含了一个同时使用所有这些方法的小例子。您可以根据自己的需求随意下载、更改并运行该示例。
- 查看 Compute Engine API 参考和 OS Login API 参考,了解如何使用这些 API 执行其他任务。
- 开始创建您自己的应用。