Servidor disponible solo los jueves de 10:30 a 12:30 y los viernes de 10:00 a 13:00 (hora de Madrid); fuera de ese horario está apagado. Fuera del horario, usa la documentación local del material que te descargaste (el README.md de cada carpeta).
G214 · CUNEF
Inicio / tema5 / 05.01-infraestructurabase

Tema 5 · 1 · Infraestructura base (Paso 0)

Diapositivas del Tema 5: preparación del laboratorio (antes del Ejercicio 1). Duración: 5 min de preparación + 5-10 min de espera del stack. Coste: la RDS y la EC2 facturan por hora mientras existan; una sesión de 2-3 horas cuesta del orden de céntimos, pero dejar esta infraestructura encendida días cuesta del orden de 1 USD al día (tarifas de lista, sin Free Tier; las IPv4 públicas también pueden facturarse por hora). Para que no se quede encendida por olvido, se apaga sola a las 4 horas (ver Apagado automático).

AVISO DE COSTE: la base de datos RDS y la máquina EC2 de esta carpeta facturan por hora mientras existan, las uses o no, y aunque las cubra el Free Tier o tu crédito (lo consumen). El apagado automático las para, pero no las borra (apagadas siguen cobrando sus discos, y la RDS parada la enciende AWS sola a los 7 días). Cuando termines todo el Tema 5, borra esta infraestructura (sección Limpieza: ./gestionar-etl-base.sh eliminar). No basta con cerrar CloudShell: los recursos viven en tu cuenta de AWS, no en CloudShell.

Estado de la verificación: el script se probó en AWS real (crear, estado, extender, vencimiento real con la EC2 y la RDS paradas sin destruirse, arranque con crear, --permanente y eliminar con la EC2 y la RDS paradas o en transición, repetido y tras interrumpir una creación). Las salidas de abajo son las que escribe el script; los nombres reales los genera AWS.

¿Dudas con un script? Todos los scripts de esta carpeta traen su propia ayuda: ./gestionar-etl-base.sh --ayuda (también vale --help o -h) explica los pasos y las opciones. Este README.md es el paso a paso de la actividad: tenlo a mano y consúltalo antes de preguntar.

Etiquetas de lo que creas. ./gestionar-etl-base.sh crear etiqueta el stack y todo lo que contiene (bucket, RDS, EC2, Lambda, roles) con curso = G214, universidad = CUNEF, actividad = 05.01-infraestructurabase y script = gestionar-etl-base.sh. Las verás en la consola (pestaña Tags del recurso) y, si hiciera falta borrar a mano, se localizan con aws resourcegroupstaggingapi get-resources --region eu-north-1 --tag-filters Key=actividad,Values=05.01-infraestructurabase. Más detalle (cómo etiquetar con la CLI, cómo buscar y qué hacer en una emergencia): README principal, sección «Etiquetas».

Qué vas a hacer

Vas a crear con un solo script la infraestructura que usan casi todas las actividades del Tema 5: un bucket S3, una base de datos MariaDB (RDS), una máquina EC2 con Adminer (una web para consultar la base de datos desde el navegador) y una función Lambda de marcador. Después compruebas que todo existe y entras en Adminer.

Qué se crea en AWS (región eu-north-1, un único stack de CloudFormation llamado cunef-etl):

Qué es un stack. CloudFormation lee una plantilla (un texto en YAML que describe recursos de AWS) y los crea todos juntos, como una unidad llamada stack. Al borrar el stack se borran todos sus recursos de una vez. Aquí la plantilla va dentro del propio script (ver más abajo).

Qué contiene esta carpeta

Fichero Para qué sirve En qué paso se usa
gestionar-etl-base.sh Un solo script con todo: crear, consultar el estado y borrar (a la fuerza) el stack cunef-etl. Lleva dentro la plantilla de CloudFormation. Con menú numérico o con comandos. Pasos 1-2 (crear) y Limpieza (borrar)
titanic.csv El dataset del Titanic (891 pasajeros). El script lo sube al bucket si está en la carpeta desde la que lo lanzas o junto al script. Paso 2 (subida al bucket)
README.md Este documento. Siempre

Dónde está la plantilla de CloudFormation. Antes era un fichero aparte; ahora está embebida al final de gestionar-etl-base.sh, entre las marcas # >>>>> INICIO ARCHIVO EMBEBIDO: plantilla-etl-base.yaml y # <<<<< FIN ARCHIVO EMBEBIDO. El script la escribe en una carpeta temporal cuando la necesita y la borra al terminar: no tienes que hacer nada. Si quieres leerla o editarla, vuélcala a un fichero:

./gestionar-etl-base.sh extraer            # escribe plantilla-etl-base.yaml en la carpeta actual
USAR_LOCAL=1 ./gestionar-etl-base.sh crear # crea el stack con TU copia editada en lugar de la embebida

titanic.csv (los datos) no se embebe: sigue siendo un fichero aparte.

Antes de empezar

Cómo llevar los ficheros a CloudShell

  1. En tu PC, comprime esta carpeta entera (05.01-infraestructurabase, no solo su contenido): clic derecho → Comprimir en archivo ZIP (Windows 11), Enviar a > Carpeta comprimida en zip (Windows 10) o Comprimir (Mac). Obtienes 05.01-infraestructurabase.zip.
  2. Abre CloudShell desde la consola de AWS (región eu-north-1). La primera vez tarda un minuto en arrancar.
  3. Actions → Upload file, elige el zip y confirma. Queda en tu carpeta personal (~).
  4. Ejecuta:
cd ~
unzip -o 05.01-infraestructurabase.zip && cd 05.01-infraestructurabase
chmod -R u+rwX . && chmod +x *.sh
ls

Si ya subiste g214-materiales.zip (README principal), no necesitas este zip: entra con cd ~/g214-materiales/tema5/05.01-infraestructurabase y, si algún fichero da Permission denied, ejecuta allí chmod -R u+rwX . && chmod +x *.sh.

Qué verás: gestionar-etl-base.sh, README.md y titanic.csv. Si cd da error, el zip no tenía la carpeta dentro: mira qué ha creado con ls ~.

chmod +x *.sh es necesario: al descomprimir pueden perderse los permisos de ejecución y daría Permission denied. Es seguro repetirlo. (Si no quieres hacerlo, bash gestionar-etl-base.sh crear funciona igual.)

Comprueba que CloudShell tiene aws y tus credenciales (es lo único que necesita este script):

command -v aws >/dev/null && echo "OK     aws" || echo "FALTA  aws"
aws sts get-caller-identity --query Account --output text

Qué verás: OK aws y el número de tu cuenta de AWS (12 dígitos). Si sale FALTA aws, no estás en CloudShell: usa CloudShell. (jq, zip y unzip ya no hacen falta para este script; unzip solo para abrir el zip de arriba.)

Notas de uso de CloudShell:

Comandos del script

./gestionar-etl-base.sh                  # menú numérico (solo si hay un terminal)
./gestionar-etl-base.sh crear            # crea el stack (apagado automático a las 4 h)
./gestionar-etl-base.sh crear --horas 8  # ... con otro plazo (de 1 a 24 horas)
./gestionar-etl-base.sh crear --permanente  # ... sin apagado automático (cuesta dinero)
./gestionar-etl-base.sh extender         # solo cambia el plazo (otras 4 h; también --horas N o --permanente)
./gestionar-etl-base.sh estado           # comprueba el estado del stack, de cada recurso y del apagado automático
./gestionar-etl-base.sh eliminar         # borra TODO (pide confirmación); con --si o -y no pregunta
./gestionar-etl-base.sh extraer          # escribe la plantilla embebida (plantilla-etl-base.yaml) en la carpeta actual
./gestionar-etl-base.sh ayuda            # muestra el uso

Alias que también entiende: create, desplegar, arrancar (= crear); extend, ampliar, renovar (= extender); status, info, ver, mostrar, verificar (= estado); borrar, delete, destroy, limpiar (= eliminar); extract (= extraer); help, -h, --help (= ayuda). Si lo lanzas sin comando y sin terminal (por ejemplo desde otro programa), imprime el uso y termina: nunca se queda esperando.

Menú (al lanzarlo sin comando en un terminal). Muestra el estado actual del stack cunef-etl y siempre las mismas opciones:

Opción Hace lo mismo que
1) Crear stack crear (si ya existe, arranca lo parado y renueva 4 h)
2) Mostrar información / comprobar estado estado
3) Eliminar stack y todos los recursos eliminar (pide confirmación)
4) Extraer los archivos embebidos (plantilla yaml) extraer
5) Extender el apagado automático 4 horas más extender
6) Hacer el stack PERMANENTE extender --permanente
0) Salir

Apagado automático

Para que la EC2 y la RDS no se queden encendidas (y facturando) por olvido, se apagan solas a las 4 horas de estar listas. Se apagan (stop), no se borran: tu base de datos y tus datos siguen ahí; solo eliminar lo borra todo.

