Nuestro primer Deploy en AWS con Glassfish y MySQL

Luego de desarrollar un sistema viene una parte fundamental que es salir del entorno de pruebas en localhost, y publicar el mismo en la nube para que sea accesible por nuestros clientes o prospectos, ya sea para configurar un entorno de producción o un ambiente de pruebas para realizar alguna demo.

El día de hoy en esta entrada del blog veremos una completa guía de cómo realizar un deploy en AWS, con un servidor de aplicaciones Glassfish (Java) y un servicio de bases de datos relacionales MySQL (RDS).

Itinerario

  1. Tener claros los objetivos del deploy
  2. Configuración de Servidor en AWS
  3. Configurar acceso a la máquina virtual por SSH
  4. Implementación de servicios que brindará el servidor
  5. Procedimiento de instalación Java JDK y JRE 8
  6. Procedimiento de instalación de Glassfish 4.1.1
  7. Despliegue de aplicación web
  8. Rotación de Logs
  9. Configuración de servidor de bases de datos
  10. Configuración de acceso desde la máquina virtual EC2 al RDS
  11. Carga de scripts en el RDS desde nuestro Ubuntu Server
  12. Optimización de glassfish para producción
  13. Procedimiento de instalación de cliente de actualización DynDNS
  14. Asignación de 1GB de memoria SWAP al servidor

Tener claros los objetivos del deploy

Cuando nosotros vamos a desplegar nuestro sistema en la nube debemos tener claro con qué objetivo lo hacemos, si es un entorno de producción, y para cuantos usuarios, si es solo con objetivo de hacer una demo, o tener nuestro ambiente de testing.

Esto es importante porque en base a esto nosotros determinaremos cuantos recursos necesitamos anexar a nuestro servidor, y eso se verá reflejado en el billing de AWS.  El cual nos cobra poco, pero nos cobra por todo, por lo que debemos tener un control preciso de los recursos que se están destinando, y del tiempo que se tienen encendidos los servidores.

El objetivo de esta guía es generar un deploy sumamente económico que oficiará de ambiente de testing para el sistema que estamos desarrollando.

Configuración de Servidor en AWS

Nosotros en un inicio para tener el deploy del prototipo, generamos una máquina virtual en AWS con 1 vcpu, 1gb de RAM y 8gb de Storage (buscando limitar al máximo el uso de recursos sin que interfiera en el testing).

Entonces en nuestro panel de instancias EC2 nos dirigimos a Lanzar Instancias.

El paso 1 es elegir la imagen de sistema operativo que vamos a utilizar (en AWS las denominan AMI’s).

Interfaz de AWS para configurar instancia a lanzar (Distribución de Linux escogida)

El sistema operativo utilizado fue Linux por su estabilidad, rendimiento y confiabilidad, además de que podemos generar el servidor con menos recursos (por tanto, una máquina más económica), con respecto a Windows Server.

Específicamente elegimos Ubuntu Server en su versión LTS 20.04.

Cuando se habla de servidores Ubuntu siempre es recomendable usar las versiones LTS porque tienen más tiempo de soporte que las comunes.

Las versiones LTS se liberan una vez cada 2 años y tienen hasta 5 años de soporte (cuando hablamos de servidores).

El paso 2 será escoger que nivel de prestaciones deseamos que tenga la máquina virtual.

Interfaz de AWS para configurar instancia a lanzar (Máquina virtual elegida)

La máquina que se utilizó fue una micro de la familia t2, la cual tiene 1 vCPU y 1GB de RAM.

El paso 3 nos sugiere ciertas configuraciones avanzadas que de momento no tocaremos.

El paso 4 nos hace indicarle a AWS el storage que tendrá nuestro servidor, al cual vamos a especificarle 8gb de SSD.

El paso 5 no es relevante en este momento así que continuamos.

Para finalizar en el paso 6, se configuró un Security Group abriendo los siguientes puertos TCP:

  • 22 (SSH).
  • 8080 (Glassfish, puerto de aplicación web HTTP).
Configurando Security Groups de AWS

Al finalizar todas estas configuraciones simplemente lanzamos la máquina virtual.

Descargando archivo PEM con clave privada

Como último paso previo al lanzamiento se nos solicita crear el par de claves para poder acceder a esta máquina por SSH, simplemente le damos un nombre al par de claves y las descargamos (luego configuraremos este archivo en PuTTY).

