Compartilhar arquivos entre servidores de aplicações com EFS

AWSBeginner
Pratique Agora

Introdução

Uma aplicação de uploads funciona em dois servidores. Cada um salva arquivos no próprio disco local: o usuário pode enviar por um servidor e receber «não encontrado» pelo outro. Forneça aos dois uma interface de arquivos compartilhada com Amazon Elastic File System (EFS).

Conclua primeiro AWS VPC for Beginners e AWS EC2 and EBS for Beginners. Este ambiente independente fornece a aplicação, três hosts e sua rede. Use Terminal para AWS CLI e SSH e AWS View para comparar respostas reais. A CLI já está configurada; você não precisa de uma conta AWS pessoal nem de recursos anteriores. O exercício trata de arquivos compartilhados e conectividade, sem avaliar desempenho ou disponibilidade de produção.

Relação com certificações

Certificação Tarefa do exame Prática
Cloud Practitioner (CLF-C02) Task 3.6 Identificar EFS como serviço de arquivos compartilhados e distinguir uma interface montada de diretórios locais independentes.

Visão geral

Diagrama conceitual; os identificadores reais aparecem no seu novo ambiente.

Criar armazenamento para a aplicação de uploads

Nesta etapa, observe o problema dos uploads locais e crie seu sistema de arquivos compartilhado.

Trabalhe em /home/labex/project. Confirme a identidade configurada sem mostrar credenciais:

cd /home/labex/project
aws sts \
  get-caller-identity

O ARN do usuário termina em labex-fs01-operator. resources.json identifica a sub-rede e o grupo de segurança preparados. Leia esses identificadores para usar os recursos reais do ambiente:

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}'

Observe primeiro o problema local. HTTP PUT salva um upload e HTTP GET lê um arquivo. Estes endereços chegam aos servidores preparados:

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 retorna 201 Created; B retorna 404 Not Found, pois seu diretório local contém outros arquivos. Você também pode escrever e ler o mesmo nome nos cartões de AWS View.

EFS fornece um sistema de arquivos compartilhado. As aplicações acessam os mesmos diretórios e arquivos pelo protocolo Network File System (NFS). Crie primeiro o sistema. O token identifica a solicitação de criação; a tag Name ajuda a reconhecer o recurso na inspeção e limpeza. --encrypted ativa a configuração de criptografia em repouso do serviço. A criptografia de transporte será configurada na montagem.

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}'

Espere pelo estado available. O recurso existe, mas as aplicações ainda precisam de um destino acessível e uma montagem real.

Conectar o sistema à sub-rede das aplicações

Nesta etapa, forneça um ponto de conexão NFS acessível e restrinja o acesso aos servidores das aplicações.

Um destino de montagem fornece o ponto de conexão de rede na sub-rede. NFS usa TCP 2049. Crie um grupo de segurança dedicado e permita essa porta a partir do grupo das aplicações preparado. A regra por grupo de origem inclui os dois servidores sem abrir NFS para todos os endereços. O servidor de referência independente pertence a outro grupo e deve continuar excluído.

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}]"

Crie o destino na sub-rede preparada e associe o novo grupo:

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"

Espere o destino ficar available. As aplicações estão na mesma zona de disponibilidade; esta topologia precisa de apenas um destino. Em produção, planeje destinos nas zonas onde estão os clientes.

Montar as duas aplicações e observar arquivos compartilhados

Nesta etapa, conecte as aplicações ao EFS e teste uploads nos dois sentidos.

ssh_config conecta a cada host. Um ponto de montagem é o diretório local usado para acessar o sistema remoto. Crie /srv/shared nos dois hosts e monte a raiz do 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 consulta novamente nomes antes inexistentes quando outra aplicação cria um arquivo. Isso torna os novos uploads visíveis durante este exercício curto. Ajustes de cache em produção precisam de avaliação de desempenho separada. Consulte as opções de cache de diretórios do Linux NFS.

-t efs seleciona o assistente oficial; tls criptografa a conexão e stunnel escolhe seu transporte TLS compatível. ${FS_ID}:/ seleciona a raiz do sistema. Os hosts já possuem as ferramentas necessárias.

O diretório novo pertence inicialmente a root. Prepare um subdiretório para o usuário labex da aplicação e configure as duas aplicações para usá-lo:

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'

A aplicação lê a configuração a cada solicitação, sem reinicialização. Confira as montagens reais:

ssh -F ssh_config application-a 'findmnt -t nfs4 /srv/shared'
ssh -F ssh_config application-b 'findmnt -t nfs4 /srv/shared'

Os dois hosts mostram NFS 4 em /srv/shared. Com TLS, a origem exibida pelo kernel pode ser 127.0.0.1:/, pois o assistente encaminha NFS por um túnel local criptografado.

Envie por A e leia por 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 retorna 200 OK e Shared upload version 1. Atualize por B e leia por A para confirmar o sentido inverso:

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'

As duas aplicações leem a versão 2 e stat mostra o mesmo inode. As montagens independentes acessam o mesmo arquivo EFS; não há cópia nem sincronização entre diretórios locais. Compare também o upload em AWS View.

Uploads compartilhados em AWS View

As duas aplicações leem o mesmo upload atualizado. Os identificadores variam em cada novo ambiente.

Desmontar e excluir seu armazenamento

Nesta etapa, pare de usar o diretório compartilhado e exclua somente o armazenamento que criou.

Antes de excluir o ponto de conexão, restaure o diretório local preparado em cada aplicação e desmonte 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'

Se umount indicar que o diretório está ocupado, saia dos shells que usam /srv/shared e tente novamente. Confirme que as montagens desapareceram:

ssh -F ssh_config application-a 'findmnt -t nfs4'
ssh -F ssh_config application-b 'findmnt -t nfs4'

Nenhuma montagem NFS deve permanecer. Sem correspondências, findmnt retorna estado 1; aqui isso é esperado.

Exclua primeiro o destino de montagem, depois o sistema de arquivos e por último apenas seu grupo de segurança dedicado:

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"
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'

As consultas retornam listas vazias. Somente uma consulta autorizada bem-sucedida comprova a exclusão; falhas de rede ou autorização não comprovam isso. Preserve os servidores preparados, seus grupos e a sub-rede.

Execute a verificação para confirmar a limpeza e a preservação dos recursos preparados. Cada próximo exercício começa em um ambiente independente.

Resumo

Você conectou duas aplicações ao mesmo EFS com um destino de montagem, acesso NFS restrito e montagens TLS. Uploads recíprocos e a mesma identidade de arquivo comprovaram compartilhamento real. Depois restaurou os diretórios locais, desmontou os clientes e removeu seus recursos na ordem de dependência.

Um sistema compartilhado não separa automaticamente diretórios de aplicações nem identidades POSIX. O próximo exercício usa pontos de acesso EFS para estabelecer esses limites.

Para aprofundar o tema, consulte a documentação da AWS: Auxiliar de montagem do EFS e transporte TLS; Regras de rede do cliente e do destino de montagem.