将应用文件存储在 EBS 卷上

AWSBeginner
立即练习

介绍

报表应用需要一个独立磁盘存放报表文件。你将创建 Amazon EBS 卷,将它连接到 EC2 实例,格式化并挂载文件系统,让应用从该卷提供报表。随后卸载、分离并删除自己创建的资源。

你应已了解 EC2 启动和 SSH。每个实验都从全新环境开始;这里提供独立的应用镜像、网络和密钥对。

认证备考关联

本实验练习为 EC2 工作负载选择块存储,对应 AWS Certified Cloud Practitioner CLF-C02 考试领域 3 中任务 3.6 的存储概念。

启动存储服务器

本步骤将启动应用实例,并查明其可用区。

进入工作目录,加载预置资源的 ID:

cd /home/labex/project
source launch.env

启动一个名为 storage-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=storage-server}]'

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

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

等待实例运行:

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

可用区(Availability Zone)是一个区域内相互隔离的位置。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,选择 storage-server,再点击 Check application。添加存储之前,确认 HTTP 200。

创建并连接数据卷

本步骤将创建独立的 EBS 数据卷,并连接到运行中的服务器。

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=report-data}]' \
  --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

挂载点(mount point)是访问文件系统所使用的目录。将新文件系统挂载到报表应用预置的目录:

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 中选择 storage-server,点击 Read volume report。确认 HTTP 200,以及 CSV 文本 period,total 和 Q1,320。这个响应证明应用能够从挂载卷读取文件。

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

卸载、分离和删除

本步骤将按受控顺序移除数据卷和应用实例。

首先重新连接应用实例:

ssh -F ssh_config ubuntu@"$PUBLIC_IP"

分离磁盘前先卸载文件系统。这会停止文件系统访问,并刷新尚未写入的数据:

sudo umount /srv/reports

确认已不再挂载:

findmnt /srv/reports

目录未挂载时,findmnt 不输出内容并返回非零退出状态,这是此处的预期结果。返回 LabEx 终端:

exit

只分离你的数据卷:

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 "$VOLUME_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}'

确认 terminated,再列出剩余卷:

aws ec2 \
  describe-volumes \
  --query 'Volumes[].{Volume:VolumeId,State:State}'

预期结果为 []:你已显式删除数据卷,这个实例的根卷也在终止时删除。刷新 AWS View,确认服务器不再是运行中的请求目标,卷列表为空。保留预置网络和密钥对。

总结

你在 EC2 实例的相同可用区创建并连接了 EBS 数据卷,为空卷创建文件系统并挂载给应用使用。验证真实报表响应后,你卸载、分离并删除数据卷,最后终止服务器。