Panel de instancias EC2 de AWS

Nuestro servidor generado es el “Servidor de prueba”, y atentos al siguiente detalle: su dirección IP actual es 3.133.100.76, la cual es dinámica y cambia cada cierto tiempo (aspecto que debemos corregir luego).

Configurar acceso a la máquina virtual por SSH

Para acceder a nuestro servidor por SSH deberemos usar un cliente SSH en Windows (PuTTY: https://www.putty.org/).

Una vez instalado PuTTY lo abrimos y veremos lo siguiente.

Cliente de SSH (PuTTY)

Ahora debemos tener en cuenta el siguiente detalle: AWS nos brinda una clave privada en formato .PEM, pero PuTTY solo es compatible con archivos de clave en formato .PPK, por lo cual deberemos convertir la clave .PEM en .PPK.

Para esto lo que hay que hacer es abrir la utilidad PuTTYgen.

Utilidad PuTTY key generator

En esta interfaz mediante el botón “Load” cargamos el archivo .PEM, y luego con el botón “Save private key” guardamos esta clave privada en formato .PPK.

Ahora hay que configurar en PuTTY este archivo PPK para que se utilice como clave de acceso por SSH, entonces nos dirigimos a SSH/Auth, y el botón “Browse…”, como vemos en la siguiente imagen.

Cargando clave PPK en PuTTY

Al seleccionar nuestra clave volvemos a Session, y en Host Name ingresamos la ip que vimos en nuestro panel de instancias (en este caso 3.133.100.76), y clickeamos en “open”.

IMPORTANTE: Luego de configurar el servicio DynDNS en nuestro servidor no se utilizará más esa IP y para acceder al servidor por SSH se usará la dirección deploydeprueba.is-a-student.com

Al ingresar nos aparecerá una alerta a la cual le damos que sí, y el usuario por defecto que se utiliza en estas AMI es ubuntu.

Ya estamos dentro de nuestra máquina virtual, en la cual para actuar como root debemos ingresar el comando:

/home/ubuntu$:/sudo -s
Terminal de Ubuntu Server por SSH
Configuración en PuTTY de túneles SSH para acceder como localhost a los puertos de Glassfish

TIP: Por razones de seguridad, en tiempos de desarrollo se recomienda abrir solo el puerto 22, generando un túnel SSH a los puertos utilizados por glassfish para evitar ataques. Por otra parte, el puerto 8080 puede ser abierto puntualmente cuando deseemos realizar una demo del producto.

Implementación de servicios que brindará el servidor

La máquina virtual poseerá un servidor de aplicaciones Glassfish 4.1.1 y dado que el mismo trabaja con IP pública dinámica se implementará un cliente de actualización DynDNS con el dominio deploydeprueba.is-a-student.com, por lo que siempre se podrá acceder al servidor desde ese dominio mientras no se tenga una ip estática.

Procedimiento de instalación de Java JDK y JRE 8

Para instalar el JDK 8 que es el compatible con Glassfish 4.1.1 se ejecutaron los siguientes comandos:

/home/ubuntu$:/apt-get update
/home/ubuntu$:/apt-get install default-jre
/home/ubuntu$:/apt-get install openjdk-8-jre-headless
/home/ubuntu$:/apt-get install openjdk-8-jdk
/home/ubuntu$:/update-alternatives --config java

El último de ellos para escoger el JDK 8 como opción por defecto.

Procedimiento de instalación de Glassfish 4.1.1

Primero que nada, se instalan un par de paquetes que nos permitirán descomprimir archivos zip, luego descargamos el fichero que contiene a Glassfish y lo movemos a un lugar más adecuado en nuestro servidor:

/home/ubuntu$:/wget https://download.oracle.com/glassfish/4.1.1/release/glassfish-4.1.1.zip
/home/ubuntu$:/apt-get install zip unzip
/home/ubuntu$:/unzip glassfish-4.1.1.zip
/home/ubuntu$:/cp -r glassfish4 /opt
/home/ubuntu$:/rm -r glassfish4

Una vez hecho esto se procede a configurar Glassfish, donde se crea un dominio, se activa la propiedad secure-admin que nos permite gestionar el servidor de aplicaciones remotamente, se asigna usuario, password de admin sobre ese dominio creado (“dominioPrueba”) y con esto ya estaría configurado nuestro server de aplicaciones.

/opt$:/glassfish4/bin/asadmin create-domain dominioPrueba
/opt$:/glassfish4/bin/asadmin start-domain dominioPrueba
/opt$:/glassfish4/bin/asadmin --host localhost --port 4848 enable-secure-admin
/opt$:/glassfish4/bin/asadmin stop-domain dominioPrueba
/opt$:/glassfish4/bin/asadmin start-domain dominioPrueba

Luego nos encontramos con el inconveniente de que Glassfish no se ejecutaba automáticamente al bootear el server, ni mucho menos iniciar el dominioPrueba, por lo que generamos un script para poderlo manejar como un servicio del sistema.

/opt$:/nano /etc/init.d/glassfish

Dentro del fichero se incluye el siguiente script, y se pulió un poco en base a nuestras necesidades.

#! /bin/sh    

GLASSFISHPATH=/opt/glassfish4/bin   

case "$1" in  
    start)  
        echo "starting glassfish from $GLASSFISHPATH"  
        sudo $GLASSFISHPATH/asadmin start-domain --debug dominioPrueba  
    ;;  
    restart)  
        $0 stop  
        $0 start  
    ;;  
    stop)  
        echo "stopping glassfish from $GLASSFISHPATH"  
        sudo $GLASSFISHPATH/asadmin stop-domain dominioPrueba  
    ;;  
    *)  
        echo $"usage: $0 {start|stop|restart}"  
        exit 3  
    ;;  