Quiero... Comando
Ver cuánto queda ./gestionar-etl-base.sh estado (línea Apagado automático: se apagará a las HH:MM UTC (dentro de N min))
Ampliar el plazo otras 4 h ./gestionar-etl-base.sh extender (o volver a ejecutar crear)
Otro plazo (1-24 h) ./gestionar-etl-base.sh extender --horas 8 (también vale con crear --horas 8)
Que no se apague nunca ./gestionar-etl-base.sh extender --permanente (¡cuesta dinero hasta que ejecutes eliminar!)
Arrancarlas tras el apagado ./gestionar-etl-base.sh crear (arranca la EC2 y la RDS, espera ~7 min a que la RDS esté disponible y renueva 4 h)
Borrarlo todo ./gestionar-etl-base.sh eliminar

Cómo funciona: la EC2 lleva una etiqueta g214-apagar-tras con la hora de vencimiento (o la palabra permanente) y un pequeño servicio que la mira cada 30 segundos. Al vencer, para la RDS (su rol de IAM solo permite parar esa base de datos) y apaga la EC2. El plazo cuenta desde que todo está listo, no desde que lanzas el comando (la RDS tarda unos 7 minutos).

Qué tener en cuenta:

Paso a paso

1. Lanza el script (desde ~/05.01-infraestructurabase):

./gestionar-etl-base.sh crear

Qué verás: "Comprobando el entorno" con dos comprobaciones en verde (AWS CLI instalado, credenciales correctas con tu número de cuenta y la región eu-north-1). Después "Creando Stack CloudFormation" y "Configuración de parámetros".

El script detecta tu VPC por defecto, una subred por zona de disponibilidad (hasta tres), la clase de la base de datos (ver "Qué elige el script para la RDS") y un par de claves SSH: usa el primero que haya en la región; si no tienes ninguno, crea cunef-etl-key-<número> y guarda su .pem en la carpeta actual. No lo necesitas para el laboratorio y, si ya tenías pares de claves, no se modifica. El stack se crea con la etiqueta Project=g214-etl (útil para localizar en la consola lo que ha creado este laboratorio).

Qué verás, en este orden:

  1. "Configuración de parámetros": la VPC encontrada, las subredes elegidas (una por zona, normalmente tres), la clase de la RDS con una línea que explica por qué, el par de claves detectado o creado, y los valores de la base de datos. La consulta de las zonas de la RDS puede tardar hasta un minuto. Si ves un aviso db.t4g.micro no se ofrece en al menos 2 zonas...; se prueba otra clase, el script pasa solo a db.t3.micro (ambas son clases micro del plan gratuito).
  2. "Validando template..." y "Template válido".
  3. La lista de lo que se va a crear (bucket S3, RDS MariaDB con la clase elegida, EC2 con Adminer t3.micro, Lambda, grupos de seguridad, roles de IAM), el aviso del apagado automático y el aviso de coste.
  4. "Creando stack...", "Stack creación iniciada" y "Esperando a que se complete la creación...".
  5. Durante 5-10 minutos verás una línea de avance cada 20 segundos ([02:40] CREATE_IN_PROGRESS - último evento: MariaDBInstance CREATE_IN_PROGRESS; la base de datos es lo último en quedar lista). El script espera como máximo 45 minutos. No cierres CloudShell ni pulses Ctrl+C. Si algo falla (el stack acaba en ROLLBACK_COMPLETE o create-stack es rechazado), el script lo dice con un ✗ y enseña el motivo (ver "Errores frecuentes").
  6. Al terminar: "Stack creado exitosamente", "Subiendo archivo titanic.csv al bucket S3...", "Archivo titanic.csv subido correctamente" y la línea "Plazo fijado: la EC2 y la RDS se APAGAN (no se borran) a las HH:MM UTC (dentro de 240 min)" (el apagado automático; ver su sección).
  7. Un resumen final como este (los nombres reales los genera CloudFormation):
Información del Stack: cunef-etl
Estado: CREATE_COMPLETE
El stack está listo.

Recursos creados:

Bucket S3: cunef-etl-databucket-xxxxxxxxxxxx
RDS Endpoint: xxxxxxxx.xxxxxxxx.eu-north-1.rds.amazonaws.com
Adminer URL: http://ec2-x-x-x-x.eu-north-1.compute.amazonaws.com/
Lambda Function: cunef-etl-ETLLambda-xxxxxxxx

Credenciales de Base de Datos (fijas en este laboratorio):
Usuario: admin
Contraseña: CunefAdmin!

Comprobación de cada pieza:
  RDS (...): available / db.t4g.micro / 10.11.x
  EC2 Adminer (i-...): running
  ...

Copia a tu bloc de notas el bucket, el endpoint de RDS, la URL de Adminer y el nombre de la Lambda. Puedes volver a verlos cuando quieras con ./gestionar-etl-base.sh estado.

