从 EBS 快照恢复文件

LinuxBeginner
立即练习

简介

一份报告文件被删除了,团队需要从经过测试的备份中恢复它。你将准备模拟报告数据,创建 EBS 快照,有意删除本次练习的文件,再将文件原来的内容恢复到一个新卷中。清理资源前,你将验证应用返回的报告已恢复。

你应当已经了解如何创建、连接、格式化和挂载 EBS 数据卷。这个独立环境提供自己的镜像、网络和密钥对,不会复用之前实验的资源。

认证备考关联

快照备份与恢复有助于理解 AWS Certified Cloud Practitioner CLF-C02 第 3 领域目标中任务 3.6 的存储概念。

启动恢复服务器

本步骤中,你将启动应用实例并确认其可用区。

在工作目录中开始,加载提供的资源 ID:

cd /home/labex/project
source launch.env

启动一台名为 recovery-server 的实例。镜像已经包含报告应用,你的任务是为它提供数据卷:

aws ec2 \
  run-instances \
  --image-id "$AMI_ID" \
  --instance-type t3.micro \
  --subnet-id "$SUBNET_ID" \
  --security-group-ids "$SECURITY_GROUP_ID" \
  --key-name report-key \
  --count 1 \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=recovery-server}]'

通过名称标签获取实例 ID:

INSTANCE_ID=$(aws ec2 \
  describe-instances \
  --filters Name=tag:Name,Values=recovery-server \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --output text)

等待实例进入运行状态:

aws ec2 \
  wait instance-running \
  --instance-ids "$INSTANCE_ID"

可用区是一个区域内相互隔离的位置。EBS 卷需要连接到同一可用区的实例。请查询实例的可用区,而不是凭空猜测:

AVAILABILITY_ZONE=$(aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[0].Instances[0].Placement.AvailabilityZone' \
  --output text)

查看状态与可用区:

aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name,Zone:Placement.AvailabilityZone}'

确认状态为 running。打开 AWS View,点击 Refresh resources,选择 recovery-server,再点击 Check application。添加存储前,确认返回 HTTP 200。

准备源报告

本步骤中,你将创建原始数据卷,并写入需要备份的模拟报告。

Amazon EBS 为 EC2 提供块存储。卷是一种类似磁盘的资源,而文件系统负责组织磁盘上的文件。连接卷会让块设备可用,但不会创建文件系统。EBS 卷指南介绍了卷的连接和持久性。

创建一个小型、空白的通用 SSD 卷。gp3 指定卷类型,--size 1 请求 1 GiB 容量,可用区变量将其放在实例所在的可用区。保存其 ID,供后续操作使用:

VOLUME_ID=$(aws ec2 \
  create-volume \
  --availability-zone "$AVAILABILITY_ZONE" \
  --size 1 \
  --volume-type gp3 \
  --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=source-report}]' \
  --query 'VolumeId' \
  --output text)

等待新卷可用:

aws ec2 \
  wait volume-available \
  --volume-ids "$VOLUME_ID"

使用 API 设备名称 /dev/sdf 连接它:

aws ec2 \
  attach-volume \
  --volume-id "$VOLUME_ID" \
  --instance-id "$INSTANCE_ID" \
  --device /dev/sdf

等待连接完成:

aws ec2 \
  wait volume-in-use \
  --volume-ids "$VOLUME_ID"

查看卷与连接信息:

aws ec2 \
  describe-volumes \
  --volume-ids "$VOLUME_ID" \
  --query 'Volumes[].{Volume:VolumeId,State:State,Zone:AvailabilityZone,Size:Size,Type:VolumeType,Attachments:Attachments}'

确认状态为 in-use、大小为 1、类型为 gp3,并已连接到你的实例。刷新 AWS View 并查看卷所在行。根卷与新建的数据卷是分开的。

获取实例当前的公网地址:

PUBLIC_IP=$(aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

使用提供的 SSH 配置连接:

ssh -F ssh_config ubuntu@"$PUBLIC_IP"

在实例内查看新连接的设备。本实验中的 Linux 设备名称是 /dev/xvdf,可能与 API 连接时使用的名称不同。其他 EC2 镜像可能使用 NVMe 名称,因此操作前必须辨认磁盘。官方 Linux 卷准备指南解释了这种区别。

lsblk -f /dev/xvdf

确认设备尚无文件系统类型。仅在这个新建且为空的数据卷上创建 ext4 文件系统。格式化已有数据的卷会删除其中的数据:

sudo mkfs.ext4 /dev/xvdf

挂载点是访问文件系统所使用的目录。将新文件系统挂载到报告应用已经准备好的目录:

sudo mount /dev/xvdf /srv/reports

确认源设备、文件系统和挂载点:

findmnt /srv/reports

检查 /dev/xvdf、ext4 和 /srv/reports。创建一份包含模拟数据的 CSV 报告。sudo tee 写入管理员拥有的文件系统;带引号的 here-document 分隔符让两行内容保持原样:

sudo tee /srv/reports/report.csv <<'CSV'
period,total
Q1,320
CSV

读回文件:

cat /srv/reports/report.csv

返回 LabEx 终端:

exit

在 AWS View 中选择 recovery-server,点击 Read volume report。确认返回 HTTP 200,并包含 CSV 文本 period,total 和 Q1,320。这个响应说明应用能够读取挂载卷中的文件。

本实验采用手动挂载。重启不会自动恢复手动挂载;生产环境通常在测试条目后,将文件系统 UUID 配置到 /etc/fstab。

创建一致的快照

本步骤中,你将暂停文件系统访问,并备份源卷。

EBS 快照是卷在某个时间点的备份。备份必须包含需要的数据,不能仅凭资源状态成功就认为备份可用。快照创建指南中,AWS 建议暂停写入或卸载卷,以保证一致性。本实验会在备份前卸载数据文件系统。

连接到实例:

ssh -F ssh_config ubuntu@"$PUBLIC_IP"

卸载源文件系统,刷新写入并停止文件系统访问:

sudo umount /srv/reports

返回 LabEx 终端:

exit

为源卷创建快照。保存它的 ID,并将其标记为 report-backup:

SNAPSHOT_ID=$(aws ec2 \
  create-snapshot \
  --volume-id "$VOLUME_ID" \
  --description 'Report before accidental deletion' \
  --tag-specifications 'ResourceType=snapshot,Tags=[{Key=Name,Value=report-backup}]' \
  --query 'SnapshotId' \
  --output text)

快照创建是异步操作。等待其完成:

aws ec2 \
  wait snapshot-completed \
  --snapshot-ids "$SNAPSHOT_ID"

查看快照状态与源卷:

aws ec2 \
  describe-snapshots \
  --snapshot-ids "$SNAPSHOT_ID" \
  --query 'Snapshots[].{Snapshot:SnapshotId,State:State,SourceVolume:VolumeId}'

确认状态为 completed,且源卷符合预期。刷新 AWS View 查看快照。接下来会有意删除文件,再通过恢复来测试备份内容。

观察文件误删的影响

本步骤中,你将从源卷删除模拟报告,并观察应用缺少报告时的表现。

重新连接并挂载原始卷:

ssh -F ssh_config ubuntu@"$PUBLIC_IP"
sudo mount /dev/xvdf /srv/reports

只删除你为本次练习创建的模拟文件:

sudo rm /srv/reports/report.csv

返回 LabEx 终端:

exit

在 AWS View 中选择 recovery-server,点击 Read volume report。请求仍应返回 HTTP 200,但 report 现在为 null。应用仍在运行,只是它需要的文件不存在。这能帮助区分存储内容问题与服务器停止问题。

快照创建于删除之前。它可以提供一个包含原有报告的新卷,而无需修改原始卷。

从快照恢复新卷

本步骤中,你将把备份恢复到一个独立卷,并让应用改用恢复后的文件系统。

恢复会创建新卷,而不是撤销现有卷中的更改。使用已完成的快照,在实例所在的可用区创建替代卷。官方恢复指南介绍了这种替换流程:

RESTORED_VOLUME_ID=$(aws ec2 \
  create-volume \
  --availability-zone "$AVAILABILITY_ZONE" \
  --snapshot-id "$SNAPSHOT_ID" \
  --volume-type gp3 \
  --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=recovered-report}]' \
  --query 'VolumeId' \
  --output text)

