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
- Tener claros los objetivos del deploy
- Configuración de Servidor en AWS
- Configurar acceso a la máquina virtual por SSH
- Implementación de servicios que brindará el servidor
- Procedimiento de instalación Java JDK y JRE 8
- Procedimiento de instalación de Glassfish 4.1.1
- Despliegue de aplicación web
- Rotación de Logs
- Configuración de servidor de bases de datos
- Configuración de acceso desde la máquina virtual EC2 al RDS
- Carga de scripts en el RDS desde nuestro Ubuntu Server
- Optimización de glassfish para producción
- Procedimiento de instalación de cliente de actualización DynDNS
- 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).

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.

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).

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

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).

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.

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.

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.

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


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).

Para esto nos dirigimos a Applications:

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

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:

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”).

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.

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

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

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

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.

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.

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.

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


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

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&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC"></property>
<property name="Url" value="jdbc:mysql://alfacomplatform.cx3teiukxfae.us-east-1.rds.amazonaws.com:3306/alfacomPlatform?zeroDateTimeBehavior=CONVERT_TO_NULL&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&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:
- -Xms1024m
- Memoria inicial asignada a la máquina virtual de java (en este caso 1024mb).
- -Xmx1024m
- Memoria máxima que se puede asignar.
- -Xss128k
- Establece el máximo de pila para subprocesos Java.
- -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.
- -XX:+DisableExplicitGC-XX:ParallelGCThreads=2
- Establece la cantidad de cores que puede usar la JVM.
- -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.
- -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

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.