Введение
Двум приложениям нужно общее хранилище, но каждое должно работать в своём каталоге. Настройте точки доступа EFS с отдельным корнем и POSIX-идентичностью для каждого монтирования, затем проверьте реальные файлы и владельцев.
Сначала завершите Общие файлы между серверами приложений с EFS. Эта независимая VM предоставляет новые узлы и подсеть, не используя прежнюю файловую систему. Используйте Terminal для настроенной AWS CLI и SSH и AWS View для сравнения ответов. Личная учётная запись AWS не нужна.
Связь с сертификацией
| Сертификация | Задача экзамена | Практика |
|---|---|---|
| Cloud Practitioner (CLF-C02) | Task 3.6 | Изучить EFS и сравнить каталоги и файловые разрешения с объектным хранилищем. |

Схема концептуальная; идентификаторы смотрите в новой среде.
Подготовить общую систему и точку подключения NFS
На этом шаге создайте хранилище и ограниченную сетевую точку для двух приложений.
Работайте в /home/labex/project и определите подготовленную сеть. AWS CLI уже настроен:
cd /home/labex/project
aws sts \
get-caller-identity
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"
Создайте новую EFS. Приложения используют один ресурс, а точки доступа выбирают разные каталоги в нём:
FS_ID=$(aws efs \
create-file-system \
--creation-token fs02-application-files \
--encrypted \
--tags Key=Name,Value=fs02-application-files \
--query FileSystemId --output text)
echo "$FS_ID"
Создайте отдельную группу хранилища:
EFS_GROUP_ID=$(aws ec2 \
create-security-group \
--group-name fs02-efs-access \
--description 'NFS for the upload application servers' \
--vpc-id "$VPC_ID" \
--query GroupId --output text)
echo "$EFS_GROUP_ID"
Разрешите TCP 2049 из группы приложений. Это правило разрешает NFS, но не выбирает каталог или пользовательскую идентичность:
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"
Проверьте состояния и дождитесь available у обоих ресурсов:
aws efs \
describe-file-systems \
--file-system-id "$FS_ID" \
--query 'FileSystems[].{ID:FileSystemId,State:LifeCycleState}'
aws efs \
describe-mount-targets \
--file-system-id "$FS_ID" \
--query 'MountTargets[].{ID:MountTargetId,IP:IpAddress,State:LifeCycleState}'
Создать точки доступа приложений
На этом шаге определите корень и идентичность файловых операций каждого монтирования.
Точка доступа — вход EFS для приложения. Её корень становится / внутри монтирования, а POSIX-пользователь заменяет идентичность файловых операций клиента. POSIX использует числовой UID для пользователя и GID для группы.
Создайте точку для A:
AP_A_ID=$(aws efs \
create-access-point \
--file-system-id "$FS_ID" \
--posix-user Uid=2001,Gid=2001 \
--root-directory 'Path=/app-a,CreationInfo={OwnerUid=2001,OwnerGid=2001,Permissions=700}' \
--tags Key=Name,Value=fs02-app-a \
--query AccessPointId --output text)
echo "$AP_A_ID"
Если /app-a отсутствует, CreationInfo задаёт владельца и разрешения. 700 даёт владельцу чтение, запись и проход по каталогу, не предоставляя их другим пользователям. UID/GID точки совпадает с владельцем.
Создайте вторую точку с другим корнем и идентичностью:
AP_B_ID=$(aws efs \
create-access-point \
--file-system-id "$FS_ID" \
--posix-user Uid=2002,Gid=2002 \
--root-directory 'Path=/app-b,CreationInfo={OwnerUid=2002,OwnerGid=2002,Permissions=700}' \
--tags Key=Name,Value=fs02-app-b \
--query AccessPointId --output text)
echo "$AP_B_ID"
Проверьте обе конфигурации:
aws efs \
describe-access-points \
--file-system-id "$FS_ID" \
--query 'AccessPoints[].{ID:AccessPointId,Root:RootDirectory.Path,User:PosixUser,Creation:RootDirectory.CreationInfo}'
Корни — /app-a и /app-b, идентичности — 2001:2001 и 2002:2002. Следующий шаг проверяет реальное поведение; одной конфигурации для доказательства границы недостаточно.
Точка ограничивает корень и идентичность монтирования, которое её выбирает. Сама по себе она не запрещает авторизованному клиенту выбрать другую точку. В рабочей среде IAM и политики файловой системы могут ограничить допустимые точки. Здесь изучаются каталоги и POSIX-поведение.
Проверить отдельные каталоги и принудительных владельцев
На этом шаге смонтируйте точки и докажите, что одинаковые имена обозначают разные файлы.
Смонтируйте точку A на A. Монтирование точки доступа требует TLS:
ssh -F ssh_config application-a \
"sudo mkdir -p /srv/shared && sudo mount -t efs -o tls,stunnel,lookupcache=positive,accesspoint=${AP_A_ID} ${FS_ID}:/ /srv/shared"
lookupcache=positive повторно проверяет ранее отсутствовавшее имя на сервере после создания файла другим приложением. Это делает короткое упражнение наблюдаемым; настройка кеша в рабочей среде требует отдельной оценки производительности. См. параметры кеша Linux NFS.
Смонтируйте точку B на B:
ssh -F ssh_config application-b \
"sudo mkdir -p /srv/shared && sudo mount -t efs -o tls,stunnel,lookupcache=positive,accesspoint=${AP_B_ID} ${FS_ID}:/ /srv/shared"
Оба локальных пути — /srv/shared, но на A это /app-a, а на B — /app-b. Настройте приложения использовать корень своей точки напрямую:
ssh -F ssh_config application-a \
'printf "{\"upload_directory\":\"/srv/shared\"}\n" | sudo tee /etc/uploads-app/config.json'
ssh -F ssh_config application-b \
'printf "{\"upload_directory\":\"/srv/shared\"}\n" | sudo tee /etc/uploads-app/config.json'
Запишите private.txt через A и попробуйте прочитать через B:
curl -i -X PUT --data-binary 'Private upload for application A' \
http://127.0.0.1:8081/uploads/private.txt
curl -i http://127.0.0.1:8082/uploads/private.txt
A возвращает 201 Created, B — 404 Not Found. Создайте собственный файл B с тем же именем:
curl -i -X PUT --data-binary 'Private upload for application B' \
http://127.0.0.1:8082/uploads/private.txt
curl -i http://127.0.0.1:8081/uploads/private.txt
curl -i http://127.0.0.1:8082/uploads/private.txt
A по-прежнему возвращает свой текст, B — свой. Выберите private.txt и Read upload на обеих карточках AWS View.
Проверьте реальные монтирования и файловые идентичности:
ssh -F ssh_config application-a 'findmnt -t nfs4 /srv/shared; stat -c "%i %u:%g" /srv/shared/private.txt'
ssh -F ssh_config application-b 'findmnt -t nfs4 /srv/shared; stat -c "%i %u:%g" /srv/shared/private.txt'
Inode отличаются, владельцы — 2001:2001 и 2002:2002. Приложение работает как labex, но сервер применяет идентичность точки.
Даже запись клиента root через монтирование A использует выбранную идентичность:
ssh -F ssh_config application-a \
'printf "Access-point identity also applies to root callers\n" | sudo tee /srv/shared/root-caller.txt; stat -c "%u:%g" /srv/shared/root-caller.txt'
Владелец — 2001:2001. EFS применяет числовые идентичности без локальных учётных записей с именами 2001 и 2002.
Монтирование A показывает содержимое /app-a, а не весь корень EFS. Соседний каталог B не является дочерним каталогом этого монтирования:
ssh -F ssh_config application-a 'ls -a /srv/shared'
ssh -F ssh_config application-a 'cat /srv/shared/app-b/private.txt'
Последняя команда возвращает No such file or directory, хотя B читает свой существующий файл. Независимые корни и разные данные доказывают разделение. Переход через .. из локальной точки ведёт в локальный родительский каталог, а не к соседнему каталогу 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'
Удалите обе точки и убедитесь, что их не осталось:
aws efs \
delete-access-point \
--access-point-id "$AP_A_ID"
aws efs \
delete-access-point \
--access-point-id "$AP_B_ID"
aws efs \
describe-access-points \
--file-system-id "$FS_ID"
AccessPoints должен быть пустым. Удаление точки убирает определение входа, но не файлы каталога. Далее удаляется вся временная файловая система и её данные:
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==`fs02-application-files`].FileSystemId'
aws ec2 \
describe-security-groups \
--filters Name=group-name,Values=fs02-efs-access \
--query 'SecurityGroups[].GroupId'
Оба списка пусты. Сохраните подготовленные серверы, группы и подсеть, затем запустите проверку.
Резюме
Две точки доступа выбрали разные корни и POSIX-идентичности в одной EFS. Одинаковые имена содержали разные данные, а сервер назначал владельцев даже записям от root. Затем вы размонтировали и удалили точки, сетевой ресурс и временную файловую систему.
Сетевая доступность, выбор монтирования и права каталогов — разные уровни. Следующее упражнение использует их для диагностики подключения EFS.
Подробнее см. в документации AWS: Корневые каталоги, идентичности и область авторизации точек доступа.



