2024/11/268 min. de lectura

Cómo usé AWS para desplegar mi sitio web de manera eficiente y escalable

AWSInfrastructureServerless
Hero image for Cómo usé AWS para desplegar mi sitio web de manera eficiente y escalable

Llevo varios meses queriendo actualizar mi sitio web personal para reflejar mejor mis habilidades y proyectos recientes. Antes de cambiarlo por completo, intenté simplemente actualizar la primera versión que había creado hace tiempo, pero me di cuenta de que ya no me gustaba lo suficiente como para seguir usándolo. Así que decidí empezar desde cero con un nuevo diseño, tecnologías y arquitectura más robusta (aunque para un sitio web personal no era necesario algo más allá de una plantilla estática y el despliegue en Netlify o Vercel).

Aprovechando que acabo de certificarme en AWS como Solutions Architect - Associate, decidí implementar una arquitectura serverless en AWS. En este artículo, compartiré cómo diseñé y desplegué la arquitectura utilizando varios servicios de AWS, y las razones detrás de mis elecciones.

Diagrama de arquitectura de la solución
Diagrama de arquitectura de la solución con servicios Serverless de AWS

Sobre la Arquitectura y los Servicios

La arquitectura que implementé para mi sitio web es completamente serverless, lo que significa que no gestiono ningún servidor directamente. En su lugar, utilizo varios servicios de AWS que se encargan de la infraestructura subyacente.

A continuación, describo los principales servicios que utilizo y su función en la arquitectura con el fragmento de código correspondiente en YAML para CloudFormation:

1. Amazon S3 (Simple Storage Service)

S3 es un servicio de almacenamiento de objetos que utilizo para alojar los archivos estáticos de la carpeta out generada por Next.js (HTML, CSS, JS, imágenes, etc.). En este caso, S3 actúa como el origen para Cloudfront.

El bucket de S3 está configurado para bloquear todo el acceso público, forzar la propiedad de los objectos al propietario del bucket y versionar los archivos. Aunque estas dos últimas configuraciones no son estrictamente necesarias para un sitio web estático, las considero buenas prácticas para mejorar la seguridad y la gestión de los archivos. Sin embargo, es importante analizar si tener el versionado activo es adecuado para tu caso, ya que puede incrementar los costos de almacenamiento si no se gestiona adecuadamente con políticas de ciclo de vida.

SiteBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !If
- UseCustomBucketName
- !Ref BucketName
- !Ref DomainName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
OwnershipControls:
Rules:
- ObjectOwnership: BucketOwnerEnforced
VersioningConfiguration:
Status: Enabled
LifecycleConfiguration:
Rules:
- Id: DeleteOldVersionsRule
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 30

2. Amazon CloudFront

CloudFront es una red de distribución de contenido (CDN) que utilizo para distribuir mi sitio web globalmente. CloudFront almacena en caché los archivos estáticos en ubicaciones cercanas a los usuarios, lo que reduce la latencia y mejora la velocidad de carga del sitio web. La configuración de CloudFront incluye:

Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Comment: !Sub "Static site for ${DomainName}"
Aliases: !If
- UseWWW
- [!Ref DomainName, !Sub "www.${DomainName}"]
- [!Ref DomainName]
DefaultRootObject: index.html
HttpVersion: http2
PriceClass: PriceClass_100
Origins:
- Id: S3Origin
DomainName: !GetAtt SiteBucket.RegionalDomainName
S3OriginConfig: {}
OriginAccessControlId: !Ref OriginAccessControl
DefaultCacheBehavior:
TargetOriginId: S3Origin
ViewerProtocolPolicy: redirect-to-https
CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
Compress: true
FunctionAssociations:
- EventType: viewer-request
FunctionARN: !GetAtt WWWRedirectFunction.FunctionMetadata.FunctionARN
ViewerCertificate:
AcmCertificateArn: !Ref Certificate
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2021
CustomErrorResponses:
- ErrorCode: 404
ResponsePagePath: /404.html
ResponseCode: 404
ErrorCachingMinTTL: 31536000
- ErrorCode: 403
ResponsePagePath: /404.html
ResponseCode: 403
ErrorCachingMinTTL: 31536000

3. Amazon Route 53

Route 53 es un servicio de sistema de nombres de dominio (DNS) de alta disponibilidad y escalable que traduce nombre de dominio como pool-llerena.com a direcciones IP. Route 53 gestiona el dominio personalizado y apunta a la distribución de CloudFront.

La zona hospedada se crea automáticamente si el dominio es gestionado por Route 53. Sin embargo, he comprado el dominio a través de Namecheap, por lo que tuve que crear la zona hospedada con CloudFormation y luego actualizar los nameservers en Namecheap para que apunten a los de Route 53.

HostedZone:
Type: AWS::Route53::HostedZone
Properties:
Name: !Ref DomainName
HostedZoneConfig:
Comment: !Sub "Hosted zone for ${DomainName}"

# Registro A en Route 53 apuntando a CloudFront
ApexAlias:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref HostedZone
Name: !Ref DomainName
Type: A
AliasTarget:
DNSName: !GetAtt Distribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2

# Registro A para www.<domain> apuntando a CloudFront
WWWAlias:
Condition: UseWWW
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref HostedZone
Name: !Sub "www.${DomainName}"
Type: A
AliasTarget:
DNSName: !GetAtt Distribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2

4. AWS Certificate Manager (ACM)

ACM es un servicio que facilita la provisión, gestión y despliegue de certificados SSL/TLS para asegurar las conexiones a mi sitio web. Solicité un certificado para mi dominio personalizado y lo asocié con la distribución de CloudFront y la zona hospedada en Route 53 para habilitar HTTPS.

Route 53 gestiona automáticamente la validación del dominio mediante DNS, creando los registros CNAME necesarios en la zona hospedada.

Certificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref DomainName
ValidationMethod: DNS
SubjectAlternativeNames: !If
- UseWWW
- [!Sub "www.${DomainName}"]
- []
DomainValidationOptions:
- DomainName: !Ref DomainName
HostedZoneId: !Ref HostedZone
- !If
- UseWWW
- { DomainName: !Sub "www.${DomainName}", HostedZoneId: !Ref HostedZone }
- !Ref "AWS::NoValue"
Metadata:
Commnet: "ACM will auto-create DNS validation CNAMEs in the hosted Zone"

5. CloudFront Functions

Utilizo funciones de CloudFront para manejar redirecciones y el enrutamiento de la web. Next.js genera rutas dinámicas que necesitan ser manejadas correctamente para que los usuarios puedan acceder a las páginas sin problemas.

El código de la función es una función básica que solo devuelve la solicitud sin modificaciones porque el código real lo gestiono post-despliegue con un workflow de GitHub Actions. Esto me permite mantener la plantilla de CloudFormation más limpia y separar el código de la función del resto de la infraestructura.

WWWRedirectFunction:
Type: AWS::CloudFront::Function
Properties:
Name: !Ref RedirectFunctionName
AutoPublish: true
FunctionConfig:
Comment: !Sub "Manage application routing and redirect www.${DomainName} and CloudFront Domain Name to apex for ${DomainName}"
Runtime: cloudfront-js-2.0
FunctionCode: |
function handler(event) {
return event.request;
}

6. AWS CloudFormation

Utilizo CloudFormation para definir y desplegar toda la infraestructura como código. Esto me permite versionar la infraestructura junto con el código de mi sitio web y automatizar el proceso de despliegue.

Para ver el archivo completo de CloudFormation, puedes revisar el repositorio en GitHub

Trade-offs y Consideraciones

Elegir una arquitectura serverless en AWS para un sitio web personal tiene varias ventajas, pero también algunos trade-offs que debemos considerar:

Costos Estimados

El costo mensual estimado para alojar mi sitio web utilizando esta arquitectura serverless en AWS es relativamente bajo, especialmente considerando que el tráfico a mi sitio web no es alto.

Nivel de TráficoAmazon S3CloudFrontRoute 53ACMTotal Mensual
Bajo (1K visitas/mes)$0.02$0.15$0.50Gratis$0.67
Moderado (10K visitas/mes)$0.05$1.46$0.51Gratis$2.02
Alto (100K visitas/mes)$0.26$14.63$0.53Gratis$15.42
Con Free Tier (cualquier nivel)$0.00$0.00$0.53Gratis$0.53

Nota sobre CloudFront: Los costos están calculados basándose en los datos reales del sitio:

Desglose Detallado de Costos

Amazon S3:

Amazon CloudFront:

Amazon Route 53:

AWS Certificate Manager (ACM):

Beneficios del AWS Free Tier

Costo real con Free Tier activo: Solo la zona hospedada de Route 53 ($0.50/mes) + consultas DNS adicionales ($0.40/millón de consultas estándar). Para un sitio web personal, esto resulta en aproximadamente $0.51/mes.

Conclusión

Implementar mi sitio web personal utilizando una arquitectura serverless en AWS ha sido una experiencia enriquecedora que me ha permitido aprender y aplicar varios servicios de AWS. La combinación de S3, CloudFront, Route 53, ACM y CloudFormation me ha proporcionado una solución robusta, escalable y segura para alojar mi sitio web.

Si estás considerando desplegar un sitio web personal o cualquier otra aplicación estática, te animo a explorar las opciones que AWS ofrece y a experimentar con una arquitectura serverless. Aunque puede haber una curva de aprendizaje, los beneficios en términos de escalabilidad, costo y mantenimiento pueden ser significativos.