清理未使用的和孤立的永久性磁盘
实验
20 分钟
universal_currency_alt
5 个点数
show_chart
中级
info
此实验可能会提供 AI 工具来支持您学习。
此内容尚未针对移动设备进行优化。
为获得最佳体验,请在桌面设备上访问通过电子邮件发送的链接。
GSP648

概览
在本实验中,您将使用 Cloud Functions 和 Cloud Scheduler 来识别并清理浪费的云资源。在本例中,您将安排 Cloud Functions 函数来识别并清理未挂接的和孤立的永久性磁盘。
您将执行的操作
- 创建两个永久性磁盘。
- 创建使用其中一个磁盘的虚拟机。
- 从虚拟机分离磁盘。
- 查看 Cloud Functions 函数代码。
- 部署 Cloud Functions 函数。
- 使用 Cloud Scheduler 作业测试 Cloud Functions 函数。
架构
下图描述了本实验第一部分中使用的架构,在该架构中,您安排了一个 Cloud Functions 函数来识别并清理未使用的和孤立的永久性磁盘。

设置和要求
在本部分中,您将配置完成本实验所需的基础设施和身份。
点击“开始实验”按钮前的注意事项
请阅读以下说明。实验是计时的,并且您无法暂停实验。计时器在您点击开始实验后即开始计时,显示 Google Cloud 资源可供您使用多长时间。
此实操实验可让您在真实的云环境中开展实验活动,免受模拟或演示环境的局限。为此,我们会向您提供新的临时凭据,您可以在该实验的规定时间内通过此凭据登录和访问 Google Cloud。
为完成此实验,您需要:
- 能够使用标准的互联网浏览器(建议使用 Chrome 浏览器)。
注意:请使用无痕模式(推荐)或无痕浏览器窗口运行此实验。这可以避免您的个人账号与学生账号之间发生冲突,这种冲突可能导致您的个人账号产生额外费用。
注意:请仅使用学生账号完成本实验。如果您使用其他 Google Cloud 账号,则可能会向该账号收取费用。
如何开始实验并登录 Google Cloud 控制台
-
点击开始实验按钮。如果该实验需要付费,系统会打开一个对话框供您选择支付方式。左侧是“实验详细信息”窗格,其中包含以下各项:
- “打开 Google Cloud 控制台”按钮
- 剩余时间
- 进行该实验时必须使用的临时凭据
- 帮助您逐步完成本实验所需的其他信息(如果需要)
-
点击打开 Google Cloud 控制台(如果您使用的是 Chrome 浏览器,请右键点击并选择在无痕式窗口中打开链接)。
该实验会启动资源并打开另一个标签页,显示“登录”页面。
提示:将这些标签页安排在不同的窗口中,并排显示。
注意:如果您看见选择账号对话框,请点击使用其他账号。
-
如有必要,请复制下方的用户名,然后将其粘贴到登录对话框中。
{{{user_0.username | "<用户名>"}}}
您也可以在“实验详细信息”窗格中找到“用户名”。
-
点击下一步。
-
复制下面的密码,然后将其粘贴到欢迎对话框中。
{{{user_0.password | "<密码>"}}}
您也可以在“实验详细信息”窗格中找到“密码”。
-
点击下一步。
重要提示:您必须使用实验提供的凭据。请勿使用您的 Google Cloud 账号凭据。
注意:在本实验中使用您自己的 Google Cloud 账号可能会产生额外费用。
-
继续在后续页面中点击以完成相应操作:
- 接受条款及条件。
- 由于这是临时账号,请勿添加账号恢复选项或双重验证。
- 请勿注册免费试用。
片刻之后,系统会在此标签页中打开 Google Cloud 控制台。
注意:如需访问 Google Cloud 产品和服务,请点击导航菜单,或在搜索字段中输入服务或产品的名称。
激活 Cloud Shell
Cloud Shell 是一种装有开发者工具的虚拟机。它提供了一个永久性的 5GB 主目录,并且在 Google Cloud 上运行。Cloud Shell 提供可用于访问您的 Google Cloud 资源的命令行工具。
-
点击 Google Cloud 控制台顶部的激活 Cloud Shell
。
-
在弹出的窗口中执行以下操作:
- 继续完成 Cloud Shell 信息窗口中的设置。
- 授权 Cloud Shell 使用您的凭据进行 Google Cloud API 调用。
如果您连接成功,即表示您已通过身份验证,且项目 ID 会被设为您的 Project_ID 。输出内容中有一行说明了此会话的 Project_ID:
Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}
gcloud 是 Google Cloud 的命令行工具。它已预先安装在 Cloud Shell 上,且支持 Tab 自动补全功能。
- (可选)您可以通过此命令列出活跃账号名称:
gcloud auth list
- 点击授权。
输出:
ACTIVE: *
ACCOUNT: {{{user_0.username | "ACCOUNT"}}}
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- (可选)您可以通过此命令列出项目 ID:
gcloud config list project
输出:
[core]
project = {{{project_0.project_id | "PROJECT_ID"}}}
注意:如需查看在 Google Cloud 中使用 gcloud 的完整文档,请参阅 gcloud CLI 概览指南。
任务 1. 启用 API 并克隆代码库
-
在 Cloud Shell 中,启用 Cloud Scheduler API:
gcloud services enable cloudscheduler.googleapis.com
-
克隆代码库:
gsutil cp -r gs://spls/gsp648 . && cd gsp648
-
设置环境变量,并将代码库文件夹设为 $WORKDIR,在其中运行本实验相关的所有命令:
export PROJECT_ID=$(gcloud config list --format 'value(core.project)' 2>/dev/null)
WORKDIR=$(pwd)
-
设置本实验的项目区域:
gcloud config set compute/region {{{project_0.default_region | "REGION"}}}
-
为区域创建一个变量:
export REGION={{{project_0.default_region | Region}}}
-
为可用区创建一个变量:
export ZONE={{{project_0.default_zone | Zone}}}
参阅“区域和可用区”文档了解详情。
注意:当您在自己的机器上运行 gcloud 时,不同会话的配置设置保持不变。但在 Cloud Shell 中,您需要为每个新会话或在每次重新连接时设置配置。
任务 2. 创建永久性磁盘
-
在 Cloud Shell 中,前往 unattached-pd 目录:
cd $WORKDIR/unattached-pd
-
将磁盘的名称导出为变量:
export ORPHANED_DISK=orphaned-disk
export UNUSED_DISK=unused-disk
-
创建两个磁盘:
gcloud compute disks create $ORPHANED_DISK --project=$PROJECT_ID --type=pd-standard --size=500GB --zone=$ZONE
gcloud compute disks create $UNUSED_DISK --project=$PROJECT_ID --type=pd-standard --size=500GB --zone=$ZONE
本实验使用 区域,但您可以选择其他区域并在本实验的其余部分中始终引用该区域。
-
确认已创建两个磁盘:
gcloud compute disks list
输出应如下所示:
NAME LOCATION LOCATION_SCOPE SIZE_GB TYPE STATUS
orphaned-disk {{{project_0.default_zone | Zone}}} zone 500 pd-standard READY
unused-disk {{{project_0.default_zone | Zone}}} zone 500 pd-standard READY
验证您已完成的任务
点击检查我的进度可验证您已完成的任务。如果您已成功创建永久性磁盘,则会看到一个评估分数。
创建永久性磁盘
任务 3. 创建一个虚拟机并检查磁盘
-
在 Cloud Shell 中,创建一个实例:
gcloud compute instances create disk-instance \
--zone=$ZONE \
--machine-type=e2-medium \
--disk=name=$ORPHANED_DISK,device-name=$ORPHANED_DISK,mode=rw,boot=no
-
检查挂接到虚拟机的磁盘:
gcloud compute disks describe $ORPHANED_DISK --zone=$ZONE --format=json | jq
输出类似于以下内容:
{
"creationTimestamp": "2019-06-12T12:21:25.546-07:00",
"id": "7617542552306904666",
"kind": "compute#disk",
"labelFingerprint": "42WmSpB8rSM=",
"lastAttachTimestamp": "2019-06-12T12:24:53.989-07:00",
"name": "orphaned-disk",
"physicalBlockSizeBytes": "4096",
"selfLink": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}/disks/orphaned-disk",
"sizeGb": "500",
"status": "READY",
"type": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}/diskTypes/pd-standard",
"users": [
"https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}/instances/disk-instance"
],
"zone": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}"
}
在前面的代码示例中,以下内容至关重要:
-
users 标识附加磁盘的虚拟机。
-
lastAttachTimestamp 标识磁盘上次附加到虚拟机的时间。
验证您已完成的任务
点击检查我的进度可验证您已完成的任务。如果您已成功创建具有永久性磁盘的虚拟机实例,则会看到一个评估分数。
创建具有永久性磁盘的虚拟机实例
-
从虚拟机分离孤立的磁盘。
gcloud compute instances detach-disk disk-instance --device-name=$ORPHANED_DISK --zone=$ZONE
-
检查孤立的磁盘:
gcloud compute disks describe $ORPHANED_DISK --zone=$ZONE --format=json | jq
输出类似于以下内容:
{
"creationTimestamp": "2019-06-12T12:21:25.546-07:00",
"id": "7617542552306904666",
"kind": "compute#disk",
"labelFingerprint": "42WmSpB8rSM=",
"lastAttachTimestamp": "2019-06-12T12:24:53.989-07:00",
"lastDetachTimestamp": "2019-06-12T12:34:56.040-07:00",
"name": "orphaned-disk",
"physicalBlockSizeBytes": "4096",
"selfLink": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}/disks/orphaned-disk",
"sizeGb": "500",
"status": "READY",
"type": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}/diskTypes/pd-standard",
"zone": "https://www.googleapis.com/compute/v1/projects/automating-cost-optimization/zones/{{{project_0.default_zone | Zone}}}"
}
在前面的代码示例中,以下内容至关重要:
- 磁盘未列出
users,这表明该磁盘当前未被使用。
- 现在有一个
lastDetachTimestamp 条目,指示磁盘上次与虚拟机分离的时间,以及磁盘的最后一次使用时间。
-
lastAttachTimestamp 字段仍然存在。
验证您已完成的任务
点击检查我的进度可验证您已完成的任务。如果您已成功从虚拟机分离孤立的磁盘,则会看到一个评估分数。
从虚拟机分离孤立的永久性磁盘
任务 4. 查看 Cloud Functions 函数代码
-
在 Cloud Shell 中,输出检索项目中所有永久性磁盘的代码部分:
cat $WORKDIR/unattached-pd/main.py | grep "(request)" -A 12
输出如下所示:
def delete_unattached_pds(request):
# get list of disks and iterate through it:
disksRequest = compute.disks().aggregatedList(project=project)
while disksRequest is not None:
diskResponse = disksRequest.execute()
for name, disks_scoped_list in diskResponse['items'].items():
if disks_scoped_list.get('warning') is None:
# got disks
for disk in disks_scoped_list['disks']: # iterate through disks
diskName = disk['name']
diskZone = str((disk['zone'])).rsplit('/',1)[1]
print (diskName)
print (diskZone)
该函数使用 aggregatedList 方法获取 Google Cloud 项目(函数在该项目中运行,并迭代所有磁盘)中的所有永久性磁盘。
-
输出检查 lastAttachTimestamp 字段,并在该字段不存在的情况下删除磁盘的代码部分:
cat $WORKDIR/unattached-pd/main.py | grep "handle never" -A 11
输出如下所示:
# handle never attached disk - delete it
# lastAttachedTimestamp is not present
try:
if disk["lastAttachTimestamp"] is None:
print ("none!")
except KeyError:
print ("disk " + diskName + " was never attached - deleting")
deleteRequest = compute.disks().delete(project=project,
zone=diskZone, disk=diskName)
deleteResponse = deleteRequest.execute()
waitForZoneOperation(deleteResponse, project, diskZone)
print ("disk " + diskName + " was deleted")
continue
如果 lastAttachTimestamp 不存在(表示该磁盘从未被使用过),此部分将删除磁盘。
-
输出用于计算磁盘存在时间(如果是孤立的磁盘)、创建磁盘快照并删除磁盘的代码部分:
cat $WORKDIR/unattached-pd/main.py | grep "handle detached" -A 32
输出如下所示:
# handle detached disk - snapshot and delete
# lastAttachTimestamp is present AND users is not present
try:
if disk['users'] is None and disk['lastDetachTimestamp'] is not None:
print ("users is none")
except KeyError:
print ("disk " + diskName + " has no users and has been detached")
detachTimestamp = dateutil.parser.parse(disk['lastDetachTimestamp'])
detachedFor = pytz.utc.localize(datetime.utcnow()) - detachTimestamp
print ("disk has been detached for " + str(detachedFor))
# update this for your preferred age
if detachedFor.days > -1:
# take a snapshot
snapShotName = diskName + str(int(time.time()))
print ("taking snapshot: " + snapShotName)
snapshotBody = {
"name": snapShotName
}
snapshotRequest = compute.disks().createSnapshot(project=project,
zone=diskZone, disk=diskName, body=snapshotBody)
snapshotResponse = snapshotRequest.execute()
waitForZoneOperation(snapshotResponse, project, diskZone)
print ("snapshot completed")
# delete the disk
print ("deleting disk " + diskName)
deleteRequest = compute.disks().delete(project=project, zone=diskZone, disk=diskName)
deleteResponse = deleteRequest.execute()
waitForZoneOperation(deleteResponse, project, diskZone)
print ("disk " + diskName + " was deleted")
continue
如果磁盘确实列出了 users,并且存在 lastDetachTimestamp,将使用此部分代码,这意味着该磁盘当前未被使用,但在某些时候被使用过。在此情况下,Cloud Functions 函数将创建磁盘的快照以保留数据,然后删除该磁盘。
-
在 Cloud Shell 中,点击打开编辑器,以打开 Cloud Shell 编辑器来修改 main.py 文件。
注意:
如果出现提示,点击在新窗口中打开。
-
前往 gsp648/unattached-pd。
-
打开 main.py。
-
修改文件中的第 15 行,将 automating-cost-optimization 替换为您的项目 ID(应类似于以下内容):
project = '{{{ project_0.project_id | PROJECT ID}}}'
-
依次点击文件 > 保存,以保存该文件。
任务 5. 部署 Cloud Functions 函数
-
停用 Cloud Functions API:
gcloud services disable cloudfunctions.googleapis.com
-
重新启用 Cloud Functions API:
gcloud services enable cloudfunctions.googleapis.com
-
为您的 appspot 服务账号添加 artifactregistry.reader 权限。
gcloud projects add-iam-policy-binding {{{ project_0.project_id | PROJECT ID}}} \
--member="serviceAccount:{{{ project_0.project_id | PROJECT ID}}}@appspot.gserviceaccount.com" \
--role="roles/artifactregistry.reader"
-
在 Cloud Shell 中,部署 Cloud Functions 函数:
cd ~/gsp648/unattached-pd
gcloud functions deploy delete_unattached_pds --gen2 --trigger-http --runtime=python310 --region {{{project_0.default_region | Region}}}
注意:
当系统询问 Allow unauthenticated invocations of new function [delete_unattached_pds]? (y/N)? 时,请输入 y。
注意:
部署 Cloud Functions 函数可能需要 2-5 分钟,具体取决于区域。
-
将 Cloud Functions 函数的触发器网址设置为环境变量:
export FUNCTION_URL=$(gcloud functions describe delete_unattached_pds --format=json --region {{{project_0.default_region | Region}}} | jq -r '.url')
验证您已完成的任务
点击检查我的进度可验证您已完成的任务。如果您已成功部署 Cloud Functions 函数,则会看到一个评估分数。
部署 Cloud Functions 函数
任务 6. 安排并测试 Cloud Functions 函数
- 在 Cloud Shell 中,创建一个 App Engine 应用以使用 Cloud Scheduler:
gcloud app create --region={{{project_0.startup_script.app_region | REGION}}}
-
在 Cloud Shell 中,创建一项 Cloud Scheduler 任务,以在每天凌晨 2 点运行 Cloud Functions 函数:
gcloud scheduler jobs create http unattached-pd-job \
--schedule="* 2 * * *" \
--uri=$FUNCTION_URL \
--location=$REGION
验证您已完成的任务
点击检查我的进度可验证您已完成的任务。如果您已成功创建 Cloud Scheduler 任务来运行 Cloud Functions 函数,则会看到一个评估分数。
创建一项 Cloud Scheduler 任务来运行 Cloud Functions 函数
-
通过手动触发来测试该作业:
gcloud scheduler jobs run unattached-pd-job \
--location=$REGION
-
确认已创建孤立磁盘的快照:
gcloud compute snapshots list
输出类似于以下内容:
NAME DISK_SIZE_GB SRC_DISK STATUS
orphaned-disk1560455894 500 {{{project_0.default_zone | Zone}}}/disks/orphaned-disk READY
-
确认已删除未使用的磁盘和孤立的磁盘:
gcloud compute disks list
输出类似于以下内容:
NAME LOCATION LOCATION_SCOPE SIZE_GB TYPE STATUS
disk-instance {{{project_0.default_zone | Zone}}} zone 10 pd-standard READY
验证您已完成的任务
点击检查我的进度可验证您已完成的任务。如果您已通过手动触发成功测试了作业,则会看到一个评估分数。
通过手动触发来测试该作业
恭喜!
在本实验中,您完成了以下任务:
- 创建了两个永久性磁盘。
- 创建了使用其中一个磁盘的虚拟机。
- 从虚拟机分离了磁盘。
- 查看了 Cloud Functions 函数代码。
- 部署了 Cloud Functions 函数。
- 使用 Cloud Scheduler 作业测试了 Cloud Functions 函数。
Google Cloud 培训和认证
…可帮助您充分利用 Google Cloud 技术。我们的课程会讲解各项技能与最佳实践,可帮助您迅速上手使用并继续学习更深入的知识。我们提供从基础到高级的全方位培训,并有点播、直播和虚拟三种方式选择,让您可以按照自己的日程安排学习时间。各项认证可以帮助您核实并证明您在 Google Cloud 技术方面的技能与专业知识。
上次更新手册的时间:2025 年 11 月 14 日
上次测试实验的时间:2025 年 11 月 14 日
版权所有 2026 Google LLC 保留所有权利。Google 和 Google 徽标是 Google LLC 的商标。其他所有公司名和产品名可能是其各自相关公司的商标。