App Mod 研讨会

1. 简介

上次更新日期:2024 年 11 月 1 日

如何将旧版 PHP 应用升级到 Google Cloud?

(📽️ 观看 7 分钟的介绍视频,了解此 Codelab)

在本地运行且需要进行现代化改造的旧式应用是很常见的。这意味着,使其可在不同环境中进行扩缩、安全且可部署。

在本研讨会中,您将:

  1. 将 PHP 应用容器化
  2. 移至代管式数据库服务 ( Cloud SQL)。
  3. 部署到 Cloud Run(它是 GKE/Kubernetes 的零运维替代方案)。
  4. 使用 Identity and Access Management (IAM) 和 Secret Manager 保护应用。
  5. 通过 Cloud Build 定义 CI/CD 流水线。例如,Cloud Build 可以与在热门 Git 提供商(如 GitHub 或 GitLab)上托管的 Git 代码库相关联,并且可在任何推送到主库时触发。
  6. Cloud Storage 上托管应用图片。这是通过挂载实现的,无需代码即可更改应用。
  7. 通过 Gemini 引入 Gen AI 功能,并通过 Cloud Functions(无服务器)进行编排。
  8. 熟悉 SLO运行新刷新的应用。

按照这些步骤,您可以逐步改进 PHP 应用,提高其可扩展性、安全性和部署灵活性。此外,通过迁移到 Google Cloud,您可以利用其强大的基础架构和服务,确保您的应用在云原生环境中顺畅运行。

我们相信,您通过这些简单的步骤学到的内容可以应用于具有不同语言/堆栈和不同使用情形的您自己的应用和组织。

应用简介

您将要创建分支的应用(代码,依据 MIT 许可)是一个基于 MySQL 身份验证的基本 PHP 5.7 应用。该应用的主要理念是提供一个平台,供用户上传照片,并让管理员能够标记不当图片。该应用包含两个表:

  • 用户。已预编译,并包含管理员。新用户可以注册。
  • 图片。附带一些示例图片。登录后的用户可以上传新照片。我们将在此处添加一些魔法。

您的目标

我们希望对旧版应用进行现代化改造,以便将其迁移到 Google Cloud。我们将利用其工具和服务,通过 Cloud SQL、Cloud Run、Cloud Build、Secret Manager 等服务来提升可伸缩性、增强安全性、自动执行基础架构管理,并集成图片处理、监控和数据存储等高级功能。

445f7a9ae37e9b4d.png

更重要的是,我们希望分步完成,以便您了解每个步骤背后的思考过程,通常每个步骤都会为后续步骤开启新的可能性(例如:模块 2 -> 3,以及 6 -> 7)。

还在犹豫不决?请观看 YouTube 上的这段 7 分钟视频

所需条件

  • 一台已连接到互联网且装有浏览器的计算机。
  • 部分 GCP 赠金。请向您当地的 Google 爱好者寻求帮助 ;)
  • gcloud 命令正在运行。
  • 在本地工作吗?请点击此处下载。您还需要一些实用的编辑器(例如 vscode 或 intellij)。
  • 在云端执行一切操作吗?然后,您可以使用 Cloud Shell
  • GitHub 用户。您需要使用自己的 Git 代码库对原始代码 🧑?🏻?‍💻? gdgpescara/app-mod-workshop 进行分支。您需要拥有自己的 CI/CD 流水线(自动提交 -> 构建 -> 部署)

解决方案示例

您可以在本地计算机上参加此研讨会,也可以完全在浏览器中完成。

2. 创建信用和分叉

6dafc658860c0ce5.png

兑换 GCP 赠金并设置 GCP 环境 [可选]

要举办此研讨会,您需要一个具有部分赠金的结算账号。如果您已有自己的结算系统,则可以跳过此步骤。

创建一个全新的 Google Gmail 账号 (*),以便与您的 GCP 抵用金相关联。请向您的教师索要用于兑换 GCP 抵用金的链接,或访问以下网址使用抵用金:bit.ly/PHP-Amarcord-credits

使用新创建的账号登录并按照说明操作。

ff739240dbd84a30.png

(

) Why do I need a brand new gmail account?*

我们注意到有些用户未通过 Codelab,因为他们的账号(尤其是工作账号或学生电子邮件地址)之前使用过 GCP,并且组织政策 限制了他们操作的能力。我们建议您创建一个新的 Gmail 账号,或者使用之前未接触过 GCP 的现有 Gmail 账号 (gmail.com)。

点击该按钮即可兑换抵用金。

331658dc50213403

填写以下表单,提供您的名字和姓氏,并同意条款及条件。

您可能需要等待几秒钟,结算账号才会显示在此处:https://console.cloud.google.com/billing

完成后,打开 Google Cloud 控制台并创建一个新项目,点击左上角显示“无组织”的下拉菜单的“项目选择器”。如下所示

bd7548f78689db0b.png

如果您没有项目,请创建一个新项目,如以下屏幕截图所示。右上角有一个“新建项目”选项。

6c82aebcb9f5cd47.png

请务必按照以下步骤将新项目与 GCP 试用结算账号相关联。

f202527d254893fb.png

大功告成,您可以使用 Google Cloud Platform 了。如果您是新手,或者只想在 Cloud 环境中执行所有操作,可以通过左上角的以下按钮访问 Cloud Shell 及其编辑器,如下所示。

7d732d7bf0deb12e.png

确保您已在左上角选择了新项目:

未选择(不良):

c2ffd36a781b276a.png

已选中(良好):

594563c158f4f590

从 GitHub 复制应用

  1. 前往演示版应用:https://github.com/gdgpescara/app-mod-workshop
  2. 点击 🍴? 分叉。
  3. 如果您没有 GitHub 账号,则需要创建一个新账号。
  4. 您可以根据需要进行修改。

734e51bfc29ee5df.png

  1. 使用 git clone 克隆应用代码:https://github.com/<YOUR-GITHUB-USER>/<YOUR-REPO-NAME>
  1. 使用您喜欢的编辑器打开克隆的项目文件夹。如果您选择 Cloud Shell,可以点击“打开编辑器”执行此操作,如下所示。

40f5977ea4c1d1cb.png

如图所示,Google Cloud Shell 编辑器提供了您所需的一切

a4e5ffb3e9a35e84.png

3. 第 1 单元:创建 SQL 实例

645902e511a432a6.png

创建 Google Cloud SQL 实例

我们的 PHP 应用将连接到 MySQL 数据库,因此我们需要将其复制到 Google Cloud,以便顺利完成迁移。Cloud SQL 是理想之选,因为它支持您在 Cloud 中运行全代管式 MySQL 数据库。具体步骤如下:

  1. 前往 Cloud SQL 页面:https://console.cloud.google.com/sql/instances
  2. 点击“创建实例”
  3. 启用 API(如有必要)。此过程可能需要几秒钟的时间。
  4. 选择 MySQL。
  5. (我们会尽量为您提供价格最实惠的版本,以延长其使用寿命):
  • 版本:企业版
  • 预设:开发(我们尝试过沙盒,但不起作用)
  • Mysql Ver: 5.7(哇,怀旧一下!)
  1. 实例 ID:选择 appmod-phpapp(如果您更改此值,请务必相应地更改未来的脚本和解决方案)。
  2. 密码:您可以随意设置,但请记下 CLOUDSQL_INSTANCE_PASSWORD
  3. 地区:与您为应用的其余部分选择的地区保持一致(例如,米兰 = europe-west8
  4. 可用区可用性:单可用区(为演示节省费用)

点击“创建实例”按钮以部署 Cloud SQL 数据库;⌛ 此过程大约需要 10 分钟⌛。在此期间,请继续阅读文档;您也可以开始解决下一个模块(“将 PHP 应用容器化”),因为它与第一部分中的此模块没有依赖项(在您修复数据库连接之前)。

注意:此实例的费用应该约为 7 美元/天。请务必在研讨会结束后将其停止。

在 Cloud SQL 中创建 image_catalog 数据库和用户

应用项目附带一个 db/ 文件夹,其中包含两个 sql 文件:

  1. 01_schema.sql:包含用于创建包含 Users 和 Images 数据的两个表的 SQL 代码。
  2. 02_seed.sql:包含用于将数据注入之前创建的表的 SQL 代码。

创建 image_catalog 数据库后,系统会使用这些文件。为此,请按以下步骤操作:

  1. 打开您的实例,然后点击“数据库”标签页:
  2. 点击“创建数据库”
  3. 将其命名为 image_catalog(如 PHP 应用配置中所示)。

997ef853e5ebd857.png

然后,我们创建数据库用户。这样,我们就可以对 image_catalog 数据库进行身份验证了。

  1. 现在,点击用户标签页
  2. 点击“添加用户账号”。
  3. 用户:我们来创建一个用户:
  • 用户名:appmod-phpapp-user
  • 密码:请选择您能记住的密码,或点击“生成”
  • 保留“允许任何主机 (%)”。
  1. 点击“添加”。

针对已知 IP 打开数据库。

请注意,Cloud SQL 中的所有数据库都是“独立”的。您需要明确设置可从中访问的网络。

  1. 点击您的实例
  2. 打开“连接”菜单
  3. 点击“网络”标签页。
  4. 点击“已获授权的网络”下方的相应位置。现在,添加子网。
  • 现在,我们将其设为“不安全”,以便应用正常运行:
  • 名称:“全世界的每个人 - 不安全”(让我们提醒自己,这种廉价解决方案也不安全)。
  • 网络:“0.0.0.0/0”(注意:这不安全!)

点击“保存”。

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

5ccb9062a7071964.png

注意:此解决方案是一个很好的折衷方案,可让您在 O(hours) 内完成本研讨会。不过,请查看安全文档,以帮助您确保生产环境中的解决方案安全无虞!

现在该测试数据库连接了!

我们来看看之前创建的 image_catalog 用户是否可用。访问实例中的 Cloud SQL Studio,然后输入要进行身份验证的数据库、用户和密码,如下所示:

d56765c6154c11a4.png

现在,您可以打开 SQL 编辑器并继续执行下一部分的操作。

从代码库导入数据库

使用 SQL 编辑器导入 image_catalog 表及其数据。从代码库的 SQL 文件中获取 SQL 代码,并依次执行这些代码。01_schema.sql,然后是 02_seed.sql

之后,您应该会在 image_catalog 中看到两个表,即 usersimages,如下所示:

65ba01e4c6c2dac0.png

您可以通过在编辑器中运行以下命令来测试:select * from images;

此外,请务必记下公共 IP 地址,稍后您将用到它。

4. 第 2 单元:将 PHP 应用容器化

e7f0e9979d8805f5.png

我们希望将此应用构建为云端应用。

这意味着,您需要将代码打包到某种 ZIP 文件中,其中包含在云端运行该代码所需的所有信息。

您可以通过以下几种方式打包它:

  • Docker。非常受欢迎,但正确设置起来非常复杂。
  • Buildpack。不太常用,但往往会“自动猜测”要构建和运行的内容。通常它就是有效的!

在本研讨会中,我们假设您使用的是 Docker。

Docker

如果您希望掌控一切,这是一个不错的解决方案。当您需要配置特定库并注入某些不明显的行为(上传中的 chmod、应用中的非标准可执行文件等)时,这很有用。

由于我们最终希望将容器化应用部署到 Cloud Run,因此请查看以下文档,并尝试填写空白。目前,我们只提供基本功能,以便您轻松上手。最终的 Dockerfile 将如下所示:

# Use an official PHP image with Apache
# Pull a suitable php image
FROM __________# Define the env variable for the Apache listening port 8080
ENV __________

# Set working directory inside the container
WORKDIR __________

# Install required PHP extensions: PDO, MySQL, and other dependencies
RUN __________

# Copy all application files into the container
COPY __________

# Configure Apache to listen on port 8080. Use ‘sed' command to change the default listening port.
RUN __________

# When in doubt, always expose to port 8080
EXPOSE __________

# Start Apache in the foreground
CMD __________

此外,为了在本地测试我们的应用,我们需要更改 config.php 文件,以便我们的 PHP 应用能够连接到 Google CloudSQL 上可用的 MySQL 数据库。根据您以前设置的内容,在空白处填写内容

  • Db_host 是 Cloud SQL 的公共 IP 地址,您可以在控制台中找到它:

bd27071bf450a8d0.png

  • Db_name 应保持不变:image_catalog
  • Db_user 应为 appmod-phpapp-user
  • Db_pass 是您选择的。使用单引号进行设置,并根据需要进行转义。
<?php
// Database configuration
$db_host = '____________';
$db_name = '____________';
$db_user = '____________';
$db_pass = '____________';

try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Errore di connessione: " . $e->getMessage());
}

session_start();
?>

此外,您随时可以在 Gemini 的帮助下将一些意大利语内容翻译成英语!

好的,现在您已经有了 Dockerfile,并将 PHP 应用配置为连接到数据库,接下来我们来试一试!

如果您还没有 Docker,请安装它(链接)。如果您使用的是 Cloud Shell,就不需要安装这个版本(这有多酷?)。

现在,尝试使用适当的 docker build 和 run 命令构建和运行容器化 PHP 应用。

  • docker build -t <IMAGE_TAG_NAME> .
  • docker run -it -p <CONTAINER PORT>:<LOCAL MACHINE PORT> <IMAGE_TAG_NAME>

如果一切正常,您在连接到本地主机后应该会看到以下网页。

如果您使用的是 Cloud Shell,还可以将本地端口(例如 8080)导出到浏览器,如下所示:

docker build -t my-php-app-docker app-mod-workshop/ -f Dockerfile

docker run -it -p 8080:8080 my-php-app-docker

现在,您知道应用在端口 8080 上运行,请点击“网页预览”图标(带有眼睛的浏览器),然后点击在端口 8080 上预览(对于任何其他端口,请点击“更改端口”)

33a24673f4550454.png

在浏览器中测试结果

现在,您的应用应如下所示:

2718ece96b1f18b6.png

如果您使用 Admin/admin123 登录,则应该会看到如下内容。

68b62048c2e86aea.png

太棒了!正在处理 🎉🎉🎉

如果您的 dockerization 不错,但数据库凭据有误,您可能会收到如下内容:

e22f45b79bab86e1.png

请再试一次,您已经很接近了!

Buildpack [可选]

借助 Buildpack,应用会自动构建。很遗憾,您无法完全控制,因此最终可能会出现意外配置。

您的本地环境中应该有一个新的 Docker 映像。您可以尝试为其运行容器,但由于我们无法完全控制映像的构建方式,应用可能无法运行。无论如何,我们都邀请您参与实验,并在成功后分享您的意见。谢谢!

保存到 Artifact Registry [可选]

到目前为止,您应该已经拥有一个可正常运行的容器化 PHP 应用,可以部署到云端了。接下来,我们需要在云端有个位置来存储 Docker 映像,使其可用于部署到 Cloud Run 等 Google Cloud 服务。此存储解决方案称为 Artifact Registry,是一项全代管式 Google Cloud 服务,专门用于存储应用工件,包括 Docker 容器映像、Maven 软件包、npm 模块等。

我们来使用相应的按钮在 Google Cloud Artifact Registry 中创建一个代码库。

e1123f0c924022e6.png

选择有效的名称、格式和适合存储制品的区域。

4e516ed209c470ee.png

返回本地开发环境标记,然后将应用容器映像推送到刚刚创建的 Artifact Registry 代码库。为此,请完成以下命令。

  • docker 标记 SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
  • docker push TARGET_IMAGE[:TAG]

结果应如下屏幕截图所示。

1e498feb4e88be9f.png

太棒了!🎉?🎉?🎉?您可以进入下一级别了。

注意:您还可以尝试使用 /upload.php 端点并上传一张照片。您可能会收到“权限被拒绝”消息。如果是这样,您需要在 Dockerfile 中进行一些 chmod/chown 修复。

5. 第 3 单元:将应用部署到 Cloud Run

9ffca42774f6c5d1

为何选择 Cloud Run?

这个问题很合理!几年前,您肯定会选择 Google App Engine。

简而言之,目前,Cloud Run 拥有更新的技术栈,部署更轻松、更便宜,并且可在不使用时缩减至 0。它能够灵活地运行任何无状态容器,并与各种 Google Cloud 服务集成,非常适合以最低开销和最高效率部署微服务和现代应用。

更具体地说,Cloud Run 是 Google Cloud 提供的全代管式平台,可让您在无服务器环境中运行无状态容器化应用。它会自动处理所有基础架构,从零开始扩容以满足传入流量,并在闲置时缩容,从而实现经济高效的运行。Cloud Run 支持任何语言或库,只要它们打包在容器中即可,从而让开发变得非常灵活。它可与其他 Google Cloud 服务很好地集成,适合构建微服务、API、网站和事件驱动型应用,而无需管理服务器基础架构。

前提条件

如需完成此任务,您应在本地计算机上安装 gcloud。如果没有,请参阅此处的说明。相反,如果您使用的是 Google Cloud Shell,则无需采取任何措施。

部署之前...

如果您在本地环境中工作,请使用以下命令对 Google Cloud 进行身份验证

  • $ gcloud auth login –update-adc # not needed in Cloud Shell

这应该会通过浏览器上的 OAuth 登录对您进行身份验证。请务必使用已登录 Google Cloud 且已启用结算功能的用户(例如 vattelapesca@gmail.com)通过 Chrome 登录。

使用以下命令启用 Cloud Run API

  • $ gcloud services enable run.googleapis.com

至此,一切都已准备好部署到 Cloud Run。

通过 gcloud 将应用部署到 Cloud Run

用于在 Cloud Run 上部署应用的命令是 gcloud run deploy。您可以通过设置多种选项来实现自己的目标。最小一组角色是:

  1. 您要为应用部署的 Cloud Run 服务的名称。Cloud Run 服务会返回一个网址,用于为您的应用提供端点。
  2. 您的应用将在其中运行的 Google Cloud 区域
  3. 封装应用的容器映像
  4. 应用在执行期间需要使用的环境变量
  5. Allow-Unauthenticated 标志:允许所有人无需进一步身份验证即可访问您的应用

请参阅文档,了解如何将此选项应用于您的命令。部署需要几分钟时间。如果一切正确无误,您应该会在 Google Cloud 控制台中看到如下内容。

ef1029fb62f8de81.png

f7191d579c21ca3e.png

点击 Cloud Run 提供的网址,然后测试您的应用。身份验证成功后,您应该会看到如下内容。

d571a90cd5a373f9.png

使用“no questions”运行“gcloud run deploy”

您可能已经注意到,gcloud run deploy 会向您提出恰当的问题,并填补您留下的空白。太棒了!

不过,在一些模块中,我们将把此命令添加到 Cloud Build 触发器,因此不能有任何问题。我们需要填写该命令中的每个选项。因此,您想制作金色 gcloud run deploy --option1 blah --foo bar --region your-fav-region。如何实现?

  1. 重复第 2-3-4 步,直到 gcloud 停止询问问题:
  2. [LOOP] 目前找到的选项为gcloud run deploy
  3. [LOOP] 系统请求选项 X
  4. [LOOP] 在公开文档中搜索如何通过 CLI 添加选项 --my-option [my-value] 来设置 X。
  5. 现在,请返回第 2 步,除非 gcloud 在没有其他问题的情况下完成。
  6. 此 gcloud run 部署 BLAH BLAH BLAH 太棒了!将该命令保存到某个位置,您稍后在 Cloud Build 步骤中需要用到它!

可在此处查看可能的解决方案。

太棒了!🎉?🎉?🎉?您已成功在 Google Cloud 中部署应用,完成了现代化改造的第一步。

6. 第 4 单元:使用 Secret Manager 清理密码

95cd57b03b4e3c73.png

在上一步中,我们成功在 Cloud Run 中部署并运行了应用。不过,我们在实现该功能时采用了一种安全不良做法:以明文形式提供一些 Secret

第一轮迭代:更新 config.php 以使用 ENV

您可能已经注意到,我们直接将数据库密码放入了 config.php 文件中的代码中。这对于测试和查看应用是否正常运行来说是可以接受的。但您不能在生产环境中提交/使用此类代码。应动态读取密码(和其他数据库连接参数),并在运行时将其提供给应用。更改 config.php 文件,使其从 ENV 变量中读取数据库参数。如果失败,您应考虑设置默认值。这样做有助于您在无法加载 ENV 时了解页面输出是否使用了默认值。填空并替换 config.php 中的代码。

<?php
// Database configuration with ENV variables. Set default values as well 
$db_host = getenv('DB_HOST') ?: _______;
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: _______;
// Note getenv() is PHP 5.3 compatible
try {
    $pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Errore di connessione: " . $e->getMessage());
}

session_start();
?>

由于您的应用是容器化应用,因此您需要提供一种向应用提供 ENV 变量的方法。这可以通过以下几种方式实现:

  • build 时刻,在 Dockerfile 中。使用语法 ENV DB_VAR=ENV_VAR_VALUE 向上一个 Dockerfile 中添加 4 个参数。这会设置可在运行时替换的默认值。例如,只能在此处设置“DB_NAME”和“DB_USER”,不能在其他任何位置设置。
  • run 时。您可以通过 CLI 或界面为 Cloud Run 设置这些变量。这里是放置全部 4 个变量的正确位置(除非您希望保留 Dockerfile 中设置的默认值)。

在本地主机中,您可能需要将 ENV 变量放在 .env 文件中(请查看 solutions 文件夹)。

此外,请确保将 .env 添加到 .gitignore:您不想将 Secret 推送到 GitHub!

echo .env >> .gitignore

之后,您可以在本地测试实例:

docker run -it -p 8080:8080 --env-file .env my-php-app-docker

现在,您已完成以下操作:

  1. 您的应用将从环境变量中动态读取变量
  2. 您从代码中移除了数据库密码,从而提高了安全性)

现在,您可以将新修订版本部署到 Cloud Run。我们直接进入界面,手动设置环境变量:

  • 前往 https://console.cloud.google.com/run
  • 点击您的应用
  • 点击“修改和部署新的修订版本”
  • 在第一个标签页“容器”上,点击下方的“变量和 Secret”标签页
  • 点击“+ 添加变量”,然后添加所有所需的变量。最终结果应如下所示:

7a5fbfa448544d3.png

f2780c35585388ca.png

完美吗?不会。大多数运营商仍然可以看到您的卡券。您可以使用 Google Cloud Secret Manager 来缓解此问题。

第二次迭代:Secret Manager

你的密码从你自己的代码中消失了:成功!但请等一下 - 我们现在安全了吗?

任何有权访问 Google Cloud 控制台的用户仍然可以看到您的密码。事实上,如果您访问 Cloud Run YAML 部署文件,则可以检索该文件。或者,如果您尝试修改或部署新的 Cloud Run 修订版,密码会显示在“变量和 Secret”部分,如下面的屏幕截图所示。

Google Cloud Secret Manager 是一项安全的集中式服务,用于管理 API 密钥、密码、证书和其他密钥等敏感信息。

借助 Secret Manager,您可以使用精细的权限和强大的加密功能存储、管理和访问 Secret。Secret Manager 与 Google Cloud 的 Identity and Access Management (IAM) 集成,让您可以控制哪些人可以访问特定 Secret,从而确保数据安全和法规遵从。

它还支持自动轮替密钥和版本控制,简化密钥生命周期管理,并增强 Google Cloud 服务中应用的安全性。

如需访问 Secret Manager,请从三线菜单前往安全服务,然后在数据保护部分下找到它,如下面的屏幕截图所示。

6df83a1c3cb757f6.png

进入该 API 后,按照下图所示启用 Secret Manager API。

a96c312e2c098db1.png

  • 现在,点击“Create a Secret”(创建 Secret)。我们理性地称呼它:
  • 名称:php-amarcord-db-pass
  • Secret 值:“您的数据库密码”(忽略“上传文件”部分)。
  • 为此 Secret 链接添加注释,应如下所示:projects/123456789012/secrets/php-amarcord-db-pass。这是指向您的 Secret 的唯一指针(适用于 Terraform、Cloud Run 等)。该编号是您的唯一项目编号。

提示:请尝试为您的 Secret 采用一致的命名惯例,从左到右进行专门化,例如:cloud-devrel-phpamarcord-dbpass

  • 组织(包含公司)
  • 团队(在组织内)
  • 应用(团队内部)
  • 变量名称(应用内)

这样,您就可以使用简单的正则表达式查找单个应用的所有密钥。

创建新的 Cloud Run 修订版本

现在,我们已经有了新的 Secret,需要移除 DB_PASS ENV 变量,并将其替换为新的 Secret。因此:

  • 通过 Google Cloud 控制台访问 Cloud Run
  • 选择相应应用。
  • 点击“修改和部署新修订版本”
  • 找到“变量和 Secret”标签页。
  • 使用“+ 引用密文”按钮重置 DB_PASS ENV 变量。
  • 为引用的 Secret 使用相同的“DB_PASS”,并使用最新版本。

9ed4e35be7654dcb

完成后,您应该会看到以下错误

da0ccd7af39b04ed.png

尝试找出解决方法。要解决此问题,您需要访问 IAM 和管理部分,然后更改授予权限。祝您调试顺利!

确定问题后,请返回 Cloud Run 并重新部署新修订版本。结果应如下图所示:

e89f9ca780169b6b.png

提示:Play 管理中心 (UI) 非常擅长指出权限问题。请花些时间浏览 Cloud 实体的所有链接!

7. 第 5 单元:使用 Cloud Build 设置 CI/CD

ba49b033c11be94c.png

为什么要使用 CI/CD 流水线?

到现在,您应该已经输入了几次 gcloud run deploy,也许还反复回答了同一个问题。

厌倦使用 gcloud run deploy 手动部署应用了吗?如果每次您将新更改推送到 Git 代码库时,您的应用都可以自动部署,那不是很好吗?

如需使用 CI/CD 流水线,您需要满足以下两项条件:

  1. 个人 Git 代码库:幸运的是,您应该已在第 2 步中将本教程的代码库分叉到您的 GitHub 账号。如果没有,请返回并完成该步骤。您的分叉代码库应如下所示:https://github.com/<YOUR_GITHUB_USER>/app-mod-workshop
  2. Cloud Build。借助这项令人惊叹且价格低廉的服务,您可以为几乎所有内容配置构建自动化:Terraform、容器化应用等。

本部分将重点介绍如何设置 Cloud Build。

开始使用 Cloud Build!

我们将使用 Cloud Build 来实现这一点:

  • 使用 Dockerfile 构建源代码。您可以将其视为一个“大 .zip 文件”,其中包含构建和运行该文件所需的所有内容(“构建工件”)。
  • 将此工件推送到 Artifact Registry (AR)。
  • 然后,为应用“php-amarcord”从 AR 到 Cloud Run 发出部署
  • 这将创建现有应用的新版本(“修订版本”),该版本可视为包含新代码的层,我们会将其配置为在推送成功时将流量转移到新版本。

下面是我的 php-amarcord 应用的部分 build 示例:

f30f42d4571ad5e2.png

我们如何实现这一切?

  1. 通过编写一个完美的 YAML 文件:cloudbuild.yaml
  2. 通过创建 Cloud Build 触发器。
  3. 通过 Cloud Build 界面连接到我们的 GitHub 代码库。

创建触发器(和 Connect 代码库)

  • 前往 https://console.cloud.google.com/cloud-build/triggers
  • 点击“创建触发器”。
  • 编译:
  • 名称:on-git-commit-build-php-app 等有意义的名称
  • 事件:推送到分支
  • 来源:“关联新代码库”替代文本
  • 这会在右侧打开一个窗口:“关联代码库”
  • 来源提供方:“GitHub”(第一项)
  • “继续”
  • 点击“Authenticate”(验证身份)后,GitHub 上会打开一个窗口以进行跨平台身份验证。请按照流程操作,并耐心等待。如果您有许多代码库,则可能需要一些时间。
  • “选择代码库”选择您的账号/代码库,然后选中“我了解...”部分。
  • 如果您收到错误:表示 GitHub 应用未安装在您的任何代码库中,请继续点击“Install Google Cloud Build”(安装 Google Cloud Build)并按照说明操作。
  • 23e0e0f1219afea3.png点击“连接”
  • bafd904ec07122d2.png
  • 答对了!您的代码库现已连接。
  • 返回触发器部分...
  • 配置:自动检测 (*)
  • 高级:选择服务账号“[PROJECT_NUMBER]-compute@developer.gserviceaccount.com
  • xxxxx 是您的项目 ID
  • 默认计算服务账号适用于实验室方法,请勿在生产环境中使用!(了解详情)。
  • 其他所有设置均保持不变。
  • 点击“创建”按钮。

(*) 这是最简单的方法,因为它会检查 Dockerfile 或 cloudbuild.yaml。不过,cloudbuild.yaml 让您可以真正决定在哪个步骤执行哪项操作。

我有电源!

现在,除非您向 Cloud Build 服务账号(什么是服务账号?代表您执行任务的“机器人”的电子邮件地址(在本例中,是在云端构建内容)。

除非您授权您的 SA 执行构建和部署操作,否则他将无法执行这些操作。幸运的是,这很容易!

  • 依次前往“Cloud Build”>“Settings”(设置)。
  • “[PROJECT_NUMBER]-compute@developer.gserviceaccount.com”服务账号
  • 勾选以下复选框:
  • Cloud Run
  • Secret Manager
  • 服务账号
  • Cloud Build
  • 还要勾选“设置为首选服务账号”

8715acca72286a46.png

Cloud Build YAML 在哪里?

我们强烈建议您花一些时间创建自己的 Cloud Build YAML。

不过,如果您没有时间或不想抽出时间,可以从以下解决方案文件夹中获得一些灵感:.solutions

现在,您可以将更改推送到 GitHub,并观察 Cloud Build 的运行情况。

设置 Cloud Build 可能会比较复杂。预计可通过以下方式来回发送:

  • https://console.cloud.google.com/cloud-build/builds;region=global 中查看日志
  • 正在查找错误。
  • 修复代码并重新发出 git commit / git push。
  • 有时错误并非在代码中,而是在一些配置中。在这种情况下,您可以通过界面(Cloud Build >“Triggers”>“Run”)发布新的 build

97acd16980a144ab.png

请注意,如果您使用此解决方案,则仍需执行一些工作。例如,您需要为新创建的 dev/prod 端点设置 ENV 变量:

3da8723e4ff80c0a.png

可以通过以下两种方法实现此目的:

  • 通过界面 - 再次设置 ENV 变量
  • 通过 CLI 为您量身打造“完美”脚本。您可以点击此处查看示例:gcloud-run-deploy.sh。您需要调整一些设置,例如端点和项目编号;您可以在 Cloud 概览中找到项目编号。

如何将代码提交到 GitHub?

本研讨会无法介绍将 git push 推送到 GitHub 的最佳方式。不过,如果您在 Cloud Shell 中遇到问题,可以通过以下两种方式解决:

  1. CLI。在本地添加 SSH 密钥,然后添加远程代码库 git@github.com:YOUR_USER/app-mod-workshop.git(而不是 http)
  2. VSCode。如果您使用的是 Cloud Shell 编辑器,则可以使用源代码控件 (ctrl-shift-G) 标签页,点击“同步更改”,然后按照说明操作。您应该能够将 GitHub 账号的身份验证信息导入到 VSCode,这样就可以轻松地从中拉取/推送代码了。

f0d53f839c7fa3b6.png

请务必git add clodubuild.yaml和其他文件,否则将无法正常运行。

深度与浅层的“开发/生产环境一致性”[可选]

如果您从此处复制模型版本,则会有两个相同的 DEV 和 PROD 版本。这很棒,符合 《十二要素应用》规则 10

不过,我们使用两个不同的 Web 端点让应用指向同一数据库。这对于研讨会来说已经足够了;但在现实生活中,您需要花一些时间来打造适当的生产环境。这意味着拥有两个数据库(一个用于开发数据库,一个用于生产环境),同时还要选择将其部署在何处以实现灾难恢复 / 高可用性。这超出了本研讨会的范围,但值得您思考。

如果您有时间进行“深度”版本的制作,请记住需要复制的所有资源,例如:

  • Cloud SQL 数据库(可能还有 SQL 实例)。
  • GCS 存储桶
  • Cloud Functions 函数。
  • 您可以在开发阶段使用 Gemini 1.5 Flash 作为模型(价格更低、速度更快),在生产阶段使用 Gemini 1.5 Pro(功能更强大)。

一般来说,每次您对应用执行操作时,都应进行批判性思考:生产环境是否应具有相同的值?如果没有,则需要重复工作。当然,使用 Terraform 会更加容易,通过 Terraform,您可以将环境(-dev、-prod)作为后缀注入资源。

8. 第 6 单元:迁移到 Google Cloud Storage

a680e0f287dd2dfb.png

存储

目前,应用将状态存储在 Docker 容器中。如果机器发生故障、应用发生崩溃,或者您只是推送了新修订版,系统就会安排新的 build,并重置存储空间(=> 清空)。🙈

如何解决此问题?有多种方法。

  1. 将图片存储在数据库中。我最终对之前的 PHP 应用就是这么做的。这是最简单的解决方案,因为它不会增加复杂性。但这肯定会增加数据库的延迟时间和负载!
  2. 将您的 Cloud Run 应用迁移到适合存储的解决方案:GCE + 永久性磁盘?或许是 GKE + Storage
  3. 移至 GCS。Google Cloud Storage 是整个 Google Cloud 中一流的存储服务,也是最符合 Cloud 惯例的解决方案。不过,这需要我们深入研究 PHP 库。我们是否有 适用于 GCS 的 PHP 5.7 库PHP 5.7 是否支持 Composer(似乎 PHP 5.3.2 是 Composer 支持的最低版本)?
  4. 可以使用 docker sidecar 吗?
  5. 也可以使用 GCS Cloud Run 卷装载。这听起来很棒。

🤔 迁移存储空间(开放式)

[开放式] 在本练习中,我们希望您找到一种解决方案,以某种方式保留图片。

验收测试

我不想告诉您解决方案,但希望您能做到以下几点:

  1. 您上传了 newpic.jpg。您可以在应用中看到它。
  2. 您将应用升级到新版本。
  3. newpic.jpg仍在原地,可见。

💡 可能的解决方案(GCS Cloud Run 卷挂载)

这是一个非常优雅的解决方案,它使我们能够在完全不涉及代码的情况下实现有状态文件上传(除了显示图片说明,但它很简单,并且仅是为了提升视觉满意度)。

这样,您应该就可以将 Cloud Run 中的文件夹挂载到 GCS 了,具体步骤如下:

  1. 所有上传到 GCS 的内容实际上都会显示在您的应用中。
  2. 所有上传到您的应用的内容实际上都会上传到 GCS
  3. 系统会对上传到 GCS 的对象执行一些神奇操作(第 7 章)。

注意:请阅读 FUSE 的详细信息。如果性能存在问题,则不适用。

创建 GCS 存储分区

GCS 是 Google Cloud 的通用存储服务。它经过了严格的测试,并且每项需要存储空间的 GCP 服务都使用它。

请注意,Cloud Shell 会将 PROJECT_ID 导出为 GOOGLE_CLOUD_PROJECT:

$ export PROJECT_ID=$GOOGLE_CLOUD_PROJECT

#!/bin/bash

set -euo pipefail

# Your Cloud Run Service Name, eg php-amarcord-dev
SERVICE_NAME='php-amarcord-dev'
BUCKET="${PROJECT_ID}-public-images"
GS_BUCKET="gs://${BUCKET}"

# Create bucket
gsutil mb -l "$GCP_REGION" -p "$PROJECT_ID" "$GS_BUCKET/"

# Copy original pictures there - better if you add an image of YOURS before.
gsutil cp ./uploads/*.png "$GS_BUCKET/"

配置 Cloud Run 以将存储分区装载到 /uploads/ 文件夹中

现在,我们来看看优雅的部分。我们创建一个卷 php_uploads,并指示 Cloud Run 在 MOUNT_PATH 上进行 FUSE 装载(类似于 /var/www/html/uploads/):

#!/bin/bash

set -euo pipefail

# .. keep variables from previous script..

# Uploads folder within your docker container.
# Tweak it for your app code.
MOUNT_PATH='/var/www/html/uploads/'

# Inject a volume mount to your GCS bucket in the right folder.
gcloud --project "$PROJECT_ID" beta run services update "$SERVICE_NAME" \
    --region $GCP_REGION \
    --execution-environment gen2 \
    --add-volume=name=php_uploads,type=cloud-storage,bucket="$BUCKET"  \
    --add-volume-mount=volume=php_uploads,mount-path="$MOUNT_PATH"

现在,针对您要指向 Cloud Storage 的所有端点重复此步骤。

您也可以通过界面实现相同的效果

  1. 在“卷”标签页下,创建一个指向您的存储分区的卷挂载,类型为“Cloud Storage 存储分区”,例如名称为“php_uploads”。
  2. 在“容器”>“卷挂载”下,将您刚刚创建的卷挂载到应用请求的卷点。具体取决于 Dockerfile,但可能类似于 var/www/html/uploads/

无论是哪种方式,如果一切正常,您在修改新的 Cloud Run 修订版本时应该会看到如下内容:

6c2bb98fc1b0e077

现在,测试将一张新图片上传到 /upload.php 端点的新应用。

图片应该会在 GCS 上流畅传输,而无需编写任何 PHP 代码:

70032b216afee2d7.png

刚刚发生了什么?

发生了一件非常神奇的事。

使用旧代码的旧应用仍在正常运行。得益于现代化的全新堆栈,我们能够将应用中的所有图片/图片轻松存放在有状态的云端存储分区中。现在,您可以尽情发挥创意:

  • 想要在每次收到包含“危险”或“裸露”内容的图片时发送电子邮件?您无需更改 PHP 代码即可执行此操作。
  • 想要在每次收到图片时使用 Gemini 多模态模型对其进行描述,并将包含相应描述的数据库上传到数据库?您无需修改 PHP 代码即可执行此操作。您不相信我吗?请继续阅读第 7 章。

我们刚刚发现了一个巨大的机会。

9. 第 7 单元:利用 Google Gemini 为应用赋能

c00425f0ad83b32c.png

现在,您已经拥有了一个现代化的全新 PHP 应用(就像 2024 年的 Fiat 126),并且该应用使用了云端存储空间。

您可以用它来做些什么呢?

前提条件

在上一章中,借助模型解决方案,我们可以在 GCS 上装载映像 /uploads/实际上可以将应用逻辑与映像存储空间分开。

在本练习中,您需要:

  • 已成功完成第 6 章(存储)中的练习。
  • 创建一个用于存储上传图片的 GCS 存储分区,用户可以在您的应用中上传图片,这些图片会流入您的存储分区。

设置 Cloud Functions 函数(使用 Python)

您是否曾想过如何实现事件驱动型应用?例如:

  • &lt;event&gt; 发生 => 时发送电子邮件
  • &lt;event&gt; 发生 => 时,如果 <condition> 为 true,则更新数据库。

事件可以是任何内容,包括 BigQuery 中可用的新记录、GCS 中某个文件夹中发生更改的新对象,或 Pub/Sub 队列中等待处理的新消息。

Google Cloud 支持多种范例来实现这一点。最值得注意的是:

在本练习中,我们将深入了解 Cloud Functions 函数,以实现令人惊叹的效果。我们还会为您提供一些选做练习。

请注意,示例代码在 .solutions/ 下提供

设置 Cloud Functions 函数 (공 python)

我们正努力打造一个雄心勃勃的 GCF。

  1. 在 GCS 上创建新映像时。(可能是因为有人在应用中上传了该内容,但也可能是因为其他原因)
  2. .. 调用 Gemini 来描述它并获取图片的文本说明 ..(最好检查 MIME 并确保它是图片,而不是 PDF、MP3 或文本)
  3. ... 并使用此说明更新数据库。(这可能需要对数据库进行补丁,以便向 images 表添加 description 列)。

修补数据库以将 description 添加到映像

  1. 打开 Cloud SQL Studio:

b92b07c4cba658ef.png

  1. 输入图片数据库的用户名和密码
  2. 注入以下 SQL 语句,为图片说明添加列:

ALTER TABLE images ADD COLUMN description TEXT;

3691aced78a6389.png

就是这样!现在,请尝试检查它是否正常运行:

SELECT * FROM images;

您应该会看到新的说明列:

bed69d6ad0263114.png

写出 Gemini f(x)

注意:实际上,此函数是借助 Gemini Code Assist 创建的。

注意:创建此函数时,您可能会遇到 IAM 权限错误。下面的“可能的错误”段落中记录了其中一些错误。

  1. 启用 API
  2. 前往 https://console.cloud.google.com/functions/list
  3. 点击“创建函数”
  4. 通过 API 向导启用 API:

d22b82658cfd4c48.png

您可以通过界面或命令行创建 GCF。在这里,我们将使用命令行。

您可以在 .solutions/ 下找到可能的代码

  1. 创建一个用于托管代码的文件夹,例如“gcf/”。进入该文件夹。
  2. 创建 requirements.txt 文件:
google-cloud-storage
google-cloud-aiplatform
pymysql
  1. 创建一个 Python 函数。示例代码:gcf/main.py
#!/usr/bin/env python

"""Complete this"""

from google.cloud import storage
from google.cloud import aiplatform
import vertexai
from vertexai.generative_models import GenerativeModel, Part
import os
import pymysql
import pymysql.cursors

# Replace with your project ID
PROJECT_ID = "your-project-id"
GEMINI_MODEL = "gemini-1.5-pro-002"
DEFAULT_PROMPT = "Generate a caption for this image: "

def gemini_describe_image_from_gcs(gcs_url, image_prompt=DEFAULT_PROMPT):
    pass

def update_db_with_description(image_filename, caption, db_user, db_pass, db_host, db_name):
    pass

def generate_caption(event, context):
    """
    Cloud Function triggered by a GCS event.
    Args:
        event (dict): The dictionary with data specific to this type of event.
        context (google.cloud.functions.Context): The context parameter contains
                                                event metadata such as event ID
                                                and timestamp.
    """
    pass
  1. 推送函数。您可以使用类似于以下脚本的脚本:gcf/push-to-gcf.sh

注意 1。请务必使用正确的值获取 ENV,或直接在顶部添加它们 (GS_BUCKET=blah, …):

注意 2。这会推送所有本地代码 (.),因此请务必将代码封装在特定文件夹中,并像专业人士一样使用 .gcloudignore,以免推送巨大的库。(示例)。

#!/bin/bash

set -euo pipefail

# add your logic here, for instance:
source .env || exit 2 

echo "Pushing ☁️ f(x)☁ to 🪣 $GS_BUCKET, along with DB config.. (DB_PASS=$DB_PASS)"

gcloud --project "$PROJECT_ID" functions deploy php_amarcord_generate_caption \
    --runtime python310 \
    --region "$GCP_REGION" \
    --trigger-event google.cloud.storage.object.v1.finalized \
    --trigger-resource "$BUCKET" \
    --set-env-vars "DB_HOST=$DB_HOST,DB_NAME=$DB_NAME,DB_PASS=$DB_PASS,DB_USER=$DB_USER" \
    --source . \
    --entry-point generate_caption \
    --gen2

注意:在此示例中,generate_caption 将是被调用的方法,Cloud Functions 函数将将 GCS 事件及其所有相关信息(存储桶名称、对象名称等)传递给它。请花些时间调试该事件 Python 字典。

测试函数

单元测试

该函数包含许多动态部分。您可能希望能够测试所有单个用例。

如需查看示例,请参阅 gcf/test.py

Cloud Functions 界面

此外,请花些时间在界面中浏览一下您的函数。每个标签页都值得探索,尤其是 Source(我的最爱)、VariablesTriggerLogs;您将会花费大量时间在 Logs 中排查错误(另请参阅此页面底部的可能错误)。此外,请务必查看 Permissions

cf3ded30d532a2c7.png

端到端测试

现在,我们来手动测试该函数!

  1. 前往您的应用并登录
  2. 上传一张照片(不要太大,我们发现大图片会出现问题)
  3. 在界面上检查上传的图片。
  4. Cloud SQL Studio 中检查说明是否已更新。登录并运行此查询:SELECT * FROM images

43a680b12dbbdda0.png

效果非常好!我们还需要更新前端以显示该描述。

更新 PHP 以显示 [可选]

我们已证明该应用可以正常运行。不过,如果用户也能看到该说明就更好了。

您无需成为 PHP 专家,即可向 index.php 添加说明。以下代码应该可以解决问题(没错,Gemini 也帮我编写了它!):

<?php if (!empty($image['description'])): ?>
    <p class="font-bold">Gemini Caption:</p>
    <p class="italic"><?php echo $image['description']; ?></p>
<?php endif; ?>

您可以根据自己的喜好将此代码放置在 foreach 中。

在后续步骤中,我们还会看到一个更美观的界面版本,这得益于 Gemini Code Assist。美化后的版本可能如下所示:

fdc12de0c88c4464.png

总结

您有一个 Cloud Functions 函数会在有新对象存储到 GCS 时触发,该函数能够像人一样为图片内容添加注释,并自动更新数据库。哇哦!

接下来该做什么?您可以按照相同的推理来实现两个很棒的功能。

[可选] 添加其他 Cloud Functions 函数 [开放式]

我还想到了一些其他功能。

📩 电子邮件触发器

电子邮件触发器:每当有人发送照片时,系统都会向您发送一封电子邮件。

  • 是否过于频繁?添加进一步的约束条件:大图片,或 Gemini 内容包含“裸露/裸体/暴力”字样的图片。
  • 不妨参阅 EventArc 了解详情。

🚫? 自动审核不当照片

目前,人工管理员会将图片标记为“不当”。不妨让 Gemini 来帮您减负,管理聊天室。添加一个测试,用于标记不当的触发器内容并更新数据库,就像我们在前面的函数中学习的那样。这基本上意味着,使用之前的函数、更改提示,并根据回答更新数据库。

注意。生成式 AI 的输出不可预测。确保将 Gemini 中的“广告素材输出”放置在“轨道”上。您可以询问确定性答案,例如介于 0 到 1 之间的置信度得分、JSON 等。您可以通过多种方式实现此目的,例如:* 使用 Python 库 pydanticlangchain 等* 使用 Gemini 结构化输出

提示。您可以使用多个函数,也可以使用一个提示来强制要求回答 JSON 格式的问题(与上文中突出显示的“Gemini 结构化输出”搭配使用效果更佳),例如:

生成这类提示需要什么?

{
    "description": "This is the picture of an arrosticino",
    "suitable": TRUE
}

您可以在提示中添加其他字段,以获得相关洞见,例如:它有什么优点吗?对此有意见吗?您认得这个地方吗?是否包含文字(OCR 从未如此简单):

  • goods:“看起来很美味”
  • bads:“看起来像不健康的食物”
  • OCR: "Da consumare preferibilmente prima del 10 Novembre 2024"
  • location:“Pescara, Lungomare”

虽然针对 N 个结果使用 N 函数通常更好,但当一个模型完成 10 项任务时却获得了极大的奖励。请参阅 Riccardo 撰写的这篇文章,了解具体方法。

可能出现的错误(主要是 IAM / 权限)

在首次开发此解决方案时,我遇到了一些 IAM 权限问题。我会将这些信息添加到此处,以便同情您的感受,并提供一些解决方法。

错误:服务账号权限不足

  1. 请注意,如需部署监听 GCS 存储分区的 GCF 函数,您需要为用于作业的服务账号设置适当的权限,如下图所示:

22f51012fa6b4a24.png

您可能还需要启用 EventArc API,这些 API 可能需要几分钟才能完全可用。

错误:缺少 Cloud Run Invoker

  1. 界面中关于 GCF 权限的另一条评论如下(Cloud Run Invoker 角色):

be72e17294f2d3f3.png

可以通过在映像中运行命令来修复此错误(类似于 fix-permissions.sh),

有关此问题的说明,请访问:https://cloud.google.com/functions/docs/securing/authenticating

错误:超出内存上限

第一次运行它时,我的日志可以这样显示:“‘使用 270 MiB 时,已超出 244 MiB 的内存限制。Consider increasing the memory limit, see https://cloud.google.com/functions/docs/configuring/memory'"。再次将 RAM 添加到 GCF。在界面中执行此操作非常简单。可能存在的排名靠前:

bed69d6ad0263114.png

或者,您也可以修正 Cloud Run 部署脚本以提高 MEM/CPU。这需要多一点时间。

错误:PubSub 已发布

使用 GCF v1 创建触发器时,系统会显示以下错误:

e5c338ee35ad4c24.png

同样,您只需前往 IAM 并向您的服务账号授予“Pub/Sub Publisher”角色,即可轻松解决此问题。

错误:未使用 Vertex AI

如果您收到以下错误:

权限被拒:403 Vertex AI API 之前未用于项目 YOUR_PROJECT,或者已停用。如需启用此 API,请访问 https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOR_PROJECT

您只需启用 Vertex AI API 即可。启用所有需要的 API 的最简单方法是:

  1. https://console.cloud.google.com/vertex-ai
  2. 点击“启用所有推荐的 API”。

492f05ac377f3630

错误:未找到 EventArc 触发器。

如果您收到此消息,请重新部署函数。

8ec4fc11833d7420.png

错误:正在预配 400 个服务代理

系统正在预配 400 个服务代理 ( https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents)。服务代理需要读取所提供的 Cloud Storage 文件。请过几分钟再试。

如果出现这种情况,请稍等片刻或向 Google 员工寻求帮助。

10. 第 8 单元:创建可用性 SLO

在本章中,我们将尝试实现以下目标:

  1. 创建 SLI
  2. 根据 SLI 创建 SLO
  3. 根据 SLO 创建提醒

f63426182c052123.png

这个主题对作者来说非常重要,因为 Riccardo 从事 Google Cloud 的 SRE / DevOps 领域。

(开放式问题)为此应用创建 SLI 和 SLO

如果您无法判断应用何时宕机,那么该应用还有什么用?

什么是 SLO?

噢,太巧了!SLO 是 Google 发明的!若要深入了解该工具,建议您:

第 1 步:创建可用性 SLI/SLO

我们先从可用性 SLO 开始,因为它是您要衡量的最简单,也可能是最重要的指标。

幸运的是,Cloud Run 内置了 SLO 支持,这得益于 Istio

当应用在 Cloud Run 上运行后,这超级简单,需要 30 秒。

  • 前往 Cloud Run 页面。
  • 点击/选择您的应用。
  • 选择 SLOs 标签。
  • 点击“+ 创建服务等级目标”。
  • 可用性(基于请求)
  • 继续
  • 日历月 / 99%。
  • 点击“创建服务等级目标”。

e471c7ebdc56cdf6.png

第 2 步:针对此 SLO 设置提醒

我建议您创建 2 个提醒:

  1. 一个是消耗率较低的“Slowburn”,会通过电子邮件提醒您(模拟低优先级票券)。
  2. 一个烧毁率较高(“快速烧毁”),通过短信提醒您(模拟高优先级工单 / 寻呼器)

前往之前的 SLO tab

执行此操作两次:

314bfd6b9ef0a260.png

  • 点击“创建 SLO 提醒”(右侧带有加号的 🔔 按钮)
  • 回溯期、消耗率阈值:
  • [FAST]。第一种:60 分钟/10 x
  • [慢]。秒:720 分钟 / 2 x
  • 通知渠道:点击“管理通知渠道”
  • 首先,点击“电子邮件”->“添加新建”-> ..
  • 其次,选择“短信”->“新增”->“在手机上验证”。
  • 提示:我喜欢在名称中使用表情符号!演示时很有趣。
  • 完成后,点击右上角的“X”图标。
  • 先选择电话(速度快),然后选择电子邮件(速度慢)。
  • 添加一些示例文档,例如:
  • [PHP Amarcord] Riccardo told me to type sudo reboot or to check documentation in http://example.com/playbooks/1.php but I guess he was joking

答对了!

最终结果

当您有 1 个工作 SLO 和 2 次可用性提醒,并且它会通过您的电子邮件和手机发出提醒时,我们就可以认为这项练习结束了。

如果需要,您可以添加延迟时间(我们强烈建议您添加),甚至可以添加更复杂的延迟时间。对于延迟时间,请选择您认为合理的延迟时间;如果不确定,请选择 200 毫秒

11. 后续步骤

您已完成所有操作,还缺少什么?

一些值得思考的问题:

玩转 Gemini

Gemini 有两种版本:

  1. Vertex AI。“企业方式”与 GCP 交织在一起,我们已在第 7 章 (GCF+Gemini) 中对此进行了介绍。所有身份验证都会神奇地正常运行,服务之间会完美互联。
  2. Google AI。“消费者方式”。从此处获取 Gemini API 密钥,然后开始构建小脚本,这些脚本可以关联到已有的工作负载(专有工作、其他云、本地主机等)上。您只需替换 API 密钥,代码就会神奇地开始运行。

我们建议您尝试使用自己的小项目探索 (2)。

界面提升

我不擅长界面设计。但 Gemini 可以!您只需使用一个 PHP 页面,然后说出类似以下内容即可:

I have a VERY old PHP application. I want to touch it as little as possible. Can you help me:

1. add some nice CSS to it, a single static include for tailwind or similar, whatever you prefer
2. Transform the image print with description into cards, which fit 4 per line in the canvas?

Here's the code:

-----------------------------------
[Paste your PHP page, for instance index.php - mind the token limit!]

只需一个 Cloud Build 即可轻松实现,整个流程不到 5 分钟!:)

Gemini 的回答非常完美(也就是说,我无需进行任何更改):

8a3d5fe37ec40bf8.png

以下是作者个人应用中的新布局:

81620eb90ae3229a.png

注意:代码以图片形式粘贴,因为我们并不想鼓励您直接使用代码,而是为了让 Gemini 为您编写代码,同时保持您对广告素材界面/前端的限制;相信我,您之后只能进行非常小的更改。

安全性

本 4 小时工作坊的目标并非妥善保护此应用。

如需获取一些想法,请查看 SECURITY doc

12. 恭喜!

恭喜 🎉?🎉?🎉?,您已成功使用 Google Cloud 对旧版 PHP 应用进行了现代化改造。

24cb9a39b1841fbd.png

总的来说,在此 Codelab 中,您学习了以下内容:

  • 如何在 Google Cloud SQL 中部署 MYSQL 数据库,以及如何将现有数据库迁移到其中。
  • 如何使用 Docker 和 Buildpack 将 PHP 应用容器化,并将其映像存储到 Google Cloud Artifact Registry
  • 如何将容器化应用部署到 Cloud Run 并使用 Cloud SQL 运行该应用
  • 如何使用 Google Secret Manager 秘密存储/使用敏感配置参数(例如数据库密码)
  • 如何使用 Google Cloud Build 设置 CI/CD 流水线,以便在每次有代码推送到 GitHub 代码库时自动构建和部署 PHP 应用。
  • 如何使用 Cloud Storage 将应用资源“云化”
  • 如何利用无服务器技术在 Google Cloud 之上构建出色的工作流,而无需更改应用代码。
  • 针对合适的应用场景使用 Gemini 多模态功能。

开启 Google Cloud 应用现代化改造之旅,开启美好的开始!

🔁 反馈

如果您想告诉我们您在参加此研讨会时的体验,不妨填写此反馈表单

我们欢迎您提供反馈以及特别引以为豪的代码段的公关

🙏? 谢谢

作者想感谢来自 Datatonic 的 Mirko Gilioli 和 Maurizio Ipsale,他们在撰写本文档和测试解决方案方面提供了帮助。