介绍
上传应用运行在两台服务器上。它们目前分别将文件保存在本地磁盘,因此用户可能通过一台服务器上传成功,却在另一台服务器得到“文件不存在”。使用 Amazon Elastic File System(EFS)为两台服务器提供共享文件接口。
请先完成 AWS VPC 入门和 AWS EC2、EBS 入门。本独立环境提供上传应用、三台应用主机及其网络。在 Terminal 中执行 AWS CLI 和 SSH 命令,在 AWS View 中比较真实上传响应。CLI 已配置,无需个人 AWS 账号或之前实验的资源。本实验聚焦文件共享和连接,不测试生产性能或可用性。
认证关联
| 认证 | 考纲任务 | 实践 |
|---|---|---|
| Cloud Practitioner (CLF-C02) | Task 3.6 | 认识 EFS 共享文件服务,区分挂载的文件接口与各自独立的本地上传目录。 |

概念示意图;实际标识符以你的新环境为准。
为上传应用创建存储
本步骤先观察本地上传的问题,再创建共享文件系统。
在 /home/labex/project 中操作。确认配置的身份,不显示凭据:
cd /home/labex/project
aws sts \
get-caller-identity
用户 ARN 以 labex-fs01-operator 结尾。resources.json 记录准备好的子网和应用安全组。读取这些标识符,让后续命令使用当前环境的真实资源:
SUBNET_ID=$(jq -r .subnet_id resources.json)
APP_GROUP_ID=$(jq -r .application_group_id resources.json)
VPC_ID=$(jq -r .vpc_id resources.json)
echo "$SUBNET_ID"
echo "$APP_GROUP_ID"
echo "$VPC_ID"
aws ec2 \
describe-instances \
--filters Name=tag:Name,Values=application-a,application-b \
--query 'Reservations[].Instances[].{Name:Tags[?Key==`Name`].Value|[0],IP:PrivateIpAddress,State:State.Name}'
先观察本地存储问题。HTTP PUT 保存上传内容,HTTP GET 读取文件。以下地址连接准备好的应用服务器:
curl -i -X PUT --data-binary 'A local upload' \
http://127.0.0.1:8081/uploads/local-example.txt
curl -i http://127.0.0.1:8082/uploads/local-example.txt
A 返回 201 Created,B 返回 404 Not Found,因为 B 的本地目录包含另一组文件。也可以通过 AWS View 的两个应用卡片写入、读取同一文件名。
EFS 提供共享文件系统:两个应用通过网络文件系统协议 NFS 访问相同目录和文件。先创建文件系统。创建令牌标识这次创建请求,Name 标签便于检查和清理时识别资源。--encrypted 启用服务的静态加密设置;传输加密将在挂载时另行配置。
FS_ID=$(aws efs \
create-file-system \
--creation-token fs01-shared-uploads \
--encrypted \
--tags Key=Name,Value=fs01-shared-uploads \
--query FileSystemId --output text)
echo "$FS_ID"
aws efs \
describe-file-systems \
--file-system-id "$FS_ID" \
--query 'FileSystems[].{ID:FileSystemId,State:LifeCycleState,Encrypted:Encrypted}'
等待状态为 available 再继续。这说明服务资源已存在,但应用还需要可达的挂载目标和真正的挂载。
将文件系统连接到应用子网
本步骤提供可达的 NFS 端点,并将访问限制为应用服务器。
挂载目标提供文件系统在子网内的网络端点。NFS 使用 TCP 2049 端口。创建专用存储安全组,并允许准备好的应用安全组访问该端口。来源组规则包含两台应用服务器,不会向所有地址开放 NFS。无关参考服务器属于另一组,应继续被排除。
EFS_GROUP_ID=$(aws ec2 \
create-security-group \
--group-name fs01-efs-access \
--description 'NFS from the upload application servers' \
--vpc-id "$VPC_ID" \
--query GroupId --output text)
echo "$EFS_GROUP_ID"
aws ec2 \
authorize-security-group-ingress \
--group-id "$EFS_GROUP_ID" \
--ip-permissions "IpProtocol=tcp,FromPort=2049,ToPort=2049,UserIdGroupPairs=[{GroupId=$APP_GROUP_ID}]"
在准备好的应用子网中创建挂载目标,并绑定新的安全组:
MOUNT_TARGET_ID=$(aws efs \
create-mount-target \
--file-system-id "$FS_ID" \
--subnet-id "$SUBNET_ID" \
--security-groups "$EFS_GROUP_ID" \
--query MountTargetId --output text)
echo "$MOUNT_TARGET_ID"
aws efs \
describe-mount-targets \
--file-system-id "$FS_ID" \
--query 'MountTargets[].{ID:MountTargetId,IP:IpAddress,State:LifeCycleState,AZ:AvailabilityZoneName}'
aws efs \
describe-mount-target-security-groups \
--mount-target-id "$MOUNT_TARGET_ID"
等待挂载目标为 available。本实验将两台应用放在一个可用区,因此准备好的拓扑只需一个挂载目标。生产区域部署应为客户端所在的各可用区规划挂载目标。
挂载两个应用并观察共享文件
本步骤将两个应用连接到 EFS,测试双向上传。
提供的 ssh_config 用于连接各应用主机。挂载点是应用访问远程文件系统的本地目录。在两台主机上创建 /srv/shared,并将 EFS 根目录挂载到这里:
ssh -F ssh_config application-a \
"sudo mkdir -p /srv/shared && sudo mount -t efs -o tls,stunnel,lookupcache=positive ${FS_ID}:/ /srv/shared"
ssh -F ssh_config application-b \
"sudo mkdir -p /srv/shared && sudo mount -t efs -o tls,stunnel,lookupcache=positive ${FS_ID}:/ /srv/shared"
挂载使用 lookupcache=positive:当另一台应用创建之前不存在的文件时,再次向服务器查询该文件名,让短时间内的上传结果可见。生产工作负载的缓存调整还需要单独评估性能。参见 Linux NFS 目录缓存选项。
-t efs 选择官方 EFS 挂载助手。tls 加密连接,stunnel 选择其支持的 TLS 传输方式。${FS_ID}:/ 选择文件系统根目录。准备好的主机已有所需客户端工具,无需另行安装。
新文件系统的目录最初由 root 拥有。为应用的 labex 用户准备上传子目录,并让两个应用使用它:
ssh -F ssh_config application-a \
'sudo mkdir -p /srv/shared/uploads && sudo chown labex:labex /srv/shared/uploads'
ssh -F ssh_config application-a \
'printf "{\"upload_directory\":\"/srv/shared/uploads\"}\n" | sudo tee /etc/uploads-app/config.json'
ssh -F ssh_config application-b \
'printf "{\"upload_directory\":\"/srv/shared/uploads\"}\n" | sudo tee /etc/uploads-app/config.json'
应用在每次请求时读取配置,无需重启。查看两台主机的实际挂载:
ssh -F ssh_config application-a 'findmnt -t nfs4 /srv/shared'
ssh -F ssh_config application-b 'findmnt -t nfs4 /srv/shared'
两台主机都在 /srv/shared 显示 NFS 4 挂载。使用 TLS 时,内核显示的源可能是 127.0.0.1:/,因为挂载助手通过本地加密隧道转发 NFS。
现在通过 A 上传,再通过 B 读取:
curl -i -X PUT --data-binary 'Shared upload version 1' \
http://127.0.0.1:8081/uploads/shared.txt
curl -i http://127.0.0.1:8082/uploads/shared.txt
B 返回 200 OK 和 Shared upload version 1。再通过 B 更新、通过 A 读取,证明共享是双向的:
curl -i -X PUT --data-binary 'Shared upload version 2' \
http://127.0.0.1:8082/uploads/shared.txt
curl -i http://127.0.0.1:8081/uploads/shared.txt
ssh -F ssh_config application-a 'stat -c "%i %u:%g" /srv/shared/uploads/shared.txt'
ssh -F ssh_config application-b 'stat -c "%i %u:%g" /srv/shared/uploads/shared.txt'
两个应用都读取版本 2,两条 stat 命令报告相同的文件 inode。EFS 通过独立挂载提供同一个共享文件,不是同步或复制两个本地上传目录。在 AWS View 中比较同一上传,作为浏览器观察点。

