Разделить каталоги приложений с помощью точек доступа

AWSBeginner
Практиковаться сейчас

Введение

Двум приложениям нужно общее хранилище, но каждое должно работать в своём каталоге. Настройте точки доступа 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.

Раздельные каталоги в AWS View

Одинаковое имя содержит разные данные в двух корнях. Идентификаторы различаются между средами.

Удалить точки доступа и общее хранилище

На этом шаге освободите монтирования и удалите только своё хранилище.

Верните приложения к локальным каталогам перед размонтированием:

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: Корневые каталоги, идентичности и область авторизации точек доступа.