等待它准备就绪:

aws ec2 \
  wait volume-available \
  --volume-ids "$RESTORED_VOLUME_ID"

将它连接为第二个数据设备:

aws ec2 \
  attach-volume \
  --volume-id "$RESTORED_VOLUME_ID" \
  --instance-id "$INSTANCE_ID" \
  --device /dev/sdg
aws ec2 \
  wait volume-in-use \
  --volume-ids "$RESTORED_VOLUME_ID"

查看替代卷与快照的关联:

aws ec2 \
  describe-volumes \
  --volume-ids "$RESTORED_VOLUME_ID" \
  --query 'Volumes[].{Volume:VolumeId,State:State,Snapshot:SnapshotId}'

确认状态为 in-use,且快照 ID 与保存的 ID 一致。连接实例以切换应用挂载:

ssh -F ssh_config ubuntu@"$PUBLIC_IP"

卸载原始文件系统:

sudo umount /srv/reports

查看恢复后的设备,本实验中为 /dev/xvdg:

sudo lsblk -f /dev/xvdg

它已经包含从备份复制的 ext4 文件系统。不要格式化这个设备:格式化会覆盖恢复的数据。将现有文件系统挂载到应用的报告目录:

sudo mount /dev/xvdg /srv/reports

确认当前使用的源设备:

findmnt /srv/reports

检查 /dev/xvdg。读取恢复后的报告:

cat /srv/reports/report.csv

应当看到原来的两行内容:period,total 和 Q1,320。返回 LabEx 终端:

exit

在 AWS View 中点击 Refresh resources,选择 recovery-server,再点击 Read volume report。确认 HTTP 200 和原始 CSV 文本。成功的恢复测试证明这个备份包含可用的应用数据。

删除恢复资源

本步骤中,你将清理两个数据卷、快照和实例。

连接实例并卸载恢复后的文件系统:

ssh -F ssh_config ubuntu@"$PUBLIC_IP"
sudo umount /srv/reports
exit

分离恢复后的卷:

aws ec2 \
  detach-volume \
  --volume-id "$RESTORED_VOLUME_ID" \
  --instance-id "$INSTANCE_ID" \
  --device /dev/sdg
aws ec2 \
  wait volume-available \
  --volume-ids "$RESTORED_VOLUME_ID"

源文件系统已在恢复时卸载,也将其卷分离:

aws ec2 \
  detach-volume \
  --volume-id "$VOLUME_ID" \
  --instance-id "$INSTANCE_ID" \
  --device /dev/sdf
aws ec2 \
  wait volume-available \
  --volume-ids "$VOLUME_ID"

删除两个已分离的练习卷:

aws ec2 \
  delete-volume \
  --volume-id "$RESTORED_VOLUME_ID"
aws ec2 \
  delete-volume \
  --volume-id "$VOLUME_ID"

恢复测试完成后,删除练习备份:

aws ec2 \
  delete-snapshot \
  --snapshot-id "$SNAPSHOT_ID"

终止服务器并等待其最终状态:

aws ec2 \
  terminate-instances \
  --instance-ids "$INSTANCE_ID"
aws ec2 \
  wait instance-terminated \
  --instance-ids "$INSTANCE_ID"

确认实例已终止:

aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name}'

列出本次练习中带有指定名称的卷与备份:

aws ec2 \
  describe-volumes \
  --filters Name=tag:Name,Values=source-report,recovered-report \
  --query 'Volumes[].VolumeId'
aws ec2 \
  describe-snapshots \
  --filters Name=tag:Name,Values=report-backup \
  --query 'Snapshots[].SnapshotId'

两个列表都应为 []。刷新 AWS View,确认练习卷和快照已消失,服务器不再是运行中的目标。保留已准备的网络与密钥对。

总结

你使用 EBS 快照备份了报告卷,观察了删除文件的影响,并从备份恢复了一个独立卷。你没有格式化恢复设备,而是挂载其现有文件系统,验证了原始应用数据。最后,你删除了两个数据卷、快照和实例。