两台应用读取同一份更新后的上传内容。资源标识符以每次新环境为准。
卸载并删除自有存储
本步骤停止使用共享目录,仅删除你创建的存储资源。
删除网络端点前先停止使用共享目录。将每个应用恢复到提供的本地上传目录,然后卸载 EFS:
ssh -F ssh_config application-a \
'printf "{\"upload_directory\":\"/srv/uploads\"}\n" | sudo tee /etc/uploads-app/config.json'
ssh -F ssh_config application-b \
'printf "{\"upload_directory\":\"/srv/uploads\"}\n" | sudo tee /etc/uploads-app/config.json'
ssh -F ssh_config application-a 'sudo umount /srv/shared'
ssh -F ssh_config application-b 'sudo umount /srv/shared'
如果 umount 提示目录忙,请退出正在使用 /srv/shared 的 Shell 后重试。确认挂载已消失:
ssh -F ssh_config application-a 'findmnt -t nfs4'
ssh -F ssh_config application-b 'findmnt -t nfs4'
不应再有 NFS 挂载记录。没有匹配挂载时 findmnt 返回状态 1,在这里属于预期结果。
先删除挂载目标,再删除文件系统,最后仅删除你的专用存储安全组:
aws efs \
delete-mount-target --mount-target-id "$MOUNT_TARGET_ID"
aws efs \
describe-mount-targets --file-system-id "$FS_ID"
等待 MountTargets 为空,再继续:
aws efs \
delete-file-system --file-system-id "$FS_ID"
aws ec2 \
delete-security-group --group-id "$EFS_GROUP_ID"
aws efs \
describe-file-systems \
--query 'FileSystems[?Name==`fs01-shared-uploads`].FileSystemId'
aws ec2 \
describe-security-groups \
--filters Name=group-name,Values=fs01-efs-access \
--query 'SecurityGroups[].GroupId'
两条查询都返回空列表。成功的服务查询才能证明删除;连接或授权错误不能证明资源已删除。保留准备好的应用服务器、它们的安全组和子网。
运行本步骤检查,确认存储已删除、应用准备资源仍然保留。后续每个实验都从各自独立的准备环境开始。
总结
你通过挂载目标、受限 NFS 访问和 TLS 挂载,将两个应用连接到同一个 EFS 文件系统。双向上传和相同文件身份证明了真实共享。随后将应用恢复到本地存储,卸载客户端,并按依赖顺序删除自有存储资源。
共享文件系统解决文件位置问题,但不会自动分隔应用目录或选择 POSIX 身份。下一个引导实验将使用 EFS 访问点建立这些边界。
进一步阅读 AWS 官方资料:EFS 挂载助手与 TLS 传输; 客户端与挂载目标网络规则。



