Introducción a AWS

Introducción al despliegue en la nube AWS

¿Qué es AWS Academy?

Crear instancia EC2

EC2 con User Data

1 - Práctica Inicial

Primera práctica

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

Práctica de instalacion de apache con 2 virtualhosts

Learner Lab

Ayuda configuración apache:

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 el ssh en los Learner Lab) o si lo subes a un sitio público, puedes descargarlo con wget y descomprimirlo dentro de la máquina en la nube

3 - Despliegue de una web estática con S3 + CloudFront

Despligue de una web estática en S3 + CloudFront

Static Web S3

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

Despligue de una web estática con Hugo en S3 + CloudFront

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

Crear Web estática en S3 con AWS 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

Práctica de instalacion de dos máquinas compartiendo un volumen EFS

Objetivo:

  • Crear un servicio web con un sistema de ficheros compartido

Tareas:

En construcción

5 - Práctica - Certificado SSL

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

Conexión con Putty

Apapche / Nginx proxy inverso

Requisitos

# /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

Alojar un sitio web estático en Amazon S3, Amazon CloudFront y Route 53

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: S3-CF-Route53

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

  1. Ve a la consola de administración de Amazon CloudFront.
  2. En la lista de distribuciones haz click en Create Distribution, y luego selecciona una distribución Web.
  3. 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.
  4. En Restrict Bucket Access selecciona Yes.
  5. En Origin Access Identity escoge Create a New Identity.
  6. En Grant Read Permissions on Bucket selecciona Yes, Update Bucket Policy.
  7. En Viewer Protocol Policy escoge Redirect HTTP to HTTPS.
  8. En Default Root Object introduce el archivo correspondiente, en principio index.html.
  9. 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.

nameservers

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

Despliegue usando CloudFormation

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

Introducción al uso del CLI desde 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

Configuración de AWS CLI con AWS Academy

Instalación de AWS CLI

https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

Configuración en AWS Academy