esac

Se le da permisos de ejecución al script guardado.

/opt$:/chmod a+x /etc/init.d/glassfish

Ahora agregamos este script a una utilidad de Ubuntu que se llama CronTab, utilizada para automatizar tareas en el sistema, para esto editamos el fichero que verán a continuación y se agrega la siguiente línea:

/opt$:/nano /etc/crontab

@reboot			root	service glassfish start

Con esto al iniciar el sistema automáticamente se iniciará glassfish levantando el dominio dominioPrueba, entonces queda disponible el servicio.

Despliegue de aplicación web

Para desplegar nuestra aplicación web es necesario tener el proyecto compilado sin errores, con el archivo .WAR en su última versión (el análogo a .JAR en java de escritorio/consola).

Interfaz de administración de servidor de aplicaciones Glassfish 4.1.1

Para esto nos dirigimos a Applications:

Panel de gestión de aplicaciones, servidor de aplicaciones Glassfish 4.1.1

Aquí veremos la lista de aplicaciones que tenemos desplegadas, para hacer deploy de una nueva hacemos clic en el botón “Deploy”.

Interfaz para subir aplicación web con el archivo .WAR, servidor de aplicaciones Glassfish 4.1.1

Aquí debemos escoger el archivo .WAR que está en la carpeta “dist” de nuestro proyecto, seleccionamos Enterprise Application, le damos un nombre y la dejamos habilitada para su uso.

Una vez terminado el proceso salvamos los cambios, y nos queda hacer un último cambio:

Modificar parámetros de la aplicación en producción, servidor de aplicaciones Glassfish 4.1.1

Si nos dirigimos a Applications/DashboardWeb en la propiedad Context Root , podremos escoger el nombre de esta aplicación en particular, que figurará en la URL, quedando la misma de esta forma:

http://deploydeprueba.is-a-student.com:8080/dashboard

Rotación de Logs

Para evitar que el disco duro se nos llene con logs, con el siguiente comando seteamos como máximo en 10 la cantidad de archivos de histórico de logs que se puede tener almacenados:

/opt$:/glassfish4/bin/asadmin set-log-attributes com.sun.enterprise.server.logging.GFFileHandler.maxHistoryFiles=10

Cada archivo puede pesar 2mbytes como máximo según el panel de administración de glassfish (propiedad “File Rotation Limit”).

Interfaz de configuración de mensajes de log en Glassfish 4.1.1

Configuración de servidor de base de datos

Para esta implementación se decidió implementar una instancia de RDS en AWS, separando el servidor de aplicaciones del servidor de base de datos, dejando configurada una conexión entre ambos muy acotada (evitando que otros rangos de ip puedan acceder al RDS por ejemplo).

RDS (Relational Database Service) es un servicio proporcionado por AWS, que se ejecuta en la nube y está diseñado para simplificar la configuración y funcionamiento de bases de datos en su uso con aplicaciones.

