Introdução
Duas aplicações precisam de armazenamento compartilhado, mas cada uma deve trabalhar em seu próprio diretório. Configure pontos de acesso EFS com uma raiz e uma identidade POSIX para cada montagem e observe os arquivos e proprietários reais.
Conclua primeiro Compartilhar arquivos entre servidores de aplicações com EFS. Esta VM independente fornece novos hosts e uma sub-rede, sem reutilizar o sistema anterior. Use Terminal para AWS CLI e SSH e AWS View para comparar respostas. Não é necessária uma conta AWS pessoal.
Relação com certificações
| Certificação | Tarefa do exame | Prática |
|---|---|---|
| Cloud Practitioner (CLF-C02) | Task 3.6 | Explorar EFS e comparar diretórios e permissões de arquivos com armazenamento de objetos. |

Diagrama conceitual; confira os identificadores no novo ambiente.
Preparar um sistema compartilhado e uma conexão NFS
Nesta etapa, crie o armazenamento e o ponto de conexão restrito das aplicações.
Trabalhe em /home/labex/project e identifique a rede preparada. AWS CLI já está configurada:
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"
Crie um novo EFS. As aplicações usarão o mesmo recurso; os pontos de acesso selecionarão diretórios distintos:
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"
Crie um grupo de armazenamento dedicado:
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"
Permita TCP 2049 a partir do grupo das aplicações. A regra permite conexões NFS, mas não escolhe diretório ou identidade de usuário:
aws ec2 \
authorize-security-group-ingress \
--group-id "$EFS_GROUP_ID" \
--ip-permissions "IpProtocol=tcp,FromPort=2049,ToPort=2049,UserIdGroupPairs=[{GroupId=$APP_GROUP_ID}]"
Crie o destino na sub-rede preparada:
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"
Inspecione os estados e espere ambos os recursos ficarem 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}'
Criar pontos de acesso específicos para aplicações
Nesta etapa, defina a raiz e a identidade das operações de cada montagem.
Um ponto de acesso é uma entrada EFS específica para a aplicação. Sua raiz se torna / dentro da montagem e seu usuário POSIX substitui a identidade das operações do cliente. POSIX usa UID numérico para usuários e GID para grupos.
Crie o ponto de 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"
Se /app-a não existir, CreationInfo fornece proprietário e permissões. 700 dá ao proprietário leitura, escrita e travessia do diretório sem conceder isso aos outros usuários. O UID/GID do ponto corresponde ao proprietário.
Crie outro ponto com raiz e identidade diferentes:
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"
Inspecione as duas definições:
aws efs \
describe-access-points \
--file-system-id "$FS_ID" \
--query 'AccessPoints[].{ID:AccessPointId,Root:RootDirectory.Path,User:PosixUser,Creation:RootDirectory.CreationInfo}'
As raízes são /app-a e /app-b, com identidades 2001:2001 e 2002:2002. A próxima etapa testa o comportamento real; a configuração sozinha não comprova o limite.
O ponto limita raiz e identidade da montagem que o seleciona. Sozinho, não impede um cliente autorizado de escolher outro ponto. Em produção, IAM e políticas do sistema podem restringir os pontos permitidos. Aqui o foco é diretórios e comportamento POSIX.
Observar diretórios separados e propriedade imposta
Nesta etapa, monte os pontos e prove que nomes iguais representam arquivos diferentes.
Monte o ponto de A em A. Montagens com ponto de acesso exigem 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 consulta novamente nomes antes ausentes quando outra aplicação cria um arquivo. Isso mantém o exercício curto observável; ajustes de cache em produção precisam de avaliação de desempenho separada. Veja as opções de cache NFS do Linux.
Monte o ponto de B em 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"
Ambos usam /srv/shared, mas em A ele representa /app-a e em B /app-b. Configure cada aplicação para usar diretamente a raiz de seu ponto:
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'
Escreva private.txt por A e tente ler por 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 retorna 201 Created e B 404 Not Found. Agora crie o arquivo próprio de B com o mesmo nome:
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 continua retornando seu conteúdo e B retorna o seu. Use private.txt e Read upload nos dois cartões AWS View.
Inspecione as montagens e identidades reais:
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'
Os inodes são diferentes e os proprietários são 2001:2001 e 2002:2002. A aplicação executa como labex, mas o servidor aplica a identidade do ponto.
Mesmo uma escrita de root pela montagem de A usa a identidade selecionada:
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'
O proprietário é 2001:2001. EFS aplica identidades numéricas sem precisar de contas locais chamadas 2001 e 2002.
A montagem de A expõe /app-a, não a raiz EFS inteira. O diretório irmão de B não é um subdiretório dessa montagem:
ssh -F ssh_config application-a 'ls -a /srv/shared'
ssh -F ssh_config application-a 'cat /srv/shared/app-b/private.txt'
O último comando retorna No such file or directory, embora o arquivo de B exista e possa ser lido por sua aplicação. As raízes independentes e os conteúdos diferentes demonstram separação. .. no ponto local leva ao diretório pai local, não ao diretório irmão EFS.

O mesmo nome possui conteúdos diferentes em duas raízes. Os identificadores variam entre ambientes.
Remover pontos de acesso e armazenamento
Nesta etapa, libere as montagens e exclua somente seu armazenamento.
Restaure os diretórios locais antes de desmontar:
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'
Exclua os dois pontos e confirme que nenhum permanece:
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 deve ficar vazio. Excluir um ponto remove sua definição, não os arquivos do diretório. Agora você removerá todo o sistema descartável e seus dados:
aws efs \
delete-mount-target \
--mount-target-id "$MOUNT_TARGET_ID"
aws efs \
describe-mount-targets \
--file-system-id "$FS_ID"
Espere MountTargets ficar vazio antes de continuar:
aws efs \
delete-file-system \
--file-system-id "$FS_ID"
aws ec2 \
delete-security-group \
--group-id "$EFS_GROUP_ID"
Confirme respostas bem-sucedidas e vazias para seus recursos nomeados:
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'
As duas listas são vazias. Preserve os servidores, grupos e sub-rede preparados e execute a verificação.
Resumo
Dois pontos de acesso selecionaram raízes e identidades POSIX distintas no mesmo EFS. Nomes iguais continham dados diferentes e o servidor impôs a propriedade inclusive a clientes root. Depois você desmontou e removeu os pontos, o destino e o sistema descartável.
Acessibilidade da rede, seleção da montagem e permissões são camadas diferentes. O próximo exercício usa essas camadas para diagnosticar uma conexão EFS.
Para aprofundar o tema, consulte a documentação da AWS: Raízes, identidades e escopo de autorização dos pontos de acesso.