2. Guarda esos datos en variables de shell (vale también si luego cierras la sesión y tienes que recuperarlos):

OUT() { aws cloudformation describe-stacks --stack-name cunef-etl --region eu-north-1 \
  --query "Stacks[0].Outputs[?OutputKey=='$1'].OutputValue" --output text; }
BUCKET=$(OUT BucketName); RDS=$(OUT RDSEndpoint); FN=$(OUT LambdaName); ADMINER=$(OUT AdminerURL)
echo "Bucket : $BUCKET"; echo "RDS    : $RDS"; echo "Lambda : $FN"; echo "Adminer: $ADMINER"

Qué verás: cuatro líneas con valores. Si alguna sale vacía, el stack no está en CREATE_COMPLETE (lanza ./gestionar-etl-base.sh estado). Este bloque lo vas a repetir al empezar cada actividad posterior (cada una lo trae en su README). Ojo con ADMINER: esa salida del stack guarda la URL del primer arranque; si la EC2 se ha apagado y la has vuelto a arrancar con crear, la URL buena es la que enseñan crear y estado.

3. Comprueba el entorno (cinco minutos que evitan la mayoría de los fallos):

# el CSV de partida está en el bucket
aws s3 ls s3://$BUCKET/ --recursive

# la función de marcador existe y con qué configuración
aws lambda get-function-configuration --function-name "$FN" --region eu-north-1 \
  --query "{Runtime:Runtime,Timeout:Timeout,Memoria:MemorySize,Rol:Role}"

# la función responde (aún es un marcador)
aws lambda invoke --function-name "$FN" --region eu-north-1 out.json && cat out.json

Qué verás:

4. Abre Adminer. Adminer es una web sencilla para consultar la base de datos desde el navegador. Corre en la EC2 del stack.

  1. Abre en el navegador la URL de $ADMINER tal cual la da el script (http://<dns-de-la-ec2>/, raíz, no /adminer.php). Es http, no https: el puerto 443 no está abierto y el navegador avisará de "No seguro"; es normal en este laboratorio.
  2. Si la página no carga justo al terminar, espera 2-3 minutos y recarga: la EC2 instala Apache, PHP y Adminer al arrancar y el stack no espera a que termine. (./gestionar-etl-base.sh estado dice si Adminer ya responde, siempre que curl esté disponible, que en CloudShell lo está.)
  3. Rellena el formulario:
Campo Valor
Sistema MySQL (en Adminer 5 aparece como MySQL / MariaDB; es la misma opción: MariaDB habla el protocolo de MySQL)
Servidor el endpoint de la RDS ($RDS), sin http://
Usuario admin
Contraseña CunefAdmin!
Base de datos vacío (la base titanic aún no existe: la crea la Lambda del Ejercicio 1)

Qué verás: tras entrar, Adminer muestra las bases de datos del sistema. La base titanic aparecerá después del Ejercicio 1 (carpeta 05.02) y la base crypto después del tipo 3 del Ejercicio 2 (carpeta 05.05). Para lanzar consultas, usa el enlace SQL command de la columna izquierda.

Qué elige el script para la RDS (y por qué)

Una base de datos RDS se crea en una zona de disponibilidad concreta y no todas las zonas tienen capacidad para todas las clases de instancia en todo momento. Para que el Paso 0 no falle por esto, el script hace tres cosas, y te las cuenta por pantalla:

  1. Consulta en qué zonas se ofrece la clase (aws rds describe-orderable-db-instance-options, solo lectura) y se queda con las subredes de esas zonas, una por zona (hasta tres).
  2. Pasa todas esas subredes a la plantilla (PublicSubnet1Id, PublicSubnet2Id y, si hay tercera, PublicSubnet3Id): el grupo de subredes de la RDS las recibe todas y es AWS quien coloca la instancia en la zona que tenga capacidad en ese momento. Esa consulta informa de dónde se puede pedir la clase, no de si hay hueco ahora. En una prueba real en eu-north-1 la consulta daba 1a, 1b y 1c para db.t4g.micro, pero con solo las subredes de 1a y 1b la RDS se rechazó con no subnets exist in Availability Zones with sufficient capacity ... choose from these Availability Zones: eu-north-1c. Con las tres zonas en el grupo ya no depende de cómo ordene tu cuenta las subredes.
  3. Elige la clase. Por defecto db.t4g.micro. Si no se ofrece en al menos dos zonas de tu VPC, prueba db.t3.micro. Puedes forzar una con una variable de entorno: DB_INSTANCE_CLASS=db.t3.micro ./gestionar-etl-base.sh crear. Ambas son clases micro del plan gratuito de RDS y valen lo mismo para el laboratorio. La plantilla solo admite esas dos (parámetro DBInstanceClass).

Qué hacer si el stack falla con ...sufficient capacity...: el script lo detecta y te lo explica: (1) repite ./gestionar-etl-base.sh crear, que borra solo el stack fallido y reintenta (la capacidad de una zona cambia con el tiempo); (2) si vuelve a fallar, lanza DB_INSTANCE_CLASS=db.t3.micro ./gestionar-etl-base.sh crear. Si ninguna de las dos clases se ofrece en dos zonas de tu VPC, el script se detiene antes de crear nada y te dice qué consulta lanzar.

Errores frecuentes

Limpieza

Esta carpeta crea la infraestructura base y su borrado debe ser el ÚLTIMO paso de todo el Tema 5: las carpetas 05.02, 05.03, 05.05, 05.07 y 05.08 usan su bucket y su RDS. Limpia primero lo de esas carpetas (cada README tiene su propia sección Limpieza) y vuelve aquí al final.

1. Borra todo con el script (no desde la consola):

./gestionar-etl-base.sh eliminar

(o 3) Eliminar stack y todos los recursos en el menú). Te pregunta ¿Seguro que quieres borrarlo todo? [s/N]: contesta s. Con ./gestionar-etl-base.sh eliminar --si (o -y) no pregunta.

El borrado es forzado: funciona sea cual sea el estado del stack (CREATE_COMPLETE, ROLLBACK_COMPLETE, CREATE_FAILED, DELETE_FAILED...). En este orden: (1) vacía el bucket (archivos, versiones antiguas, marcadores de borrado y subidas a medias; si no, CloudFormation no puede borrarlo e incluye los de titanic/ y crypto/); (2) borra el stack (empieza por lo que más cuesta: la RDS y la EC2), mostrando el avance cada 20 s y esperando 5-10 minutos; (3) si el stack se queda en DELETE_FAILED, trata la causa (bucket lleno, grupos de seguridad aún en uso, RDS/EC2 todavía borrándose) y reintenta; como último recurso lo borra conservando solo lo que lo bloquea y lo borra después a mano; (4) barre los restos: función Lambda, rol de IAM y sus políticas, y el grupo de logs /aws/lambda/cunef-etl-ETLLambda-... (CloudFormation no lo borra); (5) verifica y te enseña qué queda. La plantilla no deja instantáneas de la base de datos y, aun así, el script comprueba y borra cualquier instantánea o copia de seguridad automática de la RDS que hubiera. Funciona igual con la EC2 y la RDS paradas (por el apagado automático): una RDS parada se borra directamente, y si está parándose o arrancando el script espera a que acabe esa transición antes de borrarla (puede tardar unos minutos más).

Qué verás al final: una lista "Verificación final" con una línea por recurso (✓ ... no existe) y "No queda nada del laboratorio en tu cuenta." Si algo no se pudo borrar, sale marcado con ✗ ... AÚN EXISTE (las RDS y EC2 que siguen existiendo avisan de que siguen facturando) y te dice que repitas ./gestionar-etl-base.sh eliminar. Si no hay nada que borrar, lo dice y termina bien (es seguro repetirlo). Si se corta la conexión a mitad, AWS sigue borrando; repite el comando para ver el resultado.

2. Comprueba que no queda nada facturando (solo lectura; el script ya lo hace, esto es una segunda comprobación independiente):

aws cloudformation list-stacks --region eu-north-1 \
  --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE ROLLBACK_COMPLETE CREATE_FAILED DELETE_FAILED \
  --query "StackSummaries[].[StackName,StackStatus]" --output table
aws rds describe-db-instances --region eu-north-1 \
  --query "DBInstances[].[DBInstanceIdentifier,DBInstanceStatus]" --output table
aws ec2 describe-instances --region eu-north-1 \
  --filters Name=instance-state-name,Values=pending,running,stopping,stopped \
  --query "Reservations[].Instances[].[InstanceId,State.Name]" --output table

Qué debes ver: ningún stack cunef-etl*, ninguna instancia RDS ni EC2 de este laboratorio (las tablas salen vacías o sin filas de este laboratorio). Si aparecen instancias de otros temas (por ejemplo la RDS o la EC2 con Adminer del Tema 3), también facturan: bórralas siguiendo el README de ese tema.

3. Limpieza opcional (casi no cuesta nada, pero conviene dejar limpio):

Cómo sabes que has terminado


Anterior: (ninguna, es la primera actividad del Tema 5) · Siguiente: Tema 5 · 2 · ETL Titanic