Compartir archivos entre servidores de aplicaciones con EFS

AWSBeginner
Practicar Ahora

Introducción

Una aplicación de cargas funciona en dos servidores. Cada uno guarda archivos en su propio disco: un usuario puede cargar un archivo en uno y recibir «no encontrado» en el otro. Proporciona a ambos una interfaz de archivos compartida con Amazon Elastic File System (EFS).

Completa primero AWS VPC for Beginners y AWS EC2 and EBS for Beginners. Este entorno independiente proporciona la aplicación, tres servidores y su red. Usa Terminal para AWS CLI y SSH y AWS View para comparar respuestas reales. La CLI ya está configurada; no necesitas una cuenta AWS personal ni recursos anteriores. La práctica se centra en archivos compartidos y conectividad, sin evaluar rendimiento o disponibilidad de producción.

Relación con certificaciones

Certificación Tarea del examen Práctica
Cloud Practitioner (CLF-C02) Task 3.6 Reconocer EFS como servicio de archivos compartidos y distinguir un sistema montado de directorios locales independientes.

Vista general

Esquema conceptual; consulta los identificadores reales de tu entorno nuevo.

Crear almacenamiento para la aplicación de cargas

En este paso, observa el problema de las cargas locales y crea tu sistema de archivos compartido.

Trabaja en /home/labex/project. Confirma la identidad configurada sin mostrar credenciales:

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

El ARN del usuario termina en labex-fs01-operator. resources.json identifica la subred y el grupo de seguridad preparados. Lee estos identificadores para usar los recursos reales de tu entorno:

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

Observa primero el problema del almacenamiento local. HTTP PUT guarda una carga y HTTP GET lee un archivo. Estas direcciones llegan a los 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 devuelve 201 Created y B devuelve 404 Not Found: el directorio local de B contiene otros archivos. También puedes escribir y leer el mismo nombre desde las tarjetas de AWS View.

EFS proporciona un sistema de archivos compartido: ambas aplicaciones acceden a los mismos archivos y directorios mediante NFS, el protocolo Network File System. Crea primero el sistema. El token identifica la solicitud de creación; la etiqueta Name facilita la inspección y limpieza. --encrypted activa la configuración de cifrado en reposo del servicio. El cifrado de transporte se configura al montar.

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

Espera a que el estado sea available. El recurso existe, pero las aplicaciones aún necesitan un destino de montaje accesible y un montaje real.

Conectar el sistema de archivos a la subred de aplicaciones

En este paso, proporciona un punto de conexión NFS accesible y limita el acceso a los servidores de aplicaciones.

Un destino de montaje proporciona el punto de conexión de red del sistema de archivos en una subred. NFS usa TCP 2049. Crea un grupo de seguridad dedicado y permite ese puerto desde el grupo de aplicaciones preparado. La regla incluye ambos servidores sin abrir NFS a todas las direcciones. El servidor de referencia ajeno pertenece a otro grupo y debe seguir excluido.

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

Crea el destino de montaje en la subred preparada y asocia el nuevo 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"

Espera a que el destino esté available. Las dos aplicaciones están en una sola zona de disponibilidad, por lo que este entorno necesita un destino. En producción, planifica destinos en las zonas donde se ejecutan los clientes.

Montar ambos servidores y observar archivos compartidos

En este paso, conecta ambas aplicaciones a EFS y prueba cargas en ambos sentidos.

El archivo ssh_config conecta con cada servidor. Un punto de montaje es el directorio local por el que una aplicación accede al sistema remoto. Crea /srv/shared y monta allí la raíz de EFS en ambos servidores:

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 hace que el cliente vuelva a consultar nombres antes inexistentes cuando otra aplicación crea un archivo. Así las cargas nuevas son visibles durante esta práctica breve. Los cambios de caché en producción requieren evaluar el rendimiento por separado; consulta las opciones de caché de directorios NFS de Linux.

-t efs selecciona el asistente oficial de montaje. tls cifra la conexión y stunnel selecciona su transporte TLS compatible. ${FS_ID}:/ selecciona la raíz del sistema. Los servidores ya tienen las herramientas necesarias.

Al principio, root es propietario del directorio. Prepara un subdirectorio para el usuario labex de la aplicación y configura ambas aplicaciones para usarlo:

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'

La aplicación lee la configuración en cada solicitud; no requiere reinicio. Comprueba los montajes reales:

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

Ambos servidores muestran NFS 4 en /srv/shared. Con TLS, el origen del kernel puede aparecer como 127.0.0.1:/ porque el asistente envía NFS a través de un túnel cifrado local.

Carga ahora mediante A y lee mediante 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 devuelve 200 OK y Shared upload version 1. Actualiza mediante B y lee mediante A para probar ambos sentidos:

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'

Ambas aplicaciones leen la versión 2 y las consultas stat muestran el mismo inode. Los montajes independientes acceden al mismo archivo EFS; no se sincronizan copias de directorios locales. Compara también la carga en AWS View.

Cargas compartidas en AWS View

Ambas aplicaciones leen la misma carga actualizada. Los identificadores varían en cada entorno nuevo.

Desmontar y eliminar tu almacenamiento

En este paso, deja de usar el directorio compartido y elimina solo el almacenamiento que creaste.

Antes de borrar el punto de conexión, restaura el directorio local preparado de cada aplicación y desmonta 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'

Si umount indica que el directorio está ocupado, sal de cualquier shell que esté usando /srv/shared y vuelve a intentarlo. Confirma que los montajes desaparecieron:

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

No debe quedar ningún montaje NFS. findmnt devuelve estado 1 cuando no encuentra coincidencias; aquí es el resultado esperado.

Elimina primero el destino de montaje, después el sistema de archivos y finalmente tu grupo de almacenamiento dedicado:

aws efs \
  delete-mount-target --mount-target-id "$MOUNT_TARGET_ID"
aws efs \
  describe-mount-targets --file-system-id "$FS_ID"

Espera a que MountTargets esté vacío 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'

Ambas consultas devuelven listas vacías. Solo una consulta autorizada que responde correctamente demuestra eliminación; los errores de conexión o autorización no lo hacen. Conserva los servidores preparados, sus grupos y la subred.

Ejecuta la comprobación para confirmar la eliminación del almacenamiento y la conservación de los recursos preparados. Cada práctica posterior comienza con su propio entorno independiente.

Resumen

Conectaste dos aplicaciones al mismo sistema EFS mediante un destino de montaje, acceso NFS restringido y montajes TLS. Las cargas en ambos sentidos y la identidad del archivo demostraron una compartición real. Después restauraste el almacenamiento local, desmontaste los clientes y eliminaste los recursos propios en orden de dependencia.

Compartir un sistema de archivos no separa automáticamente directorios ni selecciona identidades POSIX. La siguiente práctica usa puntos de acceso para establecer esos límites.

Para ampliar este tema, consulta la referencia de AWS: Asistente de montaje de EFS y transporte TLS; Reglas de red del cliente y del destino de montaje.