Para hacer esto vamos a la consola de administración de AWS, e ingresamos en RDS.

Consola de administración de AWS

En el apartado “Databases” clickeamos en “Create database”.

Dashboard de Amazon RDS

Entonces seleccionamos el motor de base de datos y su versión.

Parámetros de configuración de la nueva instancia que se está creando

Luego nombramos la instancia, y tipeamos el usuario con privilegios de root con su contraseña.

Parámetros de configuración de la nueva instancia que se está creando

También debemos configurar la instancia en términos de Hardware, seleccionando la tercera opción podemos escoger una bastante económica que tiene 2vcpu y 1gb de RAM.

Parámetros de configuración de la nueva instancia que se está creando

El almacenamiento quedará en el mínimo que son 20gb de SSD, y al final nos muestra un poco sobre los costes que nos va a generar esta instancia mensualmente.

Parámetros de configuración de la nueva instancia que se está creando

Una vez creada la instancia de base de datos debemos configurar en el Security Group el conjunto de reglas que nos permitan acceder a la misma de forma segura solo a nosotros.

Para eso nos dirigimos al apartado “databases” nuevamente y seleccionamos la nuestra.

Listado de instancias de RDS

Luego vamos a “Security group rules” y vemos el listado de reglas (seleccionamos el primero).

Configuración de Security Groups del RDS seleccionado
Configuración de Security Groups del RDS seleccionado

Y nuevamente seleccionamos el security group que nos aparece, y hacemos click en “Editar reglas de entrada”.

Configuración de Security Groups del RDS seleccionado

Agregamos una nueva regla de entrada en la que asociamos el launch-wizard-3 que pertenece a nuestra instancia EC2 con el Ubuntu server, esto nos permitirá abrir una conexión entre ambos.

Si también lo deseamos podemos agregar nuestra ip pública para tener un acceso temporal al RDS (solamente nosotros), hasta que dicha ip cambie.

Configuración de acceso desde la máquina virtual EC2 al RDS

La interfaz gráfica del panel de administración de Glassfish es bastante problemática, por lo cual se recomienda configurar todo en el archivo domain.xml ubicado en la ruta “/opt/glassfish4/glassfish/domains/dominioPrueba/config”.

Entonces es que ajustamos la siguiente sintaxis XML con los parámetros de configuración, que deben agregarse dentro del tag “resources”.

<jdbc-resource pool-name="poolPrueba" jndi-name="jdbc/prueba"></jdbc-resource>
    <jdbc-connection-pool max-pool-size="1500" non-transactional-connections="true" datasource-classname="com.mysql.cj.jdbc.MysqlDataSource" name="poolPrueba" res-type="javax.sql.DataSource">
      <property name="password" value="mipassword"></property> 
	  <property name="user" value="root"></property> 
	  <property name="URL" value="jdbc:mysql://alfacomplatform.cx3teiukxfae.us-east-1.rds.amazonaws.com:3306/alfacomPlatform?zeroDateTimeBehavior=CONVERT_TO_NULL&amp;useUnicode=true&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC"></property> 
      <property name="Url" value="jdbc:mysql://alfacomplatform.cx3teiukxfae.us-east-1.rds.amazonaws.com:3306/alfacomPlatform?zeroDateTimeBehavior=CONVERT_TO_NULL&amp;useUnicode=true&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC"></property> 
      <property name="useSSL" value="false"></property>
    </jdbc-connection-pool>

Para que esta configuración funcione también cabe agregar que debemos copiar la librería JAR (conector MySQL) en la ruta “/glassfish/domains/dominioPrueba/lib/ext”.

Carga de scripts en el RDS desde nuestro Ubuntu Server

Una vez que logramos que nuestra máquina EC2 tenga conexión con nuestro RDS, debemos copiar en el /home/ubuntu los scripts de nuestra base de datos por ssh al servidor, luego se ingresa a mysql desde el EC2 como root con el siguiente comando (tener en cuenta que el -h es el endpoint que nos brinda el RDS creado):

/home/ubuntu$:/ mysql -u root -h alfacomplatform.cx3teiukxfae.us-east-1.rds.amazonaws.com -p
mysql>create database dbPrueba;
mysql>exit

