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 可以与托管在 GitHub 或 GitLab 等热门 Git 提供商上的 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,并且受到组织政策的限制,无法完成此 Codelab。我们建议您创建一个新的 Gmail 账号,或者使用之前未接触过 GCP 的现有 Gmail 账号 (gmail.com)。

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

331658dc50213403.png

在以下表单中填写您的姓氏和名字,然后同意条款及条件。

您可能需要等待几秒钟,结算账号才会显示在此处: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.png

从 GitHub 分叉应用

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

734e51bfc29ee5df.png

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

40f5977ea4c1d1cb.png

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

a4e5ffb3e9a35e84.png

如需直观地实现此操作,请点击“打开文件夹”,然后选择文件夹(可能是主文件夹中的 app-mod-workshop)。

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 版本: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. 点击“Networking”标签页。
  4. 点击“已获授权的网络”下方的相应位置。现在,添加网络(即子网)。
  • 现在,我们选择快速但不安全的设置,以便应用正常运行。您可能需要稍后将其限制为仅允许可信 IP 访问:
  • 名称:“Everyone in the world - INSECURE”。
  • 网络:“0.0.0.0/0"(注意:这是不安全的部分!)
  • 点击“完成”
  1. 点击“保存”。

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

5ccb9062a7071964.png

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

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

我们来看看之前创建的 image_catalog 用户是否可用。

访问实例中的“Cloud SQL Studio”,然后输入要进行身份验证的数据库、用户和密码,如下所示:

d56765c6154c11a4.png

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

从代码库导入数据库

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

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

65ba01e4c6c2dac0.png

您可以在编辑器中运行以下代码进行测试:select * from images;

此外,请务必记下 Cloud SQL 实例的公共 IP 地址,您稍后会用到它。如需获取 IP,请前往 概览页面下的 Cloud SQL 实例主页面。(“概览”>“连接到此实例”>“公共 IP 地址”)。

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

e7f0e9979d8805f5.png

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

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

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

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

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

如果您选择使用 Cloud Shell,请在此时重新打开它(点击 Cloud 控制台右上角)。

ec6a6b90b39e03e.png

这应该会在页面底部打开一个方便的 Shell,您应该已在设置步骤中将代码分叉到该 Shell 中。

6999b906c0dedeb7.png

Docker

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

由于我们最终希望将容器化应用部署到 Cloud Run,因此请参阅以下文档。您如何将其从 PHP 8 向后移植到 PHP 5.7?您或许可以使用 Gemini 来解决此问题。或者,您也可以使用此预先编译的版本:

fbd8c2ace2faa70b.png

最新的 Dockerfile 版本可在此处找到。

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

<?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();
?>
  • DB_HOST 是 Cloud SQL 公共 IP 地址,您可以在 SQL 控制台中找到它:

bd27071bf450a8d0.png

  • DB_NAME 应保持不变:image_catalog
  • DB_USER 应为 appmod-phpapp-user
  • DB_PASS 是您选择的。使用单引号进行设置,并根据需要进行转义。

此外,您还可以随时使用 Gemini 将少数 🇮?🇹? 意大利语内容翻译成英语!

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

如果您尚未安装 Docker,请安装(链接)。如果您使用的是 Cloud Shell,则无需执行此操作(是不是很酷?)。

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

# Build command - don't forget the final . This works if Dockerfile is inside the code folder:
$ docker build -t my-php-app-docker .   

# Local Run command: most likely ports will be 8080:8080
$ docker run -it -p <CONTAINER_PORT>:<LOCAL_MACHINE_PORT> my-php-app-docker

如果一切正常,您在连接到本地主机后应该会看到以下网页!现在,您的应用在端口 8080 上运行,点击“网页预览”图标(带有眼睛的浏览器),然后点击在端口 8080 上预览(如需使用任何其他端口,请点击“更改端口”)

33a24673f4550454.png

在浏览器中测试结果

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

2718ece96b1f18b6.png

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

68b62048c2e86aea.png

太棒了!除了意大利语文本外,其他都正常!🎉🎉🎉

如果您的 Docker 容器化设置正确无误,但数据库凭据有误,您可能会收到如下错误消息:

e22f45b79bab86e1.png

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

保存到 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 tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
  • docker push TARGET_IMAGE[:TAG]

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

1e498feb4e88be9f.png

太棒了!🎉?🎉?🎉?您可以进入下一级了。在此之前,不妨花 2 分钟时间尝试上传/登录/退出登录,并熟悉应用端点。您稍后需要用到这些端点。

可能出现的错误

如果您收到容器化错误,请尝试使用 Gemini 来解释和修复错误,并提供以下信息:

  • 您当前的 Dockerfile
  • 收到的错误
  • [如果需要] 要执行的 PHP 代码。

上传权限。您还可以尝试使用 /upload.php 端点并上传一张照片。您可能会收到以下错误。如果是,您需要在 Dockerfile 中执行一些 chmod/chown 修复。

警告:move_uploaded_file(uploads/image (3).png):无法打开数据流:/var/www/html/upload.php 中第 11 行中的权限被拒绝

PDOException“找不到驱动程序”(或“Errore di connessione: could not find driver”)确保您的 Dockerfile 包含适用于 mysql (pdo_mysql) 的正确 PDO 库,以便连接到数据库。您可以点击此处,从解决方案中获得灵感。

无法将您的请求转发到后端。无法连接到端口 8080 上的服务器。这意味着您可能公开了错误的端口。确保您公开的是 Apache/Nginx 实际提供服务的端口。这并非易事。如果可能,请尝试将该端口设为 8080(这样可以更轻松地使用 Cloud Run)。如果您想保留端口 80(例如,因为 Apache 希望这样),请使用其他命令运行它:

$ docker run -it -p 8080:80 # force 80

# Use the PORT environment variable in Apache configuration files.

# https://cloud.google.com/run/docs/reference/container-contract#port

RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf

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

9ffca42774f6c5d1.png

为何选择 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 cloudbuild.googleapis.com

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

通过 gcloud 将应用部署到 Cloud Run

用于在 Cloud Run 上部署应用的命令是 gcloud run deploy。您可以通过设置多种选项来实现自己的目标。最少需要提供以下一组选项(您可以通过命令行提供,也可以通过交互式提示获取):

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

请参阅文档(或向下滚动查看可能的解决方案),了解如何将此选项应用于命令行。

部署需要几分钟时间。如果一切正确无误,您应该会在 Google Cloud 控制台中看到如下内容。

ef1029fb62f8de81.png

f7191d579c21ca3e.png

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

d571a90cd5a373f9.png

不带参数的“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 with options found so far
  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') ?: 'localhost';
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: 'wrong_password';
// 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 变量的方法。这可以通过以下几种方式实现:

  • 在 Dockerfile 的构建时。使用语法 ENV DB_VAR=ENV_VAR_VALUE 将 4 个参数添加到之前的 Dockerfile 中。这会设置可在运行时替换的默认值。例如,只能在此处设置“DB_NAME”和“DB_USER”,不能在其他任何位置设置。
  • 运行时。您可以为 Cloud Run 设置这些变量,无论是通过 CLI 还是界面都可以。这是放置所有 4 个变量的位置(除非您想保留 Dockerfile 中设置的默认值)。

在 localhost 中,您可能需要将 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 等敏感信息。

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

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

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

6df83a1c3cb757f6.png

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

a96c312e2c098db1.png

  • 现在,点击“创建 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.png

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

da0ccd7af39b04ed.png

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

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

e89f9ca780169b6b.png

提示:Play 管理中心(界面)非常擅长指出权限问题。请花些时间浏览 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 文件”,其中包含构建和运行该应用所需的所有内容(即“build 工件”)。
  • 将此工件推送到 Artifact Registry (AR)。
  • 然后,为应用“php-amarcord”从 AR 向 Cloud Run 发出部署
  • 这将创建现有应用的新版本(“修订版本”),您可以将其视为包含新代码的层,我们会将其配置为在推送成功时将流量转移到新版本。

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

f30f42d4571ad5e2.png

我们如何实现这一切?

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

创建触发器(并关联代码库)

  • 前往 https://console.cloud.google.com/cloud-build/triggers
  • 点击“创建触发器”。
  • 编译:
  • 名称:on-git-commit-build-php-app 等有意义的名称
  • 事件:推送到分支
  • 来源:“关联新代码库”替代文本
  • 这会在右侧打开一个窗口:“关联代码库”
  • 来源提供方:“Github”(第一项)
  • “继续”
  • 点击“Authenticate”(验证身份)后,GitHub 上会打开一个窗口以进行跨平台身份验证。请按照流程操作,并耐心等待。如果您有许多代码库,则可能需要一些时间。
  • “Select repo”(选择代码库)选择您的账号/代码库,然后勾选“I understand...”(我了解...)部分。
  • 如果您收到错误:未针对您的任何代码库安装 GitHub 应用,请继续点击“安装 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,这样就可以轻松地在 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 时,您可以将环境(-dev、-prod)作为后缀注入到资源中,这样就更容易了。

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

a680e0f287dd2dfb.png

存储

dc3a4b8ea92aaef6.png

目前,该应用会将状态存储在 Docker 容器中。如果机器发生故障、应用崩溃,或者您只是推送了新修订版本,系统就会安排新的修订版本,并使用新的存储空间:🙈?

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

  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(类似于 /var/www/html/uploads/)执行 FUSE 挂载:

#!/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.png

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

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

70032b216afee2d7.png

刚刚发生了什么?

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

使用旧代码的旧应用仍在正常运行。借助全新的现代化堆栈,我们可以将应用中的所有图片放置在有状态的 Cloud 存储分区中。现在,您可以尽情发挥创意:

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

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

9. 第 7 单元:使用 Google Gemini 赋能您的应用

c00425f0ad83b32c.png

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

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

前提条件

在上一章中,我们通过模型解决方案在 GCS 上挂载了图片 /uploads/实际上将应用逻辑与图片存储分离开来。

此练习要求您:

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

设置 Cloud Functions 函数(使用 Python)

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

  • <event> 发生时 => 发送电子邮件
  • <event> 发生时 => 如果 <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

错误:超出内存上限

我第一次运行时,日志会显示:“内存用量已超出 244 MiB 的限制,达到 270 MiB。Consider increasing the memory limit, see https://cloud.google.com/functions/docs/configuring/memory'"。再次向 GCF 添加 RAM。在界面中执行此操作非常简单。可能出现以下问题:

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.png

错误:未找到 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 密钥,然后开始构建可与您现有的任何工作负载(专有工作、其他云、localhost 等)相关联的小脚本。只需替换您的 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 小时工作坊的目标不是妥善保护此应用,因为这会使完成本工作坊所需的时间增加 1-2 个数量级。

不过,这个主题非常重要!我们在 SECURITY 中收集了一些想法。

12. 恭喜!

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

24cb9a39b1841fbd.png

总结一下,在此 Codelab 中,您学习了以下内容:

  • 如何在 Google Cloud SQL 中部署数据库,以及如何将现有数据库迁移到其中。
  • 如何使用 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 中实施 SRE 原则

这对您开启 Google Cloud 应用现代化之旅来说是一个良好的开端!

🔁? 反馈

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

我们欢迎您针对自己特别满意的代码提供反馈,以及提交PR

🙏? 谢谢

作者衷心感谢 DatatonicMirko GilioliMaurizio Ipsale 在撰写本文档和测试解决方案方面的帮助。