Cloud IO Enabler Podcast
|
En este tutorial vamos a ver el despliegue de una Aplicación Java con Spring Boot y Docker en Elastic Beanstalk de AWS, paso a paso y estudiando los temas principales de este servicio.
¿Qué es Elastic Beanstalk?
Elastic Beanstalk es un servicio de AWS que simplifica el despliegue de aplicaciones en la nube. ¿Cómo lo hace? Este servicio tiene más de 100 servicios asociados y es compatible con aplicaciones desarrolladas en los lenguajes Go, Java, .NET, Node.js, PHP, Python y Ruby, y los orquesta creando una infraestructura basada en el código desplegado de la aplicación y archivos de configuración adicionados en el despliegue.
El desarrollador no tiene que aprovisionar nada.. o casi nada manualmente.
¿Porqué este tutorial?
Actualmente, existen muchos ejemplos de cómo desplegar aplicaciones en Elastic Beanstalk, y los puedes encontrar aquí. Sin embargo, ninguno de ellos aborda específicamente el despliegue de una aplicación Java con Spring Boot y Docker en Elastic Beanstalk. Este artículo asume que tienes conocimientos básicos de este servicio, por lo que si aún no estás familiarizado con el mismo, revisa aquí.
Contenido
En este tutorial, vamos a ver cómo desplegar una aplicación de ejemplo desarrollada con Java, utilizando el framework Spring Boot y diseñada para ser desplegada como contenedor Docker.
Además, realizaremos el proceso manualmente (por línea de comandos) y no a través de la consola web de AWS, ya que interactuar con la consola web cada vez que queremos hacer cambios en una aplicación y subirla a la nube, no es automatizable y puede ser largo y complejo.
Por lo tanto, los pasos a seguir son:
- Descargar la aplicación y probarla localmente.
- Instalar y configurar el cliente Elastic Beanstalk CLI.
- Desplegar una primera versión en desarrollo (dev).
- Desplegar una versión en QA (próximamente).
Descargar la aplicación y probarla localmente
La aplicación de ejemplo es un simple CRUD, que puedes descargar aquí con el comando:
git clone https://github.com/pazfernando/crud-spring-boot-example.git
Ve a la carpeta donde se descargó y compílala con (requieres tener instalado Java 17+):
cd crud-spring-boot-example
./mvnw clean install
Ejecuta la aplicación con:
java -jar target/crud-0.0.1-SNAPSHOT.war
Prueba la aplicación en tu navegador con:
Instalar y configurar el cliente Elastic Beanstalk CLI
IMPORTANTE: El procedimiento a continuación es para ambiente Linux, ya que tiene mejor soporte para herramientas y frameworks de desarrollo en general. Si no tienes Linux o Mac, instala WSL en Windows. Mira las instrucciones aquí. Por defecto tendrás un Ubuntu instalado en Windows y podrás usarlo ejecutando en PowerShell lo siguiente:
wsl
Listo, asumimos desde aquí que tienes Linux, Mac o WSL en Windows.
Instalación de pyenv
Empezamos instalando un manejador de versiones de Python llamado pyenv. Encuentra cómo aquí.
Post instalación de pyenv
Añade o verifica estas líneas en .bashrc de $HOME:
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
Actualiza tu .bashrc con:
source ~/.bashrc
Instala la última versión estable de Python
Encuentra la documentación de versiones estables en https://devguide.python.org/versions/. La instalación es con el comando:
pyenv install 3.11
IMPORTANTE: A la fecha de creación de este artículo, puedes usar Python 3.11 máximo.
Configura esta versión como la de defecto en tu ambiente:
pyenv global 3.11
Instala virtualenv para aislar tu ambiente de Python
Encuentra cómo hacerlo aquí.
Instala Elastic Beanstalk CLI
Encuentra cómo hacerlo aquí.
Actualiza tu .bash_profile
para incluir los ejecutables de Elastic Beanstalk CLI en tu PATH:
echo 'export PATH="/home/pazfernando/.ebcli-virtual-env/executables:$PATH"' >> ~/.bash_profile
Refresca tus archivos de ambiente en tu $HOME
:
source ~/.bash_profile
source ~/.profile
Desplegar una primera versión en desarrollo (dev)
Ve a la carpeta del proyecto (donde se descargó).
Configura el Elastic Beanstalk CLI, mira cómo hacerlo aquí.
Aspectos importantes previos
Antes de desplegar la aplicación, hay ciertos puntos esenciales a entender acerca de Elastic Beanstalk, ya que este conocimiento nos dará el entendimiento de por qué se despliega una aplicación de una forma u otra.
Ignorando archivos con .ebignore
Cuando desplegamos aplicaciones con Elastic Beanstalk CLI, debemos saber qué archivos son ejecutables, cuáles son de configuración, cuáles son de apoyo, etc. Esto se debe a que CLI empaqueta dichos archivos en un archivo .zip
para luego extraerlo y desplegarlo en la instancia o instancias de la infraestructura que sirve la aplicación.
Por defecto, Elastic Beanstalk CLI busca el archivo .gitignore
para saber, desde la carpeta donde se están ejecutando los comandos, qué archivos debe excluir de este archivo .zip
. Pero como sabemos, para los proyectos Java, el archivo .gitignore
excluye el directorio target/
, el cual es esencial pues tiene el artefacto compilado del proyecto, y en su lugar empaqueta src/
y otros archivos que son fuentes de la aplicación, y que en este caso no aplican.
Esta estrategia funciona muy bien en proyectos tipo Python o PHP donde no hay compilados, pero no en el caso de Java. Aquí aparece otro archivo, .ebignore
, que es otro recurso que busca por defecto Elastic Beanstalk CLI ante la ausencia de un archivo .gitignore
o incluso lo precede si existiera. Por esta razón, el archivo .ebignore
en este tipo de proyectos es tan importante, y por eso nosotros tenemos en los fuentes este contenido:
HELP.md
src/
*
!Dockerfile
!target/
!.ebextensions
Esto asegura y le dice a Elastic Beanstalk CLI qué ignorar y por ende qué sí empaquetar. En nuestro caso, es importante Dockerfile
, target/
y .ebextensions
.
Configuración avanzada con .ebextensions
Desplegar una aplicación con Elastic Beanstalk no es siempre, o nunca lo es, algo tan simple como desplegar un artefacto. Si bien la infraestructura se aprovisiona automáticamente, la aplicación suele requerir de variables de ambiente, datos de conexión con servicios externos, capacidades mínimas, etc.
¿Cómo especificamos esto sin tocar el código? La respuesta es con archivos de configuración o archivos .ebextensions
.
En nuestro caso, tenemos el archivo env-vars.config
donde configuramos ciertas variables de ambiente para que funcione la aplicación:
option_settings:
aws:elasticbeanstalk:application:environment:
SPRING_PROFILES_ACTIVE: dev
CRUD_DB_URL: 'jdbc:postgresql://${RDS_ENDPOINT}/crud_spring_boot_example'
CRUD_DB_USERNAME: ebroot
CRUD_DB_PASSWORD: clave
Algo a destacar es SPRING_PROFILES_ACTIVE
que determina cómo va a funcionar la aplicación Java + Spring Boot. En la vida real, tenemos cientos de configuraciones posibles que podemos hacer a través de estos archivos. Puedes aprender más aquí.
La documentación es un poco confusa, por eso te dejo dos enlaces más de los tipos de opciones: comando opciones y de las opciones a detalle aquí.
Trabajando con aplicaciones del tipo Docker
Para empezar, necesitas un Dockerfile
que en nuestro caso contiene:
FROM amazoncorretto:17.0.11-alpine
ARG JAR_FILE=target/*.war
COPY ${JAR_FILE} app.jar
EXPOSE 8080
CMD ["java", "-jar", "/app.jar"]
Muy simple y claro, y que será incluido en el archivo .zip
gracias a nuestro archivo .ebignore
.
No tenemos en este caso Docker Compose y lo haremos a partir de ese archivo. Sin embargo, si quieres saber más de las opciones de despliegue, puedes mirarlo aquí.
IMPORTANTE: Hay otra forma de hacerlo en un clúster de Amazon ECS (Elastic Container Service), que está fuera de esta explicación pero que puedes consultarla aquí.
Despliega la aplicación
Excelente, ahora para desplegar vamos a ejecutar el comando:
eb create --single
El --single
nos ayuda a desplegar una infraestructura simple, sin redundancia y alta disponibilidad, y que aplica en este caso del tutorial.
Verás algo como:
Enter Environment Name
(default is crud-spring-boot-example-dev):
Enter DNS CNAME prefix
(default is crud-spring-boot-example-dev):
Would you like to enable Spot Fleet requests for this environment? (y/N):
Creating application version archive "app-0048-240801_111838855018".
Uploading: [##################################################] 100% Done...
...
2024-08-01 16:21:52 INFO Application available at crud-spring-boot-example-dev.us-east-1.elasticbeanstalk.com.
2024-08-01 16:21:54 INFO Successfully launched environment: crud-spring-boot-example-dev
IMPORTANTE: Si no eliges --single
, adicionalmente te preguntarán alguna información necesaria para el despliegue, sigue las siguientes recomendaciones:
- Usa Application Load Balancer ALB (por defecto)
- Di que no a Spot Fleet (por defecto)
- Todo lo demás que no sepas deja por defecto.
Prueba tu aplicación visitando precisamente el url de la salida:
http://crud-spring-boot-example-dev.us-east-1.elasticbeanstalk.com/
Finaliza el despliegue IMPORTANTE IMPORTANTE IMPORTANTE
Si fallas este paso tu factura puede salir muy alta, especialmente si no usaste --single
, así que ejecuta este comando para finalizar el tutorial:
eb terminate
Pensamientos finales
Desplegar una aplicación Java con Spring Boot en Elastic Beanstalk de AWS utilizando Docker es algo más complejo, pero siguiendo estos pasos detallados, el proceso se vuelve manejable y entendible, por lo que espero que sea de valor para ustedes.
Elastic Beanstalk de AWS simplifica enormemente el proceso de despliegue y gestión de aplicaciones, permitiendo enfocarte en el desarrollo sin preocuparte por la infraestructura. Utilizar Docker agrega una capa de consistencia y portabilidad, asegurando que tu aplicación funcione de la misma manera en cualquier entorno.
Es vital seguir entender prácticas como el uso adecuado de archivos .ebignore
y .ebextensions
para asegurar que solo los archivos necesarios se incluyan en el despliegue y que la configuración de tu aplicación sea flexible y segura. Además, siempre finaliza los entornos no utilizados para evitar costos innecesarios.
Usar perfiles de Maven es un poco más complicado, pero la idea es trabajar con .ebextension
para configurar los valores requeridos, si hay recursos relacionados como bases de datos servicios colas y demás, la recomendación es que se creen fuera de el scope de la aplicación.
La implementación de una aplicación en la nube es un proceso iterativo. A medida que te familiarices con Elastic Beanstalk y Docker, encontrarás formas de optimizar y mejorar tu flujo de trabajo. Comparte tus experiencias y cualquier obstáculo que encuentres, y sigue aprendiendo de la documentación y la comunidad de AWS.