/home/ubuntu$:/ mysql -u root -h alfacomplatform.cx3teiukxfae.us-east-1.rds.amazonaws.com -p dbPrueba < script.sql

Optimización de Glassfish para producción

Se deben agregar las siguientes propiedades dentro del tag <java-config>, para optimizar el servidor de aplicaciones como para un entorno de producción.

<jvm-options>-Xms1024m</jvm-options>
<jvm-options>-Xmx1024m</jvm-options>
<jvm-options>-Xss128k</jvm-options>
<jvm-options>-Dcom.sun.grizzly.http.asyncwrite.enabled=true</jvm-options>
<jvm-options>-XX:+DisableExplicitGC-XX:ParallelGCThreads=2</jvm-options>
<jvm-options>-Dcom.sun.grizzly.maxSelectors=500</jvm-options>
<jvm-options>-Dcom.sun.grizzly.readTimeout=86400</jvm-options>

A continuación, enumeraré el significado de cada una:

  1. -Xms1024m
    • Memoria inicial asignada a la máquina virtual de java (en este caso 1024mb).
  2. -Xmx1024m
    • Memoria máxima que se puede asignar.
  3. -Xss128k
    • Establece el máximo de pila para subprocesos Java.
  4. -Dcom.sun.grizzly.http.asyncwrite.enabled=true
    • En caso de tener muchas operaciones de E/S se puede establecer esto en true para que se hagan de forma asíncrona.
  5. -XX:+DisableExplicitGC-XX:ParallelGCThreads=2
    • Establece la cantidad de cores que puede usar la JVM.
  6. -Dcom.sun.grizzly.maxSelectors=500
    • Si ciertas operaciones de escritura toman más tiempo de lo esperado se aumenta el nro de procesadores de escritura mediante esta propiedad.
  7. -Dcom.sun.grizzly.readTimeOut=86400
    • Si fuera usado el Dashboard a través de una red lenta, se puede dar un tiempo de timeout elevado.

Procedimiento de instalación de cliente de actualización DynDNS

Para instalar el cliente de actualización de DynDNS se necesita el siguiente paquete:

/home/ubuntu$:/apt-get install ddclient
/home/ubuntu$:/nano /etc/ddclient.conf

Luego en el fichero /etc/ddclient.conf se incluye la siguiente sintaxis:

protocol=dyndns2
use=web, web=checkip.dyn.com
server=members.dyndns.org
login=//USUARIO//
password=//PASSWORD//
daemon=3600
deploydeprueba.is-a-student.com

checkip.dyn.com es un sitio proporcionado por DynDNS para averiguar la IP pública de la máquina.

Luego debemos agregar la siguiente línea en CronTab para que este servicio se inicie al bootear (y al estar en funcionamiento por la propiedad Daemon=3600 se estará actualizando la IP una vez por hora).

/home/ubuntu$:/nano /etc/crontab

@reboot         root /usr/sbin/ddclient --force

Asignación de 1GB de memoria SWAP al servidor

Si fuera necesario tener más memoria RAM, se puede asignar memoria de intercambio (SWAP), tomando una parte de nuestro Storage como RAM.

Para asignar memoria SWAP es necesario crear un fichero, darle permisos y un formato para que el mismo pueda funcionar como memoria, lo cual se hizo en los siguientes comandos:

/home/ubuntu$:/fallocate -l 1G swapfile
/home/ubuntu$:/chmod 600 swapfile
/home/ubuntu$:/mkswap swapfile
/home/ubuntu$:/swapon swapfile

Para que la memoria SWAP funcione al bootear el servidor, se agrega una línea en el /etc/fstab.

/home/ubuntu$:/nano /etc/fstab
#Agregar la linea:
	/home/ubuntu/swapfile swap swap defaults 0 0

Nosotros también podemos elegir a partir de cuanto porcentaje de RAM en uso queremos que se active la SWAP, agregando una línea en el /etc/sysctl.conf (en este caso 85%).

/home/ubuntu$:/nano /etc/sysctl.conf
#Agregar la linea:
	vm.swappinness = 85
Ejecución del comando free -h luego de implementar 1gb de SWAP en el servidor

De esta forma ya tendríamos funcional nuestro primer deploy en AWS con Glassfish y MySQL, optimizado para presentarse como un buen entorno de pruebas para demos y testing durante el desarrollo.

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *