借助 Cloud Run,只需三个简单的步骤,即可从开发到生产

1. 简介

为什么应用管理如此困难?

一个重要原因是,开发者通常必须兼任系统管理员。以下是开发、部署和管理现代生产级 Web 应用时需要考虑的部分问题:

4d018476b4a73b47.png

我不知道你怎么样,但这些都是我不想操心的事情!我真正想考虑的是我的应用逻辑:

6dfd143d20e5548b.png

简而言之,这就是 Cloud Run 的全部意义所在 - 让您能够专注于应用,并将所有管理和维护工作交给其他人(即 Google),Google 在此领域投入了数百万小时来磨练和完善自己的技能。

除了上述管理方面的挑战之外,您还必须应对以下问题:

  • 依赖项 - 应用运行的环境应尽可能与测试环境完全一致。这可能涵盖多个维度,包括操作系统、支持库、语言解释器或编译器、硬件配置以及许多其他因素。
  • 分发 - 从应用的本地版本迁移到在互联网上广泛共享的版本通常需要更改运行时环境,复杂性会大幅增加,学习曲线也会变得陡峭。

Cloud Run 会为您处理这些问题以及许多其他问题。不过,与其听我介绍,不如我们一起构建一个应用,看看只需几个简单的步骤,就能轻松从本地开发环境过渡到生产级云应用。

实践内容…

  • 您将构建一个简单的 Web 应用,并验证它在开发环境中是否按预期运行。
  • 然后,您将转到同一应用的容器化版本。在此过程中,您将了解容器化的含义以及它为何如此有用。
  • 最后,您将应用部署到云端,并了解如何使用命令行和 Google Cloud 控制台轻松管理 Cloud Run 服务。

学习内容…

  • 如何在 Python 中创建简单的 Web 服务器应用
  • 如何将应用打包到可在任何位置运行的 Docker 容器中
  • 如何将应用部署到云端,以便任何人都可以试用您的新作品
  • 如何使用 buildpack 进一步简化上述步骤
  • 如何使用 Google Cloud 命令行工具和 Cloud 控制台网页界面

所需条件…

  • 网络浏览器
  • Google 账号

本实验的适用对象为各种水平的开发者,包括新手。虽然您将使用 Python,但无需熟悉 Python 编程就能理解代码内容,因为我们会解释您使用的所有代码。

2. 进行设置

5110b5081a1e1c49.png

本部分涵盖了开始此实验所需执行的所有操作。

自定进度的环境设置

  1. 登录 Cloud 控制台,然后创建一个新项目或重复使用现有项目。 (如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个。)

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID

  1. 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。

运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分中的所有说明操作,该部分介绍了如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。

启动 Cloud Shell

在本实验中,您将使用 Cloud Shell 会话,这是一个由在 Google 云中运行的虚拟机托管的命令解释器。您也可以在自己的计算机上本地运行本部分,但使用 Cloud Shell 可让每个人在一致的环境中获得可重现的体验。完成本实验后,欢迎您在自己的计算机上重试本部分。

704a7b7491bd157.png

激活 Cloud Shell

  1. 在 Cloud Console 中,点击激活 Cloud Shell4292cbf4971c9786.png

bce75f34b2c53987.png

如果您以前从未启动过 Cloud Shell,将看到一个中间屏幕(非首屏),描述它是什么。如果是这种情况,请点击继续(您将永远不会再看到它)。一次性屏幕如下所示:

70f315d7b402b476.png

预配和连接到 Cloud Shell 只需花几分钟时间。

fbe3a0674c982259.png

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。只需使用一个浏览器或 Google Chromebook 即可完成本 Codelab 中的大部分(甚至全部)工作。

在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:

  1. 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list

命令输出

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project

命令输出

[core]
project = <PROJECT_ID>

如果不是上述结果,您可以使用以下命令进行设置:

gcloud config set project <PROJECT_ID>

命令输出

Updated property [core/project].

在终端中设置一些环境变量,以便在后续步骤中更轻松地操作:

export PROJ=$GOOGLE_CLOUD_PROJECT 
export APP=hello 
export PORT=8080
export REGION="us-central1"
export TAG="gcr.io/$PROJ/$APP"

启用 API

在后续步骤中,您将了解在哪些情况下需要这些服务(以及原因),但现在,请运行以下命令,以授予您的项目对 Cloud Build、Container Registry 和 Cloud Run 服务的访问权限:

gcloud services enable cloudbuild.googleapis.com         \
                       containerregistry.googleapis.com  \
                       run.googleapis.com          

这应该会生成类似如下内容的成功消息:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

3. 构建简单的 Web 应用

eef530b56b8e93a3.png

首先,点击 Cloud Shell 面板顶部的 Open Editor 按钮。如下所示:

9b81c8a37a6bcdd8.png

然后,您会发现自己处于类似于 Visual Studio Code 的 IDE 环境中,您可以在其中创建项目、编辑源代码、运行程序等。如果屏幕空间过于狭窄,您可以拖动控制台与编辑/终端窗口之间的水平条(此处突出显示)来展开或收缩这两个区域之间的分界线:

8dea35450851af53.png

您可以分别点击 Open EditorOpen Terminal 按钮,在编辑器和终端之间来回切换。现在,尝试在这两种环境之间来回切换。

接下来,选择“文件”->“新建文件夹”,输入 hello,然后点击 OK,以创建一个用于存储本实验作业的文件夹。您在本实验中创建的所有文件以及在 Cloud Shell 中完成的所有工作都将在此文件夹中进行。

现在,创建一个 requirements.txt 文件。这会告知 Python 您的应用依赖哪些库。对于这个简单的 Web 应用,您将使用一个用于构建 Web 服务器的热门 Python 模块(名为 Flask)和一个名为 gunicorn 的 Web 服务器框架。在 Cloud Editor 窗口中,点击“文件”->“新建文件”菜单以创建新文件。当系统提示输入新文件的名称时,输入 requirements.txt,然后按 OK 按钮。确保新文件最终位于 hello 项目文件夹中。

在新文件中输入以下行,以指定您的应用依赖于 Python Flask 软件包和 gunicorn 网络服务器。

Flask
gunicorn

您无需明确保存此文件,因为 Cloud 编辑器会自动为您保存更改。

版本 1:Hello world!

使用相同的方法,创建另一个名为 main.py 的新文件。这将是应用的主要(也是唯一的)Python 源文件。同样,请确保新文件最终位于 hello 项目文件夹中。

将以下代码插入到此文件中:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from the environment.

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
@app.route("/", methods=["GET"])
def say_hello():
    html = "<h1>Hello world!</h1>"
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

切换回终端,然后使用以下命令切换到项目文件夹:

cd hello

运行以下命令以安装项目依赖项:

pip3 install -r requirements.txt

现在,在终端中运行以下命令来启动应用:

python3 main.py

此时,您的应用正在专用于 Cloud Shell 会话的虚拟机上运行。Cloud Shell 包含一个代理机制,可让您从全球互联网上的任何位置访问在虚拟机上运行的网络服务器(例如您刚刚启动的网络服务器)。

依次点击 web preview 按钮和 Preview on Port 8080 菜单项,如下所示:

fe45e0192080efd6.png

系统随即会打开一个浏览器标签页,其中显示正在运行的应用,该应用应如下所示:

b1f06501509aefb9.png

版本 2:回显网址路径

返回 Cloud Editor(通过 Open Editor 按钮),并通过更新 main.py 文件来添加对回显可选网址后缀的支持,如下所示:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])     # ← NEW
def say_hello(name="world"):               # ← MODIFIED
    html = f"<h1>Hello {name}!</h1>"       # ← MODIFIED
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

切换回终端(通过 Open Terminal 按钮),然后输入 control-C(按住 Control 键的同时按“C”键)以停止正在运行的应用,然后输入以下内容以重新启动该应用:

python3 main.py

再次点击 web preview 按钮,然后点击 Preview on Port 8080 菜单项,以在网络浏览器标签页中打开正在运行的应用。您应该会再次看到“Hello world!”消息,但现在请将斜线字符后面的网址文本替换为您选择的任意字符串(例如 /your-name),并验证您是否看到类似以下内容:

93b87996f88fa370.png

版本 3:随机颜色

现在,返回到 Cloud Editor(通过 Open Editor 按钮),并按如下方式更新 main.py 文件,以添加对随机背景颜色的支持:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from the environment.

# This function decides whether foreground text should be
# displayed in black or white, to maximize fg/bg contrast.
def set_text_color(rgb):                      # ← NEW
    sum = round(                              # ← NEW
        (int(rgb[0]) * 0.299)                 # ← NEW
        + (int(rgb[1]) * 0.587)               # ← NEW
        + (int(rgb[2]) * 0.114)               # ← NEW
    )                                         # ← NEW
    return "black" if sum > 186 else "white"  # ← NEW


# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
# To verify each new invocation of these requests, the HTML document
# includes CSS styling to produce a randomly colored background.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])
def say_hello(name="world"):
    bg = random.sample(range(1, 255), 3)                       # ← NEW
    hex = (int(bg[0]) * 256) + (int(bg[1]) * 16) + int(bg[2])  # ← NEW
    fg_color = set_text_color(bg)                              # ← NEW
    bg_color = f"#{hex:06x}"                                   # ← NEW
    style = f"color:{fg_color}; background-color:{bg_color}"   # ← NEW
    html = f'<h1 style="{style}">Hello {name}!</h1>'           # ← MODIFIED
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

切换回终端(通过 Open Terminal 按钮),然后输入 control-C(按住 Control 键的同时按“C”键)以停止正在运行的应用,然后输入以下内容以重新启动该应用:

python3 main.py

再次点击 web preview 按钮,然后点击 Preview on Port 8080 菜单项,以在网络浏览器标签页中打开正在运行的应用。您应该会看到生成的文本,其中包含任何指定的后缀或默认的“Hello world!”字符串,显示在随机着色的背景前面,如下所示:

baf8d028f15ea7f4.png

重新加载页面几次,您会看到每次访问应用时,随机背景颜色都会发生变化。

这样一来,您的应用就完成了 - 恭喜!在下一步中,您将了解如何将应用打包到容器中,以及这样做的实用性。

4. 将应用容器化

17cc234ec3325a8a.png

什么是容器?

一般来说,容器(尤其是 Docker)使我们能够创建一个模块化盒子,在其中运行应用及其捆绑在一起的所有依赖项。我们将结果称为容器映像。在本部分中,您将创建一个容器映像,用于封装应用及其所有依赖项。

说到依赖项,在之前的步骤中,当您在开发者环境中运行应用时,必须运行 pip3 install -r requirements.txt,并确保 requirements.txt 文件包含所有依赖库和相应版本。使用容器时,您可以在生成容器映像时安装这些要求,因此容器的使用者无需担心安装任何内容

此容器映像将构成在 Cloud Run 上部署应用的基本构建块。由于容器几乎可以在任何虚拟或实际服务器上使用,因此我们可以将应用部署到您喜欢的任何位置,还可以将应用从一个服务提供商迁移到另一个服务提供商,或者从本地迁移到云端。

容器有助于使应用:

  • 可重现 - 容器是独立的且完整的
  • 可移植 - 容器是跨行业的构建块,可实现应用在不同云服务提供商和环境之间的可移植性

简而言之,容器最终实现了“一次编写,随处运行”的目标。不过,有一项例外情况是,生成的容器只能在创建时所用的处理器类型上运行,但您也可以生成适用于其他硬件配置的容器版本。

闲话少说,我们来创建一个容器吧!您将使用一种名为 Docker 的特定技术来创建容器。

在 Cloud 编辑器中,创建一个名为 Dockerfile 的新文件。此文件是用于构建映像的蓝图。它会告知 Docker 您的运行环境和源代码,以及如何安装依赖项、构建应用和运行代码。

# Use an official lightweight Python image.
FROM python:3.9-slim

# Copy local code to the container image.
WORKDIR /app
COPY main.py .
COPY requirements.txt .

# Install dependencies into this container so there's no need to 
# install anything at container run time.
RUN pip install -r requirements.txt

# Service must listen to $PORT environment variable.
# This default value facilitates local development.
ENV PORT 8080

# Run the web service on container startup. Here you use the gunicorn
# server, with one worker process and 8 threads. For environments 
# with multiple CPU cores, increase the number of workers to match 
# the number of cores available.
CMD exec gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 main:app

在 Cloud 终端中,通过运行以下命令,使用 Cloud Build 构建容器映像:

gcloud builds submit --tag $TAG

推送到注册表后,您会看到一条包含映像名称的 SUCCESS 消息,该消息应类似于 gcr.io/<project-id>/hello。映像现在存储在 Google Container Registry 中,您可以随时随地重复使用。

您可以使用下面的命令列出与您的当前项目关联的所有容器映像:

gcloud container images list

现在,使用以下 docker 命令通过 Cloud Shell 在本地运行并测试应用:

docker run -p $PORT:$PORT -e PORT=$PORT $TAG

-p $PORT:$PORT 选项用于指示 Docker 将主机环境中的外部端口 $PORT(上文设置为 8080)映射到正在运行的容器内的同一端口号。这样一来,您编写的服务器代码和测试应用时连接到的外部端口号将相同 (8080),从而简化了操作。不过,您也可以使用 -p 选项将主机上的任意外部端口映射到容器内的任意所需内部端口。

-e PORT=$PORT 选项会告知 Docker 使 $PORT 环境变量(在上面设置为 8080)可供在容器内运行的应用使用。

现在,您可以将 Web 浏览器指向容器内运行的 Python 代码,以测试应用。在 Cloud Shell 窗口中,点击“网页预览”图标,然后选择“在端口 8080 上预览”,就像您在上一步中所做的那样。

结果应该看起来很熟悉 - 您应该会看到生成的文字显示在随机颜色的背景前面,就像您直接在 Cloud Shell 终端中运行应用时一样。重新加载页面几次,您会看到每次访问应用时,随机背景颜色都会发生变化。

恭喜!您现在已运行应用的容器化版本。在下一部分中,您将无需修改任何代码,即可将容器映像转换为生产质量的 Web 应用

5. 迁移到云端...

1b0665d94750ded6.gif

现在,您已将应用容器化,接下来需要将其部署到云端,以便与全世界分享这份精彩。但您想做的不仅仅是分享。您需要确保它:

  • 运行可靠 - 如果运行应用的计算机崩溃,您将获得自动容错功能
  • 自动扩缩 - 您的应用将能够应对大量流量,并在不使用时自动减少资源占用空间
  • 可最大限度地降低您的费用,因为您无需为未使用的资源付费,只需为响应流量时消耗的资源付费
  • 可通过自定义域名访问 - 您可以使用一键式解决方案为服务分配自定义域名
  • 提供出色的响应时间 - 冷启动的响应速度相当快,但您可以通过指定实例数下限配置来进一步优化
  • 支持使用标准 SSL/TLS 网络安全技术的端到端加密 - 当您部署服务时,系统会自动免费为您提供标准网络加密和相应的必需证书

将应用部署到 Google Cloud Run,您不仅可以获得上述所有优势,还能获得更多好处。

将应用部署到 Cloud Run

首先,我们来修改应用,以便您能够区分新修订版本和旧修订版本。为此,请修改 main.py 文件,使默认消息从“Hello world!”更改为“Hello from Cloud Run!”。换句话说,将 main.py 中的相应行从以下内容:

def say_hello(name="world"):

更改为:

def say_hello(name="from Cloud Run"):

Cloud Run 是区域级的,这意味着运行 Cloud Run 服务的基础架构位于特定区域,并且由 Google 托管,以便在该区域内的所有地区以冗余方式提供。在上面的“准备工作”部分中,您已通过 REGION 环境变量定义了默认区域。

使用以下命令重新构建容器映像并将容器化应用部署到 Cloud Run:

gcloud builds submit --tag $TAG
gcloud run deploy "$APP"   \
  --image "$TAG"           \
  --platform "managed"     \
  --region "$REGION"       \
  --allow-unauthenticated
  • 您还可以使用 gcloud config set run/region $REGION 定义默认区域。
  • --allow-unauthenticated 选项可使服务公开可用。为避免未经身份验证的请求,请改用 --no-allow-unauthenticated

此处指定的映像是您在上一步中构建的 Docker 映像。借助 Cloud Build 服务(该服务将生成的映像存储在 Google Container Registry 中),Cloud Run 服务可以找到该映像并为您部署。

等待部署完成。成功部署后,命令行中便会显示该服务的网址:

Deploying container to Cloud Run service [hello] in project [PROJECT_ID...
✓ Deploying new service... Done.                                   
  ✓ Creating Revision... Revision deployment finished. Waiting for health check...
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [hello] revision [hello-...] has been deployed and is serving 100 percent of traffic.
Service URL: https://hello-....a.run.app

您还可以使用以下命令检索服务网址:

gcloud run services describe hello  \
  --platform managed                \
  --region $REGION                  \
  --format "value(status.url)"

系统应显示类似以下内容:

https://hello-....a.run.app

此链接是 Cloud Run 服务的专用网址,具有 TLS 安全性。此链接是永久性的(只要您不停用该服务),并且可在互联网上的任何位置使用。它不使用之前提到的 Cloud Shell 代理机制,该机制依赖于临时虚拟机。

点击突出显示的 Service URL 以打开一个浏览器标签页,其中显示正在运行的应用。结果应显示“Hello from Cloud Run!”消息,背景颜色随机。

恭喜!您的应用现在正在 Google Cloud 中运行。无需考虑任何问题,您的应用即可公开提供,并使用 TLS (HTTPS) 加密,而且可以自动扩缩到令人难以置信的流量水平。

但我认为这个过程还可以更简单...

6. 自动创建容器

这些都很酷,但如果我根本不想操心 Dockerfile 和容器,该怎么办?如果我像大多数开发者一样,只想专注于编写应用代码,而让其他人来负责容器化,该怎么办?幸运的是,Cloud Run 支持一种名为 Buildpacks 的开源标准,该标准正是为了自动执行从一组源文件制造容器的过程而存在的。

请注意,在某些情况下,开发者可能更倾向于使用显式 Dockerfile,例如,如果他们希望高度自定义容器的构建方式。但对于像本练习这样的常见情况,buildpack 可以很好地发挥作用,避免了手动创建 Dockerfile 的需要。我们来修改代码,以使用 buildpack。

首先,我们来修改应用,以便您能够区分新修订版本和旧修订版本。为此,请修改 main.py 文件,使默认消息从“Hello from Cloud Run!”更改为“Hello from Cloud Run with Buildpacks!”。换句话说,将 main.py 中的相应行从以下内容:

def say_hello(name="from Cloud Run"):

更改为:

def say_hello(name="from Cloud Run with Buildpacks"):

现在,我们来创建一个名为 Procfile 的新文件,以利用 buildpack。在 Cloud Editor 中创建该文件,并插入以下一行文本:

web: python3 main.py

这会告知 buildpack 系统如何在自动生成的容器中运行您的应用。有了这条指令,您甚至不再需要 Dockerfile。如需验证这一点,请删除您的 Dockerfile,然后在 Cloud Shell 终端中运行以下命令:

gcloud beta run deploy "$APP"  \
    --source .                 \
    --platform "managed"       \
    --region "$REGION"         \
    --allow-unauthenticated

这与您在上一步中运行的用于部署应用的命令类似,但这次您已将 --image 选项替换为 --source . 选项。此命令会告知 gcloud 命令,您希望它使用 buildpack 根据在当前目录中找到的源文件(--source . 中的 dot 是当前目录的简写)创建容器映像。由于该服务会隐式处理容器映像,因此您无需在此 gcloud 命令中指定映像。

再次验证此部署是否成功,方法是点击突出显示的 Service URL 以打开一个网络浏览器标签页,其中显示正在运行的应用,并确保您的服务在随机着色的背景前显示“Hello from Cloud Run with Buildpacks!”。

请注意,通过使用 buildpack 来制造 Dockerfile,您实际上已将三个简单步骤减少为两个:

  1. 在开发环境中创建应用。
  2. 只需一条命令,即可将完全相同的代码部署到云端。

7. 我是否必须使用命令行?

不需要!与几乎所有 Google Cloud 服务一样,您可以通过以下三种方式与 Cloud Run 交互:

  • 您刚刚看到的 gcloud 命令行工具。
  • 通过 Cloud 控制台提供的功能丰富的 Web 界面,支持直观的点按交互方式。
  • 以编程方式使用 Google 客户端库(支持多种常用语言,包括 Java、C#、Python、Go、Javascript、Ruby、C/C++ 等)。

接下来,我们使用控制台界面部署 Cloud Run 应用的另一个实例。通过左上角的菜单前往 Cloud Run 服务着陆页:

e2b4983b38c81796.png

然后,您应该会看到 Cloud Run 服务的摘要,如下所示:

b335e7bf0a3af845.png

点击“创建服务”链接以开始部署流程:

51f61a8ddc7a4c0b.png

输入“hello-again”作为服务名称,采用默认的部署平台和区域,然后点击“下一步”。

8a17baa45336c4c9.png

输入此容器映像网址:gcr.io/cloudrun/hello,这是 Google 出于测试目的而创建的容器,然后点击“高级设置”下拉菜单,查看可供您使用的众多配置设置。以下列举了一些可自定义的元素:

  • 端口号和容器入口点(将替换构建容器时指定的入口点)
  • 硬件:内存和 CPU 数量
  • 扩缩:实例数下限和上限
  • 环境变量
  • 其他:请求超时设置、每个容器的请求数上限、HTTP/2

点击“下一步”按钮可继续对话。在下一个对话框中,您可以指定服务的触发方式。对于“入站流量”,选择“允许所有流量”;对于“身份验证”,选择“允许未经身份验证的流量”。

e78281d1cff3418.png

这些设置最为宽松,因为它们允许任何人从公共互联网上的任何位置访问您的 Cloud Run 应用,而无需指定身份验证凭据。您可能希望为应用设置限制性更高的设置,但为了便于学习,我们在此练习中将采用较为简单的设置。

现在,点击 Create 按钮以创建 Cloud Run 服务。几秒钟后,您应该会在 Cloud Run 服务摘要列表中看到新服务。摘要行会显示最新的部署(日期/时间和部署者)以及一些关键配置设置。点击服务名称链接,深入了解新服务的详细信息。

如需验证您的服务,请点击摘要页面顶部附近显示的网址,如下例中突出显示的部分所示:

6c35cf0636dddc51.png

您应该会看到与以下类似的内容:

3ba6ab4fe0da1f84.png

现在,您已部署新的 Cloud Run 服务,请选择 REVISIONS 标签页,了解管理多个部署的一些方法。

2351ee7ec4a356f0.png

如需直接从控制台部署新修订版本,您可以点击 EDIT & DEPLOY NEW REVISION 按钮,如下面的示例屏幕截图中突出显示的那样:

a599fa88d00d6776.png

立即点击该按钮,创建新的修订版本。点击容器网址附近的 SELECT 按钮,如下所示:

5fd1b1f8e1f11d40.png

在随即显示的对话框中,找到您之前使用 Buildpack 从 Cloud Build 部署的简单 Web 应用,然后点击“选择”。请务必选择容器映像下的

gcr.io/<project>/cloud-run-source-deploy

文件夹,如下所示:

8a756c6157face3a.png

选择完毕后,滚动到底部,然后点击 DEPLOY 按钮。您现在已部署应用的新修订版本。如需验证,请再次访问您的服务网址,并验证您现在是否看到色彩鲜艳的“Hello from Cloud Run with Buildpacks!”Web 应用。

如图所示,“修订版本”标签页会显示您部署的每个修订版本的摘要,您现在应该会看到此服务的两个修订版本。您可以点击修订版本名称左侧的单选按钮来选择特定修订版本,屏幕右侧随即会显示修订版本详细信息的摘要。选择这些按钮后,您可以看到这两个修订版本派生自两个不同的容器映像。

借助 MANAGE TRAFFIC 按钮,您可以修改发送到指定修订版本的传入请求的分配。这种能够精细调整发送到给定修订版本的流量的功能可实现多种有价值的应用场景:

  • 使用少量传入流量对应用的新版本进行 Canary 测试
  • 将流量从存在问题的版本回滚到之前的修订版本
  • A/B 测试

您可以在以下位置找到 MANAGE TRAFFIC 按钮:

519d3c22ae028287.png

通过指定 50/50 的流量分配比例,在两个修订版本之间配置 50/50 的流量分配比例,如下所示:

8c37d4f115d9ded4.png

现在,点击“保存”按钮,然后反复访问服务的网址,验证 50/50 的拆分情况,确保平均而言,一半的请求由当前修订版本(“Hello from Cloud Run with Buildpacks!”)提供服务,另一半由之前的修订版本(“It's running!”)提供服务。

“服务详情”页面上的其他标签页可用于监控性能、流量和日志,从而深入了解服务的运行情况和效果。您还可以通过“权限”标签页微调对服务的访问权限。花点时间浏览此页面上的标签页,了解此处提供的功能。

程序化接口

如前所述,您还可以选择以编程方式创建、部署和管理 Cloud Run 服务。对于手动任务,此选项比命令行或 Web 控制台更高级,但对于自动化 Cloud Run 服务,这绝对是最佳选择。您可以选择使用多种常用编程语言的 Google 客户端库

8. 测试应用

198ada162d1f0bf1.png

在最后一步中,您将运行人工负载测试,对应用进行压力测试,并观察应用如何根据传入的需求进行扩缩。您将使用名为 hey 的工具,该工具已预安装在 Cloud Shell 中,可用于运行负载测试并呈现结果。

运行测试

在 Cloud Shell 终端中,运行以下命令以运行负载测试:

hey -q 1000 -c 200 -z 30s https://hello-...run.app

命令实参的含义如下:

  • -q 1000 - 尝试以每秒大约 1,000 个请求的速度驱动负载
  • -c 200 - 分配 200 个并行工作线程
  • -z 30s - 运行负载测试 30 秒
  • 请务必在此命令行中使用您的服务网址作为最后一个实参

测试结果应如下所示:

 Summary:
 Total:        30.2767 secs
 Slowest:      3.3633 secs
 Fastest:      0.1071 secs
 Average:      0.1828 secs
 Requests/sec: 1087.2387
 Total data:   3028456 bytes
 Size/request: 92 bytes

Response time histogram:
 0.107 [1]     |
 0.433 [31346] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
 0.758 [1472]  |■■
 1.084 [82]    |
 1.410 [4]     |
...

Latency distribution:
...
 50% in 0.1528 secs
 75% in 0.1949 secs
 90% in 0.2442 secs
 95% in 0.4052 secs
 99% in 0.7062 secs

Details (average, fastest, slowest):
...
 req write:    0.0000 secs, 0.0000 secs, 0.0232 secs
 resp wait:    0.1824 secs, 0.1070 secs, 3.2953 secs
 resp read:    0.0000 secs, 0.0000 secs, 0.0010 secs
Status code distribution:
 [200] 32918 responses

此摘要显示了以下几项值得关注的信息:

  • 以大约 1K/秒的速度发送了 32,918 个请求,持续了 30 秒。
  • 没有错误(只有 200 HTTP 响应)。
  • 平均延迟时间为 180 毫秒。
  • 最短延迟时间为 107 毫秒,最长延迟时间为 3.3 秒
  • 第 90 百分位的延迟时间为 244 毫秒。

如果您查看 Cloud Run 控制台中的 METRICS 标签页,则可以了解服务器端的性能情况:

e635c6831c468dd3.png

9. 清理

虽然 Cloud Run 不会针对未使用的服务收费,但您可能仍然需要为您构建的容器映像支付存储费用。

为避免产生费用,您可以删除您的 GCP 项目,让系统停止对该项目中使用的所有资源计费;您也可以使用下面的命令直接删除您的容器映像:

gcloud container images delete $TAG

如需删除 Cloud Run 服务,请使用以下命令:

gcloud run services delete hello --platform managed --region $REGION --quiet
gcloud run services delete hello-again --platform managed --region $REGION --quiet

10. 大功告成!

9a31f4fdbbf1ddcb.png

恭喜!您已成功构建并部署了生产环境 Cloud Run 应用。在此过程中,您了解了容器以及如何构建自己的容器。您还了解了如何使用 gcloud 命令行工具和 Cloud 控制台轻松部署 Cloud Run 应用。现在,您已经知道如何与全世界分享您的精彩作品了!

最后,我想问您一个重要的问题:

在开发环境中成功运行应用后,您需要修改多少行代码才能将其部署到云端,并获得 Cloud Run 提供的所有生产级属性?

答案当然是零。:)

值得一试的 Codelab…

其他值得探索的实用功能…

参考文档…

11. 号召性用语

Google Cloud 徽标

如果您喜欢此 Codelab,并且可能会花更多时间实际操作 Google Cloud,那么您应该立即加入 Google Cloud Innovators

创新者一般成员徽章徽标

Google Cloud Innovators 计划是免费的,包含以下福利:

  • 参加实时讨论、AMA 和路线图会议,获取直接由 Google 员工分享的最新动态
  • 通过电子邮件接收最新的 Google Cloud 资讯
  • 数字徽章和视频会议背景
  • 500 点数,可用于 Skills Boost 上的实验和学习

点击此处即可报名!