Versión imprimible multipagina. Haga click aquí para imprimir.
Introducción a AWS
1 - Práctica Inicial
Introducción a EC2
Revisa documentación del módulo 6: https://awsacademy.instructure.com/courses/34868/modules#module_390032
Taller guiado de EC2 del curso Cloud Foundations
https://awsacademy.instructure.com/courses/34868/modules/items/2944677
2 - Práctica Apache con VirtualHosts
Learner Lab
- Curso: https://awsacademy.instructure.com/courses/57608
- Learner Lab: https://awsacademy.instructure.com/courses/57608/modules/items/5062395
Ayuda configuración apache:
- Recuerda que la configuración en AMI LINUX es diferente a la de Ubuntu. En este caso, el archivo de configuración de apache es
/etc/httpd/conf/httpd.conf
y el directorio de los virtualhosts es/etc/httpd/conf.d/
https://thewebhacker.com/setting-up-apache-vhosts-on-aws-linux/ - Un ejemplo de un Learner Lab con EC2 & Apache: https://www.youtube.com/watch?v=cX80gnEHs_E
Objetivo:
Instalar apache en una instancia ECS y configurar 3 virtualhosts: uno para la página principal, otro para la página de relojesvex y otro para airspace. Las dos últimas webs están en la tarea de moodle.
Tareas:
- Instala apache en la instancia EC2 y configura los vhosts
- Tendrás que configurar el archivo hosts de tu máquina local para que puedas acceder a las páginas web desde tu navegador.
- La web principal (a la que accedes por la ip pública de la instancia EC2) debe mostrar un mensaje de bienvenida y un enlace a las otras dos páginas.
- Los archivos de las webs los puedes subir por
scp
(revisa cómo se configura elssh
en los Learner Lab) o si lo subes a un sitio público, puedes descargarlo conwget
y descomprimirlo dentro de la máquina en la nube
3 - Despliegue de una web estática con S3 + CloudFront
Learner Lab
- Curso: https://awsacademy.instructure.com/courses/57608
- Learner Lab: https://awsacademy.instructure.com/courses/57608/modules/items/5062395
Ayuda:
- https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html
- Amazon S3
- Ejemplo S3 + CloudFront:
Objetivo:
Desplegar una web estática en S3 y añadir CloudFront como CDN.
Tarea1: Despliegue de una web estática en S3
Sigue las instrucciones de https://docs.aws.amazon.com/AmazonS3/latest/userguide/HostingWebsiteOnS3Setup.html
- Crear un bucket S3
- Configurar el bucket para que sea accesible como web estática
- Añade los ficheros de una de las webs estáticas del ejercicio anterior. Puedes subirlos desde la misma interfaz web de la consola de AWS. Veremos también cómo puedes hacerlo desde AWS CLI.
Tarea2: Añadir CloudFront como CDN
Sigue el ejemplo de https://aws.amazon.com/es/blogs/aws-spanish/como-alojar-tu-sitio-web-estatico-en-amazon-s3-y-amazon-cloudfront/
Nosotros no integraremos AWS CodePipeline, AWS CodeCommit y AWS CodeBuild.
Aquí tienes un ejemplo paso a paso:
3.1 - Despliegue de una web hecha con Hugo en S3
Pasos
Previo
Configurar AWS CLI
- Conecta con el
Learner Lab
- Copia las
credentials
de tu usuario de IAM en~/.aws/credentials
Configurar hugo.yml
Ejemplo
[deployment]
# By default, files are uploaded in an arbitrary order.
# Files that match the regular expressions in the "Order" list
# will be uploaded first, in the listed order.
order = [".jpg$", ".gif$"]
[[deployment.targets]]
# An arbitrary name for this target.
name = "mydeployment"
# S3; see https://gocloud.dev/howto/blob/#s3
# For S3-compatible endpoints, see https://gocloud.dev/howto/blob/#s3-compatible
URL = "s3://<Bucket Name>?region=<AWS region>" # Configura aquí tu bucket
# If you are using a CloudFront CDN, deploy will invalidate the cache as needed.
cloudFrontDistributionID = <ID> # Sólo si quieres usar cloudfront
# Optionally, you can include or exclude specific files.
# See https://godoc.org/github.com/gobwas/glob#Glob for the glob pattern syntax.
# If non-empty, the pattern is matched against the local path.
# All paths are matched against in their filepath.ToSlash form.
# If exclude is non-empty, and a local or remote file's path matches it, that file is not synced.
# If include is non-empty, and a local or remote file's path does not match it, that file is not synced.
# As a result, local files that don't pass the include/exclude filters are not uploaded to remote,
# and remote files that don't pass the include/exclude filters are not deleted.
# include = "**.html" # would only include files with ".html" suffix
# exclude = "**.{jpg, png}" # would exclude files with ".jpg" or ".png" suffix
# [[deployment.matchers]] configure behavior for files that match the Pattern.
# See https://golang.org/pkg/regexp/syntax/ for pattern syntax.
# Pattern searching is stopped on first match.
# Samples:
[[deployment.matchers]]
# Cache static assets for 1 year.
pattern = "^.+\\.(js|css|svg|ttf)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = true
[[deployment.matchers]]
pattern = "^.+\\.(png|jpg)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = false
[[deployment.matchers]]
# Set custom content type for /sitemap.xml
pattern = "^sitemap\\.xml$"
contentType = "application/xml"
gzip = true
[[deployment.matchers]]
pattern = "^.+\\.(html|xml|json)$"
gzip = true
Crear web
Genera la web en el directorio
public
$ hugo
Desplegar web
$ hugo deploy
3.2 - Crear web estática en S3 con CLI
Pasos
Previo
Configurar AWS CLI
- Conecta con el
Learner Lab
- Copia las
credentials
de tu usuario de IAM en~/.aws/credentials
Crear Bucket S3
bucket_name="miwebs3-nombre-bucket-unico"
aws s3api create-bucket --bucket "${bucket_name}"
Configuramos el bucket para que sea publico
aws s3api put-public-access-block --bucket "${bucket_name}" --public-access-block-configuration "BlockPublicPolicy=false"
aws s3api put-bucket-policy --bucket "${bucket_name}" --policy '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::'"${bucket_name}"'/*"
]
}
]
}'
Subimos un fichero html
Mostramos un ejemplo, puedes subir tu web estática
echo "<html><center><h1>My Static Website on S3</h1></center></html>" > index.html
aws s3 cp index.html s3://"${bucket_name}"
Configuramos el bucket para que sea un sitio web
aws s3 website s3://"${bucket_name}" --index-document index.html
Comprobamos que funciona
curl http://"${bucket_name}".s3-website.us-east-1.amazonaws.com
4 - Práctica 3 Apaches en EC2 + EFS
Learner Lab
- Curso: https://awsacademy.instructure.com/courses/57608
- Learner Lab: https://awsacademy.instructure.com/courses/57608/modules/items/5062395
Ayuda configuración:
Objetivo:
- Crear un servicio web con un sistema de ficheros compartido
Tareas:
5 - Práctica - Certificado SSL
HTTPS
Docs AWS
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2023.html#letsencrypt-2023
- https://docs.aws.amazon.com/es_es/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-2.html#letsencrypt
Docs LetsEncrypt/Certbot
Requisitos
- Nombre de dominio
- Configurado con la ip pública de una máquina ECS
- Servidor web configurado en esa máquina
Instalación Certbot
# instalación paquetes
$ sudo dnf install -y python3 augeas-libs pip
# Creación entorno virtual python
$ sudo python3 -m venv /opt/certbot/
# Actualización pip
$ sudo /opt/certbot/bin/pip install --upgrade pip
# Instalación certbot
$ sudo /opt/certbot/bin/pip install certbot certbot-apache
Creación certificado
# parar servidor (certbot levanta uno)
$ sudo systemctl stop httpd
$ sudo /opt/certbot/bin/certbot certonly --standalone
# o también más fácil
$ sudo /opt/certbot/bin/certbot --apache
# Sigue los pasos
# Instala el certificado si certbot no ha configurado los archivos de httpd
Al final tendremos estos archivos de configuración.
/etc/httpd/conf.d/ssl.conf
# Dentro tendrá unas líneas similares
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/www.cpilosenlaces.ninja/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.cpilosenlaces.ninja/privkey.pem
/etc/httpd/conf/httpd.conf
Configuración del virtualhost y la redirección de http a https
<VirtualHost *:80>
DocumentRoot "/var/www/html"
ServerName "www.cpilosenlaces.ninja"
ServerAlias "cpilosenlaces.ninja"
#Redirect HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
Vuelve a iniciar apache
$ sudo systemctl stop httpd
Y comprueba que funciona correctamente el certificado y la redirección
Configuración renovación automática
Puedes configurar la renovación automática del certificado
$ echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
$ sudo systemctl restart crond
6 - Práctica - Flask App en EC2
Pasos
- Instalar app flask
- Ejectar con Gunicorn
- Configurar Gunicorn como servicio
- Configurar Apache o Nginx como proxy inverso
Gunicorn y Flask
- https://flask.palletsprojects.com/en/2.2.x/deploying/gunicorn/
- https://docs.gunicorn.org/en/stable/deploy.html
Conexión con Putty
Apapche / Nginx proxy inverso
Requisitos
- App a instalar https://github.com/DAW-distancia/Weather-App
# /etc/systemd/system/temperaturas.service
[Unit]
Description=Gunicorn daemon to serve my flaskapp
After=network.target
[Service]
User=ec2-user
#Group=apache
WorkingDirectory=/home/ec2-user/Weather-App
ExecStart=/home/ec2-user/Weather-App/env/bin/gunicorn -w 2 -b 127.0.0.1:8080 run:app
ExecReload=/bin/kill -s HUP $MAINPID
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl restart temperaturas
sudo systemctl status temperaturas
Configurar Apache como proxy inverso
Versión sencilla
# /etc/httpd/conf.d/temperaturas.conf
DocumentRoot "/home/ec2-user/Weather-App"
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
<Directory /home/ec2-user/Weather-App>
Require all granted
</Directory>
User Data
Si configuras la instacia (tipo, tamaño, claves, puertos, etc) desde la consola de AWS, puedes añadir un script de arranque que se ejecutará al arrancar la máquina.
#!/bin/bash
yum update -y
yum install -y httpd git
#Apache
systemctl start httpd
systemctl enable httpd
# Tempertaturas
cd /home/ec2-user
git clone https://github.com/DAW-distancia/Weather-App.git
cd Weather-App
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt
# inicializa db
python -c "from weather_app import db; db.create_all()"
# Gunicorn
pip install gunicorn
# Permisos (si no, serán los archivos de root)
chown -R ec2-user:apache /home/ec2-user/Weather-App
# Servicio
cat <<EOF > /etc/systemd/system/temperaturas.service
[Unit]
Description=Gunicorn daemon to serve my flaskapp
After=network.target
[Service]
User=ec2-user
#Group=apache
WorkingDirectory=/home/ec2-user/Weather-App
ExecStart=/home/ec2-user/Weather-App/env/bin/gunicorn -w 2 -b 127.0.0.1:8080 run:app
ExecReload=/bin/kill -s HUP $MAINPID
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start temperaturas
systemctl enable temperaturas
# Apache
cat <<EOF > /etc/httpd/conf.d/temperaturas.conf
DocumentRoot "/home/ec2-user/Weather-App"
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
<Directory /home/ec2-user/Weather-App>
Require all granted
</Directory>
EOF
systemctl restart httpd
7 - Route53 + CloudFront + S3
Guión basado en https://aws.amazon.com/es/blogs/aws-spanish/como-alojar-tu-sitio-web-estatico-en-amazon-s3-y-amazon-cloudfront/
Aprenderás:
- Cómo alojar un sitio web estático en Amazon S3
- Cómo configurar Amazon CloudFront para que sirva el contenido de Amazon S3
- Cómo configurar Amazon Route 53 para que resuelva los nombres de dominio de tu sitio web
- Cómo configurar tu sitio web para que se sirva a través de HTTPS
- Enlazar el nuevo suddominio con CloudFront
- Manejar S3 y CloudFront con AWS CLI
- Invalidar páginas del caché de CloudFront
Cómo alojar un sitio web estático en Amazon S3, Amazon CloudFront y Route 53
Motivación
Hoy en día es muy habitual tener que servir algún tipo de sitio web estático, desde sencillas páginas web para que tus clientes puedan conocerte hasta complejas aplicaciones basadas en frameworks como React, Vue.js o Angular. En un escenario tradicional, este contenido se ofrecería desde un servidor web como Apache o NGINX ejecutándose, por ejemplo, en una instancia de Amazon EC2. Por lo tanto, el operador de la infraestructura debe encargarse de tareas como la configuración de los servidores y de la aplicación de parches y actualizaciones, y asegurarse de que hay redundancia para seguir respondiendo peticiones aunque alguna de las máquinas tenga algún problema.
En este artículo veremos cómo utilizar nuestro servicio de almacenamiento de objetos, Amazon S3, y nuestra red de entrega de contenido (CDN), Amazon CloudFront, para liberarte de esa carga de trabajo y servir tus aplicaciones y sitios estáticos de manera eficiente, segura, rápida y económica. Además, haremos uso de Amazon Route 53 para gestionar los registros DNS.
Descripción del escenario
- Queremos crear un sitio web estático
- El sitio debe alojarse de manera sencilla y requerir el mínimo esfuerzo de operación por nuestra parte.
- El sitio debe poder visitarse a través de HTTPS usando nuestro propio dominio
Recuerda que tienes que crear tu propio dominio en name.com usando la promoción del student pack de github
- El sitio debe estar disponible el máximo tiempo posible (alta disponibilidad).
- El sitio debe servirse con baja latencia a todos nuestros clientes, que se encuentran repartidos por todos los países de habla hispana.
- El sitio debe ser fácil de actualizar, de manera que podamos cambiar el contenido sin tener que preocuparnos por la infraestructura.
El siguiente diagrama muestra la arquitectura de la solución:
Alojamiento del sitio en Amazon S3
Amazon S3 es el servicio de almacenamiento de objetos de AWS, que permite guardar y acceder a cualquier tipo de fichero de hasta 5 TB de tamaño de manera segura a través de una API. Los clientes no tienen que gestionar ningún tipo de servidor. Internamente, Amazon S3 se encarga de almacenar múltiples copias del objeto en diferentes Zonas de Disponibilidad dentro de la región seleccionada, razón por la que ofrece una durabilidad que alcanza los 11 nueves (99.999999999%).
La unidad lógica de almacenamiento en S3 es el bucket. El primer paso consiste en crear un bucket, dentro del cuál subiremos los archivos de nuestra web. Recuerda que en los lab usamos la región us-east-1.
Pasos
- Dirígete a la consola de administración de Amazon S3.
- En la lista de buckets, haz click en Create bucket.
- Dale un nombre arbitrario a tu bucket (recuerda que los nombres deben ser únicos dentro de S3 de manera global). Puedes dejar el resto de opciones como están.
- Haz click en Create bucket.
- Ve a la vista de detalle del bucket. Haz click en Upload y sube los ficheros de tu web.
Ahora mismo, estos objetos son privados y no son accesibles por ningún usuario excepto nosotros. Este es el comportamiento por defecto de S3, aunque los clientes pueden ajustar los permisos de manera granular (idealmente, siguiendo siempre el principio de mínimo privilegio).
S3 ofrece una característica que permite acceder a los objetos de un bucket como si se tratara de un servidor web. Técnicamente esta solución nos podría servir, pero entonces obligaríamos a todos nuestros clientes a acudir a nuestro bucket, que está en la región de us-east-1. Un usuario de Europa lo tendría muy lejos. Incumplimos uno de los requisitos que nos propusimos al inicio. Sin embargo, tenemos otras opciones.
Uso de Amazon CloudFront para servir el sitio
Las redes de entrega de contenidos (content delivery network, CDN) son servidores distribuidos por todo el mundo que actúan como caché para cierto contenido web, idealmente contenido estático que no varía de manera frecuente. Cuando un cliente visita un sitio que se sirve a través de una CDN, su petición acude primero a su caché local (que debería estar muy cerca de él, en su mismo país o incluso en la ciudad). Si el contenido no se encuentra en la caché, la CDN solicita el contenido al origen, lo devuelve al cliente y lo almacena en la caché. A partir de ahí, las peticiones de otros clientes se servirán desde la propia caché mientras el objeto siga ahí, reduciendo de manera notable la latencia de respuesta.
Amazon CloudFront es el servicio de CDN de AWS. Con más de 220 puntos de presencia (PoPs) en todo el mundo, podemos usar CloudFront para servir nuestro contenido a usuarios de manera global con una latencia baja, usando el bucket de S3 que creamos previamente como origen. Para ello tenemos que crear una distribución.
Pasos
- Ve a la consola de administración de Amazon CloudFront.
- En la lista de distribuciones haz click en Create Distribution, y luego selecciona una distribución Web.
- En Origin Domain Name, introduce el nombre de dominio de tu bucket completo, por ejemplo
mi-bucket-de-daw.s3-us-east-1.amazonaws.com
. - En Restrict Bucket Access selecciona Yes.
- En Origin Access Identity escoge Create a New Identity.
- En Grant Read Permissions on Bucket selecciona Yes, Update Bucket Policy.
- En Viewer Protocol Policy escoge Redirect HTTP to HTTPS.
- En Default Root Object introduce el archivo correspondiente, en principio
index.html
. - Haz click en Create Distribution.
Con los pasos 4, 5, y 6 nos aseguramos de que sólo CloudFront puede acceder a los objetos de S3, mediante una identidad de acceso a origen (origin access identity, OAI). Un cliente llamando directamente al bucket de S3 vería su acceso denegado.
La distribución tiene que desplegarse ahora. Tras unos minutos, la distribución pasará a estado Deployed. Si visitas la URL que aparece bajo la columna Domain Name, verás tu web.
Dominio personalizado
Ya tenemos la distribución de CloudFront sirviendo nuestra web por todo el mundo. Sin embargo, el dominio por defecto que CloudFront nos asigna (ab12cd34ef56gh.cloudfront.net) no es, digamos, muy atractivo. Sería ideal poder usar nuestro propio dominio (por ejemplo, www.anycompany.example).
Amazon Route53 es el servicio de AWS para adquirir y gestionar nombres de dominio. Con un SLA del 100%, a través de Route 53 podemos configurar registros DNS que resolverán nuestro dominio a las IPs adecuadas. Además, usaremos AWS Certificate Manager (ACM) para generar de manera gratuita un certificado TLS para nuestro dominio, que asociaremos a CloudFront para poder servir tráfico HTTPS. De nuevo, esto se hará fácilmente y sin tener que gestionar servidores ya que se trata de servicios totalmente gestionados.
Creación de una hosted zone en Amazon Route 53
Con los Learner Lab no podemos adquirir dominios, pero sí gestionarlos.
En Amazon Route 53 todos los registros DNS pertenecientes a un dominio se configuran en una hosted zone. El primer paso es, por lo tanto, crear una:
Dirígete a la consola de administración de Amazon Route 53.
- En el menú de la izquierda, haz click en Hosted zones.
- En la lista de hosted zones, haz click en Create hosted zone.
- En Domain name introduce el dominio raíz que quieres gestionar (el que hayas adquirido en
name.com
). - Asegúrate de que el tipo es Public hosted zone, y haz click en Create hosted zone.
Todas las hosted zones vienen con un registro NS. Éste contiene los servidores de nombres autoritativos para esta hosted zone a los que debes apuntar desde tu registrador, en caso contrario los cambios que realices a continuación no tendrán efecto. En name.com
ve a manage nameservers
del dominio que has registrado y cambia los servidores de nombres por los que te proporciona Route 53.
Creación de un registro DNS hacia la distribución de Amazon CloudFront
En la vista de detalle de la hosted zone de route53
, sigue estos pasos para añadir un registro DNS que permita resolver nuestro subdominio a la distribución de CloudFront:
- Haz click en Create record, selecciona Switch to wizard y escoge Simple routing.
- Haz click en Define simple record.
- En Record name, escribe el prefijo del subdominio. En nuestro caso, www.
- En Value/Route traffic to selecciona Alias to CloudFront distribution, e introduce el dominio de tu distribución (similar a “ab12cd34ef56gh.cloudfront.net”) en el campo Choose distribution.
- Haz click en Define simple record, y a continuación en Create records.
Si ahora resuelves el subdominio completo con una herramienta como nslookup
o dig
, verás que Route 53 proporciona un conjunto de IPs correspondientes al PoP de CloudFront más cercano a ti.
Creación de un certificado TLS con AWS Certificate Manager
Antes de poder servir tráfico HTTPS usando nuestro dominio personalizado necesitamos crear un certificado TLS. AWS Certificate Manager (ACM)
permite generar certificados de manera gratuita. Además, ACM se encarga de aplicarlos a servicios como CloudFront e incluso de renovarlos automáticamente antes de la fecha de expiración. Una vez más, de forma totalmente gestionada.
Antes de emitir el certificado, ACM comprobará que nosotros somos los propietarios del dominio. ACM se integra con Route 53 para crear automáticamente los registros DNS necesarios, haciéndolo si cabe aún más sencillo:
- Ve a la consola de administración de AWS Certificate Manager.
- En la lista de certificados, haz click en Request a certificate.
- Selecciona Request a public certificate y haz click en Request a certificate.
- En Add domain names escribe el subdominio que hemos registrado en Route 53 (en nuestro ejemplo, www.anycompany.example) y haz click en Next.
- Selecciona DNS validation y haz click en Next.
- Haz click en Review, y posteriormente en Confirm and request.
- El dominio estará en el estado Pending validation. Para añadir automáticamente los registros de Route 53 necesarios para que ACM los valide, despliega el detalle del dominio y haz click en Create record in Route 53.
- Haz click en Create tras revisar el registro que será creado.
- Por último, haz click en Continue.
Tras pocos minutos, el certificado pasará al estado Issued
y ya podrá usarse en CloudFront.
Modificación de la distribución de Amazon CloudFront para usar nuestro dominio
El último paso consiste en modificar la distribución de CloudFront para que acepte tráfico dirigido a nuestro dominio:
Ve, de nuevo, a la consola de administración de Amazon CloudFront y selecciona la distribución creada previamente.
- En la pestaña General, haz click en Edit.
- En el campo Alternate Domain NAmes (CNAMEs), que antes dejamos en blanco, añade tu dominio (en nuestro caso, www.anycompany.example).
- En SSL Certificate, escoge Custom SSL Certificate (example.com), y en el campo de texto selecciona el certificado que has creado en ACM.
Cuando el cambio se propague a todos los PoPs, podrás visitar el sitio web con el dominio personalizado.
Despliegue automático de cambios y cache busting
Esta parte la haremos en otra práctica
Despliegue con el cliente de AWS CLI
Subir archivos a s3
# Listado de buckets
aws s3 ls
# Copiar archivos al bucket. En mi caso:
aws s3 cp index.html s3://exhibit-lmorillas/
Invalidar cache de cloudfront
La caché de cloudfront se puede configurar para que expire cada cierto tiempo, pero también podemos invalidar la caché de forma manual. Por defecto los objetos estarán 24 horas. Pero si hacemos un cambio y queremos que se vea inmediatamente, podemos invalidar la caché.
Ejemplo con AWS CLI:
# Listado de distribuciones de cloudfront
aws cloudfront list-distributions
# crear invalidación. Fíjate el el id de la distribución
aws cloudfront create-invalidation --distribution-id ET29UE5BESTWD --path "/index.html"
8 - Práctica - Instalación de Docker en EC2
Presentación:
AWS tiene un servicio de contenedores ECS que permite ejecutar contenedores en la nube. Pero en esta práctica vamos a instalar Docker en una instancia EC2 y ejecutar un contenedor de prueba.
Para desarrollo con contenedores, mejor usar ECS y ECR
Instalación de Docker
Probado en AMI 2023
Todos los comando se ejecutan como root (con sudo)
sudo yum update
# Puedes buscar el paquete
yum search docker
yum info docker
# Instalar docker
sudo yum install docker
# servicio y comprobación
sudo systemctl enable docker
sudo systemctl start docker
sudo systemctl status docker
# Hay que añadir el usuario al grupo docker para que pueda ejecutar los comandos
sudo usermod -a -G docker ec2-user
id ec2-user
# recargar el user (o salir y entrar en el shell)
newgrp docker
Puedes comprobar que funciona correctamente con:
docker run hello-world
Instalación de docker-compose
# 1. Instalar pip
sudo yum install python3-pip
# 2. Elige uno de los 3 métodos siguientes
sudo pip3 install docker-compose # con root access
# O
pip3 install --user docker-compose # sin root access for security reasons
# O también
wget https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)
sudo mv docker-compose-$(uname -s)-$(uname -m) /usr/local/bin/docker-compose
sudo chmod -v +x /usr/local/bin/docker-compose
Comprobación:
docker-compose --version
Un ejemplo complejo
Vamos a instalar una aplicación más compleja y a interactuar con los contenedores. La aplicación a instalar es BakeryDemo, un CMS de prueba de Wagtail.
En el README tienes las instrucciones para instalar con docker-compose. Si analizas el docker-compose:
version: '2'
services:
db:
environment:
POSTGRES_DB: app_db
POSTGRES_USER: app_user
POSTGRES_PASSWORD: changeme
restart: unless-stopped
image: postgres:14.1
expose:
- '5432'
redis:
restart: unless-stopped
image: redis:6.2
expose:
- '6379'
app:
environment:
DJANGO_SECRET_KEY: changeme
DATABASE_URL: postgres://app_user:changeme@db/app_db
REDIS_URL: redis://redis
DJANGO_SETTINGS_MODULE: bakerydemo.settings.dev
build:
context: .
dockerfile: ./Dockerfile
volumes:
- ./bakerydemo:/code/bakerydemo
links:
- db:db
- redis:redis
ports:
- '8000:8000'
depends_on:
- db
- redis
Ves 3 servicios: una base de datos postgres, un redis para caché y la aplicación del CMS (con un Dockerfile específico para python)
Instalación:
# clonamos repositorio
git clone https://github.com/wagtail/bakerydemo.git
cd bakerydemo/
# construir y levantar el contenedor
docker-compose up --build -d
# Comprobar el estado
docker-compose ps
# Ejecutar carga inicial de datos. Son instrucciones que se ejecutan dentro del contenedor de la app
docker-compose run app /venv/bin/python manage.py migrate
docker-compose run app /venv/bin/python manage.py load_initial_data
# Comprobamos que funciona correctamente
curl localhost:8000
Para verlo desde el navegador tendrás que abrir el puerto 8000 en el grupo de seguridad y acceder con el navegador a la ip pública de la instancia EC2, puerto 8000
9 - Infraestrucutra como código: CloudFormation
Documentación
Despliegue de una aplicación web con CloudFormation
Despliegue de una web estática en EC2 con NGINX usando CloudFormation
Requisitos
- Instalar AWS CLI
Creación de la plantilla
Podemos tenerla en S3 o en local. En este caso la tendremos en local.
AWSTemplateFormatVersion: '2010-09-09'
Description: |
Esta plantilla crea un grupo de seguridad con los puertos 22, 80 y 443 abiertos,
crea una instancia EC2 con la AMI Amazon Linux 2023 y le asocia el grupo de seguridad.
También crea una IP elástica y la asocia a la instancia EC2 mediante el recurso AWS::EC2::EIP.
Configura nginx en la instancia EC2 y despliega una web estática en el directorio /usr/share/nginx/html. La web está en un recurso compartido en drive.google.com.
En el output muestra la IP pública de la instancia EC2 (la IP elástica).
Resources:
MySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: sg_web-nginx
GroupDescription: Grupo de seguridad del web-nginx
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-04cb4ca688797756f
InstanceType: t2.small
SecurityGroups:
- !Ref MySecurityGroup
KeyName: vockey
Tags:
- Key: Name
Value: nginx-user-data
UserData:
Fn::Base64:
!Sub |
#!/bin/bash -xe
dnf update -y
dnf install nginx -y
dnf install unzip -y
systemctl start nginx
systemctl enable nginx
cd /usr/share/nginx/html
curl -L -o airspace.zip "https://drive.google.com/uc?export=download&id=1CXihQ2U-EFzHaO3OnggQ6qkkxdC-ibsp"
unzip airspace.zip
# extracción de archivos: están en la carpeta airspace.com
cd airspace.com
mv * ..
cd ..
rm -r airspace.com/
rm airspace.zip
MyEIP:
Type: AWS::EC2::EIP
Properties:
InstanceId: !Ref MyEC2Instance
Outputs:
Website:
Description: The Public IP for the EC2 Instance (Elasic IP)
Value: !Sub 'http://${MyEIP.PublicIp}'
Despliegue de la plantilla
Recuerda que tienes que tener instalado AWS CLI
Conecta con el Learner Lab (
Start Lab
) y configura las credenciales de AWS CLI (AWS Details
->AWS CLI
->Show
)
Descarga el archivo nginx-user-data.yml con la plantilla anterior y ejecuta el siguiente comando:
$ aws cloudformation create-stack --stack-name nginx-user-data --template-body file://nginx-user-data.yml
Comprobación del despliegue
$ aws cloudformation describe-stacks --stack-name nginx-user-data
Cuando se haya desplegado podremos comprobar que la web está desplegada en la IP pública de la instancia EC2 (la IP elástica que muestra el output del comando anterior).
Eliminación de la pila
$ aws cloudformation delete-stack --stack-name nginx-user-data
Propuestas
- Configurar https con certbot automatizado.
- Desplegar varias páginas en nginx para diferentes dominios.
10 - Uso de AWS CLI con AWS CloudShell
Acceso AWS CloudShell
Tienes un botón para abrir el CloudShell
CloudShell ya tiene instalado y configurado el AWS CLI.
Uso del AWS CLI EC2
Listar instancias EC2
Todas las instancias. Toda la información. Salida como json
$ aws ec2 describe-instances
Todas las instancias. Toda la información. Salida como tabla
$ aws ec2 describe-instances --output table
Uso con filtros
Ip, nombre y estado de las instancias que están en ejecución. Salida como tabla
$ aws ec2 describe-instances \
--query "Reservations[*].Instances[*].{PublicIP:PublicIpAddress,Name:Tags[?Key=='Name']|[0].Value,Status:State.Name}" \
--filters Name=instance-state-name,Values=running \
--output table
Id y nombre de las instancias
$ aws ec2 describe-instances --query "Reservations[*].Instances[*].{Name:Tags[?Key=='Name']|[0].Value,InstanceId:InstanceId}" --output table
Parar instancia
$ aws ec2 stop-instances --instance-ids <id de instancia>
Arrancar instancia
$ aws ec2 start-instances --instance-ids <id de instancia>
Uso del AWS CLI S3
listar buckets
$ aws s3 ls
listar objetos de bucket
$ aws s3 ls s3://bucket-name
O recursivo
$ aws s3 ls s3://bucket-name --recursive
subir un archivo a un bucket
$ aws s3 cp file.txt s3://bucket-name
subir un directorio a un bucket
$ aws s3 cp --recursive dir s3://bucket-name
descargar un archivo de un bucket
$ aws s3 cp s3://bucket-name/file.txt .
eliminar bucket
$ aws s3 rb s3://bucket-name --force
eliminar objeto de un bucket
$ aws s3 rm s3://bucket-name/file.txt
10.1 - AWS CLI en AWS Academy
Instalación de AWS CLI
https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html