本教程介绍如何创建一个在 Cloud Run 上运行且包含两个服务的安全应用。此应用是一个 Markdown 编辑器,它包含一个任何人都可以用来编写 Markdown 文本的公共“前端”服务和一个将 Markdown 文本渲染成 HTML 的专用“后端”服务。
后端服务使用 Cloud Run 内置且基于 IAM 的服务到服务身份验证功能,是一项用来限制谁可以调用服务的专用服务。这两项服务均采用最小权限原则构建,只有在必要情况下才能访问 Google Cloud 的其余部分。
本教程的限制或非目标
本教程不显示最终用户身份验证,该身份验证使用 Identity Platform 或 Firebase Authentication 生成用户 ID 令牌且需要手动验证用户身份。如需详细了解最终用户身份验证,请参阅有关最终用户身份验证的 Cloud Run 教程。
由于不支持组合使用基于 IAM 的身份验证和 ID 令牌方法,本教程未予介绍。
目标
- 创建一个专用服务账号,将对服务到服务身份验证和 Google Cloud 其余部分的服务访问权限设置为最小。
- 编写、构建两个交互的服务并将其部署到 Cloud Run。
- 在公共 Cloud Run 服务和专用 Cloud Run 服务之间发出请求。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
准备工作
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Run API.
- 安装并初始化 gcloud CLI。
- 安装 curl 以试用该服务
所需的角色
如需获得完成本教程所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:
-
Cloud Build Editor (
roles/cloudbuild.builds.editor
) -
Cloud Run Admin (
roles/run.admin
) -
Create Service Accounts (
roles/iam.serviceAccountCreator
) -
Project IAM Admin (
roles/resourcemanager.projectIamAdmin
) -
Service Account User (
roles/iam.serviceAccountUser
) -
Service Usage Consumer (
roles/serviceusage.serviceUsageConsumer
) -
Storage Admin (
roles/storage.admin
) -
Artifact Registry Repository Administrator (
roles/artifactregistry.repoAdmin
)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
设置 gcloud 默认值
要配置您的 Cloud Run 服务的 gcloud 默认值,请执行以下操作:
设置默认项目:
gcloud config set project PROJECT_ID
将 PROJECT_ID 替换为您在本教程中创建的项目的名称。
为您选择的区域配置 gcloud:
gcloud config set run/region REGION
将 REGION 替换为您选择的受支持的 Cloud Run 区域。
Cloud Run 位置
Cloud Run 是区域级的,这意味着运行 Cloud Run 服务的基础架构位于特定区域,并且由 Google 代管,以便在该区域内的所有可用区以冗余方式提供。
选择用于运行 Cloud Run 服务的区域时,主要考虑该区域能否满足您的延迟时间、可用性或耐用性要求。通常,您可以选择距离用户最近的区域,但除此之外,您还应该考虑 Cloud Run 服务使用的其他 Google Cloud 产品的位置。跨多个位置使用 Google Cloud 产品可能会影响服务的延迟时间和费用。
Cloud Run 可在以下区域使用:
基于层级 1 价格
asia-east1
(台湾)asia-northeast1
(东京)asia-northeast2
(大阪)asia-south1
(印度孟买)europe-north1
(芬兰) 二氧化碳排放量低europe-southwest1
(马德里) 二氧化碳排放量低europe-west1
(比利时) 二氧化碳排放量低europe-west4
(荷兰) 二氧化碳排放量低europe-west8
(米兰)europe-west9
(巴黎) 二氧化碳排放量低me-west1
(特拉维夫)us-central1
(爱荷华) 二氧化碳排放量低us-east1
(南卡罗来纳)us-east4
(北弗吉尼亚)us-east5
(哥伦布)us-south1
(达拉斯) 二氧化碳排放量低us-west1
(俄勒冈) 二氧化碳排放量低
基于层级 2 价格
africa-south1
(约翰内斯堡)asia-east2
(香港)asia-northeast3
(韩国首尔)asia-southeast1
(新加坡)asia-southeast2
(雅加达)asia-south2
(印度德里)australia-southeast1
(悉尼)australia-southeast2
(墨尔本)europe-central2
(波兰,华沙)europe-west10
(柏林) 二氧化碳排放量低europe-west12
(都灵)europe-west2
(英国伦敦) 二氧化碳排放量低europe-west3
(德国法兰克福) 二氧化碳排放量低europe-west6
(瑞士苏黎世) 二氧化碳排放量低me-central1
(多哈)me-central2
(达曼)northamerica-northeast1
(蒙特利尔) 二氧化碳排放量低northamerica-northeast2
(多伦多) 二氧化碳排放量低southamerica-east1
(巴西圣保罗) 二氧化碳排放量低southamerica-west1
(智利圣地亚哥) 二氧化碳排放量低us-west2
(洛杉矶)us-west3
(盐湖城)us-west4
(拉斯维加斯)
如果您已创建 Cloud Run 服务,则可以在 Google Cloud 控制台中的 Cloud Run 信息中心内查看区域。
检索代码示例
要检索可用的代码示例,请执行以下操作:
将示例应用代码库克隆到 Cloud Shell 或本地机器:
Node.js
git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
Python
git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
Go
git clone https://github.com/GoogleCloudPlatform/golang-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
Java
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
C#
git clone https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
或者,您也可以下载该示例的 zip 文件并将其解压缩。
切换到包含 Cloud Run 示例代码的目录:
Node.js
cd nodejs-docs-samples/run/markdown-preview/
Python
cd python-docs-samples/run/markdown-preview/
Go
cd golang-samples/run/markdown-preview/
Java
cd java-docs-samples/run/markdown-preview/
C#
cd dotnet-docs-samples/run/markdown-preview/
查看专用 Markdown 渲染服务
从前端的角度来看,Markdown 服务应遵从一种简单的 API 规范:
- 一个位于
/
的端点 - 期望 POST 请求
- POST 请求的正文为 Markdown 文本
您可能需要查看所有代码以解决任何安全问题,或者只是浏览 ./renderer/
目录来详细了解代码。请注意,本教程未介绍 Markdown 转换代码。
开发专用 Markdown 渲染服务
如要交付代码,请先使用 Cloud Build 进行构建,然后上传到 Artifact Registry,最后再部署到 Cloud Run:
切换到
renderer
目录:Node.js
cd renderer/
Python
cd renderer/
Go
cd renderer/
Java
cd renderer/
C#
cd Samples.Run.MarkdownPreview.Renderer/
创建 Artifact Registry:
gcloud artifacts repositories create REPOSITORY \ --repository-format docker \ --location REGION
您需要进行如下替换:
- 将 REPOSITORY 替换为制品库的唯一名称。 对于项目中的每个代码库位置,代码库名称不得重复。
- 将 REGION 替换为要用于 Artifact Registry 制品库的 Google Cloud 区域。
运行以下命令来构建容器并将其发布到 Artifact Registry 上。
Node.js
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
renderer
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Python
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
renderer
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Go
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
renderer
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Java
此示例使用 Jib 利用常见 Java 工具构建 Docker 映像。无需编写 Dockerfile 或安装 Docker,Jib 便可以优化容器构建。详细了解如何使用 Jib 构建 Java 容器。
使用 gcloud 凭据帮助程序,授权 Docker 推送到您的 Artifact Registry。
gcloud auth configure-docker
使用 Jib Maven 插件来构建容器并将其推送到 Artifact Registry。
mvn compile jib:build -Dimage=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
renderer
是您要为服务指定的名称。成功后,您会看到一条 BUILD SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
C#
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
renderer
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
部署为访问受限的专用服务。
Cloud Run 提供开箱即用的访问权限控制功能和服务身份功能。访问权限控制功能提供了一个身份验证层,限制用户和其他服务调用该服务。而借助服务身份功能,您可以通过创建权限有限的专用服务账号来限制您的服务对其他 Google Cloud 资源的访问权限。
创建一个服务账号作为渲染服务的“计算身份”。默认情况下,该账号不具备除项目成员资格之外的任何特权。
命令行
gcloud iam service-accounts create renderer-identity
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
Markdown 渲染服务不会直接与 Google Cloud 中的其他任何服务集成。它不需要进一步的权限。
使用
renderer-identity
服务账号进行部署,并拒绝未经身份验证的访问。命令行
gcloud run deploy renderer \ --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer \ --service-account renderer-identity \ --no-allow-unauthenticated
如果服务账号属于同一项目,则 Cloud Run 可以使用服务账号名称的缩写形式,而非完整的电子邮件地址。
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
试用专用 Markdown 渲染服务
专用服务无法通过网络浏览器直接加载。请改用 curl
或允许注入 Authorization
标头的类似的 HTTP 请求 CLI 工具。
如需将一些粗体文本发送到该服务,并看到该服务将 Markdown 星号转换为 HTML <strong>
代码,请执行以下操作:
从部署输出中获取网址。
使用
gcloud
派生特殊开发专用身份令牌,以进行身份验证:TOKEN=$(gcloud auth print-identity-token)
创建将原始 Markdown 文本作为网址转义查询字符串参数进行传递的 curl 请求:
curl -H "Authorization: Bearer $TOKEN" \ -H 'Content-Type: text/plain' \ -d '**Hello Bold Text**' \ SERVICE_URL
将 SERVICE_URL 替换为在部署 Markdown 渲染服务后提供的网址。
响应应为 HTML 代码段:
<strong>Hello Bold Text</strong>
查看编辑器和渲染服务之间的集成
编辑器服务提供了一个简单的文本输入界面和一个用于查看 HTML 预览的空间。在继续操作之前,请打开 ./editor/
目录,查看之前检索到的代码。
接下来,请浏览以下几段安全集成这两项服务的代码。
Node.js
render.js
模块会创建经过身份验证的专用渲染程序服务请求。它使用 Cloud Run 环境中的 Google Cloud 元数据服务器来创建身份令牌,并将其作为 Authorization
标头的一部分添加到 HTTP 请求。
在其他环境中,render.js
使用应用默认凭据从 Google 的服务器请求令牌。
从 JSON 解析 Markdown,并将其发送到渲染程序服务以转换为 HTML。
Python
new_request
方法会创建经过身份验证的专用服务请求。它使用 Cloud Run 环境中的 Google Cloud 元数据服务器来创建身份令牌,并将其作为 Authorization
标头的一部分添加到 HTTP 请求。
在其他环境中,new_request
使用应用默认凭据进行身份验证,从 Google 服务器请求身份令牌。
从 JSON 解析 Markdown,并将其发送到渲染程序服务以转换为 HTML。
Go
RenderService
会创建经过身份验证的专用服务请求。它使用 Cloud Run 环境中的 Google Cloud 元数据服务器来创建身份令牌,并将其作为 Authorization
标头的一部分添加到 HTTP 请求。
在其他环境中,RenderService
使用应用默认凭据进行身份验证,从 Google 服务器请求身份令牌。
添加要转换为 HTML 的 Markdown 文本后,请求会发送到渲染程序服务。系统会处理响应错误,以将通信问题与呈现功能区分开来。
Java
makeAuthenticatedRequest
会创建经过身份验证的专用服务请求。它使用 Cloud Run 环境中的 Google Cloud 元数据服务器来创建身份令牌,并将其作为 Authorization
标头的一部分添加到 HTTP 请求。
在其他环境中,makeAuthenticatedRequest
使用应用默认凭据进行身份验证,从 Google 服务器请求身份令牌。
从 JSON 解析 Markdown,并将其发送到渲染程序服务以转换为 HTML。
C#
GetAuthenticatedPostResponse
会创建经过身份验证的专用服务请求。它使用 Cloud Run 环境中的 Google Cloud 元数据服务器来创建身份令牌,并将其作为 Authorization
标头的一部分添加到 HTTP 请求。
在其他环境中,GetAuthenticatedPostResponse
使用应用默认凭据进行身份验证,从 Google 服务器请求身份令牌。
从 JSON 解析 Markdown,并将其发送到渲染程序服务以转换为 HTML。
开发公共编辑器服务
如需构建并部署代码,请执行以下操作:
切换到
editor
目录:Node.js
cd ../editor
Python
cd ../editor
Go
cd ../editor
Java
cd ../editor
C#
cd ../Samples.Run.MarkdownPreview.Editor/
运行以下命令来构建容器并将其发布到 Artifact Registry 上。
Node.js
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
editor
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。映像存储在 Container Registry 中,并可根据需要重复使用。
Python
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
editor
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Go
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
editor
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
Java
此示例使用 Jib 利用常见 Java 工具构建 Docker 映像。无需编写 Dockerfile 或安装 Docker,Jib 便可以优化容器构建。详细了解如何使用 Jib 构建 Java 容器。mvn compile jib:build -Dimage=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
editor
是您要为服务指定的名称。成功后,您会看到一条 BUILD SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
C#
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor
其中 PROJECT_ID 是您的 Google Cloud 项目 ID,
editor
是您要为服务指定的名称。成功完成后,您将看到一条包含 ID、创建时间和映像名称的 SUCCESS 消息。该映像存储在 Artifact Registry 中,并可根据需要重复使用。
部署为对渲染服务具有特殊访问权限的专用服务。
创建一个服务账号,使其充当专用服务的“计算身份”。默认情况下,该账号不具备除项目成员资格之外的任何特权。
命令行
gcloud iam service-accounts create editor-identity
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
编辑器服务不需要与 Markdown 渲染服务之外的其他任何 Google Cloud 服务交互。
向
editor-identity
计算身份授予访问权限,以调用 Markdown 渲染服务。使用此身份的任何服务都将拥有此特权。命令行
gcloud run services add-iam-policy-binding renderer \ --member serviceAccount:editor-identity@PROJECT_ID.iam.gserviceaccount.com \ --role roles/run.invoker
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
因为在渲染服务环境中向此身份赋予了调用方角色,所以渲染服务是编辑器可以调用的唯一一项专用 Cloud Run 服务。
使用
editor-identity
服务账号进行部署,并允许未经身份验证的公开访问。命令行
gcloud run deploy editor --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor \ --service-account editor-identity \ --set-env-vars EDITOR_UPSTREAM_RENDER_URL=SERVICE_URL \ --allow-unauthenticated
您需要进行如下替换:
- PROJECT_ID 替换为您的项目 ID。
- SERVICE_URL 替换为在部署 Markdown 渲染服务后提供的网址。
Terraform
如需了解如何应用或移除 Terraform 配置,请参阅基本 Terraform 命令。
部署编辑器服务:
授予
allUsers
权限以调用服务:
了解 HTTPS 流量
使用这些服务渲染 Markdown 时有三个 HTTP 请求。
测试
如需试用完整的双服务应用,请执行以下操作:
在浏览器中导航至上述部署步骤提供的网址。
尝试编辑左侧的 Markdown 文本,然后点击按钮以在右侧预览文本。
它应该类似于如下所示:
如果您选择继续开发这些服务,请注意,它们已限制了 Identity and Access Management (IAM) 对 Google Cloud 其余服务的访问权限,并需要额外的 IAM 角色才能访问众多其他服务。
清理
如果您为本教程创建了一个新项目,请删除项目。 如果您使用的是现有项目,希望保留此项目且不保留本教程中添加的任何更改,请删除为教程创建的资源。
删除项目
为了避免产生费用,最简单的方法是删除您为本教程创建的项目。
如需删除项目,请执行以下操作:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
删除教程资源
删除您在本教程中部署的 Cloud Run 服务:
gcloud
gcloud run services delete editor gcloud run services delete renderer
您还可以从 Google Cloud 控制台中删除 Cloud Run 服务。
移除您在教程设置过程中添加的 gcloud 默认配置。
gcloud config unset run/region
移除项目配置:
gcloud config unset project
删除在本教程中创建的其他 Google Cloud 资源:
- 从 Artifact Registry 中删除编辑者容器映像(名称为
REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/editor
) - 从 Artifact Registry 中删除渲染容器映像(名称为
REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/renderer
) - 删除编辑器服务账号
editor-identity@PROJECT_ID.iam.gserviceaccount.com
- 删除渲染程序服务账号
renderer-identity@PROJECT_ID.iam.gserviceaccount.com
- 从 Artifact Registry 中删除编辑者容器映像(名称为
后续步骤
- 浏览安全使用 IAM核对清单,进一步保护您的项目
- 扩展此示例应用以使用 Cloud Monitoring 自定义指标跟踪 Markdown 使用情况
- 查看 Pub/Sub 教程,了解如何获得安全的异步微服务