监控和管理 Google Cloud 资源:实验室挑战赛
实验
20 分钟
universal_currency_alt
1 个点数
show_chart
入门级
info
此实验可能会提供 AI 工具来支持您学习。
此内容尚未针对移动设备进行优化。
为获得最佳体验,请在桌面设备上访问通过电子邮件发送的链接。
ARC101

概览
在实验室挑战赛中,我们会为您提供一个场景和一系列任务。您将使用从课程的各个实验中学到的技能自行确定如何完成这些任务,而不是按照分步说明进行操作。自动评分系统(显示在本页面中)会提供有关您是否已正确完成任务的反馈。
在您参加实验室挑战赛期间,我们不会再教授新的 Google Cloud 概念知识。您需要拓展所学的技能,例如通过更改默认值和查看并研究错误消息来更正您自己所犯的错误。
要想获得满分,您必须在该时间段内成功完成所有任务!
设置
点击“开始实验”按钮前的注意事项
请阅读以下说明。实验是计时的,并且您无法暂停实验。计时器在您点击开始实验后即开始计时,显示 Google Cloud 资源可供您使用多长时间。
此实操实验可让您在真实的云环境中开展实验活动,免受模拟或演示环境的局限。为此,我们会向您提供新的临时凭据,您可以在该实验的规定时间内通过此凭据登录和访问 Google Cloud。
为完成此实验,您需要:
- 能够使用标准的互联网浏览器(建议使用 Chrome 浏览器)。
注意:请使用无痕模式(推荐)或无痕浏览器窗口运行此实验。这可以避免您的个人账号与学生账号之间发生冲突,这种冲突可能导致您的个人账号产生额外费用。
注意:请仅使用学生账号完成本实验。如果您使用其他 Google Cloud 账号,则可能会向该账号收取费用。
挑战场景
您刚开始担任初级云工程师一职。目前,您主要协助各团队创建和管理 Google Cloud 资源。
您应该掌握了完成这些任务所需的技能和知识。
您的挑战
您需要帮助新组建的开发团队完成一个新项目的一些初始工作。这个项目名为“Travel”,围绕旅行照片的存储和整理展开。您的任务是协助 Travel 团队初步配置他们的应用开发环境。
您需要执行的操作:
- 创建一个 Cloud Storage 存储桶并与另一个用户共享。
- 创建一个 Pub/Sub 主题,供 Cloud Run 函数发送消息。
- 创建一个 Cloud Run 函数,每当 Cloud Storage 存储桶中创建了新对象时,该函数即会执行。
- 创建提醒政策,以发送有关活跃 Cloud Run 函数实例数量的通知邮件。
您应当遵循如下标准:
- 除非另有指示,否则应在 区域中创建所有资源。
- 使用项目 VPC。
- 资源通常采用“team-resource”格式命名,例如,实例可以命名为 kraken-webserver1。
- 分配经济实惠的资源容量。各个项目会受到监控,过度使用资源会导致其所属的项目终止(可能包括您的项目),因此请务必仔细规划。这是监控团队分享的指南:除非另有指示,否则请为小型 Linux 虚拟机使用 f1-micro,为 Windows 或其他应用(例如 Kubernetes 节点)使用 e2-medium。
下文详细说明了您的每项任务,祝您好运!
任务 1. 创建存储桶
-
在 区域中创建一个名为 的存储桶来存储照片。
-
向此新存储桶所属项目中的 授予 Storage Object Viewer 角色。
点击“检查我的进度”以验证是否完成了以下目标:
创建名为 的存储桶,并向 授予访问权限。
任务 2. 创建 Pub/Sub 主题
- 创建名为 的 Pub/Sub 主题,供 Cloud Run 函数发送消息。
点击“检查我的进度”以验证是否完成了以下目标:
创建名为 的 Pub/Sub 主题。
任务 3. 创建缩略图 Cloud Run 函数
-
创建名为 的第 2 代 Cloud Run 函数(使用 Node.js 22),确保每当任务 1 中创建的存储桶 中新增了对象时即执行该函数。
-
请确保将入口点(要执行的函数)设为 thumbnail,并将触发器设为 Cloud Storage。
-
在 index.js 的第 15 行,将文本 REPLACE_WITH_YOUR_TOPIC ID 替换为您在任务 2 中创建的 。
index.js:
/* globals exports, require */
//jshint strict: false
//jshint esversion: 6
"use strict";
const crc32 = require("fast-crc32c");
const { Storage } = require('@google-cloud/storage');
const gcs = new Storage();
const { PubSub } = require('@google-cloud/pubsub');
const imagemagick = require("imagemagick-stream");
exports.thumbnail = (event, context) => {
const fileName = event.name;
const bucketName = event.bucket;
const size = "64x64"
const bucket = gcs.bucket(bucketName);
const topicName = "REPLACE_WITH_YOUR_TOPIC ID";
const pubsub = new PubSub();
if ( fileName.search("64x64_thumbnail") == -1 ){
// doesn't have a thumbnail, get the filename extension
var filename_split = fileName.split('.');
var filename_ext = filename_split[filename_split.length - 1];
var filename_without_ext = fileName.substring(0, fileName.length - filename_ext.length );
if (filename_ext.toLowerCase() == 'png' || filename_ext.toLowerCase() == 'jpg'){
// only support png and jpg at this point
console.log(`Processing Original: gs://${bucketName}/${fileName}`);
const gcsObject = bucket.file(fileName);
let newFilename = filename_without_ext + size + '_thumbnail.' + filename_ext;
let gcsNewObject = bucket.file(newFilename);
let srcStream = gcsObject.createReadStream();
let dstStream = gcsNewObject.createWriteStream();
let resize = imagemagick().resize(size).quality(90);
srcStream.pipe(resize).pipe(dstStream);
return new Promise((resolve, reject) => {
dstStream
.on("error", (err) => {
console.log(`Error: ${err}`);
reject(err);
})
.on("finish", () => {
console.log(`Success: ${fileName} → ${newFilename}`);
// set the content-type
gcsNewObject.setMetadata(
{
contentType: 'image/'+ filename_ext.toLowerCase()
}, function(err, apiResponse) {});
pubsub
.topic(topicName)
.publisher()
.publish(Buffer.from(newFilename))
.then(messageId => {
console.log(`Message ${messageId} published.`);
})
.catch(err => {
console.error('ERROR:', err);
});
});
});
}
else {
console.log(`gs://${bucketName}/${fileName} is not an image I can handle`);
}
}
else {
console.log(`gs://${bucketName}/${fileName} already has a thumbnail`);
}
};
package.json:
{
"name": "thumbnails",
"version": "1.0.0",
"description": "Create Thumbnail of uploaded image",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@google-cloud/pubsub": "^2.0.0",
"@google-cloud/storage": "^5.0.0",
"fast-crc32c": "1.0.4",
"imagemagick-stream": "4.1.1"
},
"devDependencies": {},
"engines": {
"node": ">=4.3.2"
}
}
注意:
您必须向存储桶上传一张 JPG 或 PNG 图片,以验证是否创建了缩略图(在成功创建相应函数后)。您可以使用位于 https://storage.googleapis.com/cloud-training/arc101/travel.jpg 的图片。如果使用此图片,需要先将图片下载到您的计算机,然后将该图片文件上传到您的存储桶。
您很快就会看到一张缩略图(可点击存储桶详情页面中的刷新手动更新)。
上传图片文件后,您可以点击下方链接检查进度,无需等待系统创建缩略图。
注意:如果函数已成功部署,但您未在存储桶中看到缩略图,可以检查触发器标签页中是否显示了您之前为该函数提供的触发器信息。如果您之前遇到过错误,该信息可能未正确保存。
如果您在函数的触发器标签页中未看到 Cloud Storage 触发器,可以重新创建触发器(请参阅标题为为服务创建触发器的文档页面),然后重新上传新文件,再次进行测试(请在添加新文件后刷新页面)。
点击“检查我的进度”以验证是否完成了以下目标:
验证 Cloud Run 函数是否正常工作。
任务 4. 创建提醒政策
-
创建名为 Active Cloud Run Function Instances 的提醒政策,当活跃 Cloud Run 函数实例数大于零 (0) 时,向您的个人邮箱账号发送通知。
-
对于指标,请务必选择 Cloud Functions 函数 > 函数 > 活跃实例。
点击“检查我的进度”以验证是否完成了以下目标:
验证是否已创建 Cloud Run 函数提醒。
恭喜!

赢得您的下一个技能徽章
本自学实验是监控和管理 Google Cloud 资源技能徽章课程的组成部分。完成此技能徽章课程可赢得上面的徽章,以表彰您取得的成就。您可以在简历和社交平台中分享自己的徽章,并使用 #GoogleCloudBadge 让大家知道您取得的这一成就。
Google Cloud 培训和认证
…可帮助您充分利用 Google Cloud 技术。我们的课程会讲解各项技能与最佳实践,可帮助您迅速上手使用并继续学习更深入的知识。我们提供从基础到高级的全方位培训,并有点播、直播和虚拟三种方式选择,让您可以按照自己的日程安排学习时间。各项认证可以帮助您核实并证明您在 Google Cloud 技术方面的技能与专业知识。
本手册的最后更新时间:2025 年 3 月 10 日
本实验的最后测试时间:2025 年 3 月 10 日
版权所有 2026 Google LLC 保留所有权利。Google 和 Google 徽标是 Google LLC 的商标。其他所有公司名和产品名可能是其各自相关公司的商标。