Publi

Cómo configurar auto escalado asociado al balanceador de carga de Amazon Web Services

photo-1453686062273-6257b9fde1ce

Como hemos visto en anteriores posts, cuando una aplicación crece debemos hacer que el rendimiento sea aceptable, tolerar errores y que no nos salga muy caro. También, hace unos días vimos cómo configurar el balanceo de carga de nuestros servicios en Amazon Web Services.
Amazon, dentro de sus servicios, nos proporciona una forma fácil y amigable de ahorrar costes, al mismo tiempo que mantenemos nuestros servicios online y con el mejor rendimiento posible. Lo lograremos haciendo uso del auto escalado. Es decir, en tiempo real, se contratarán máquinas y comenzarán a servir nuestra aplicación desde nuestro balanceador de carga. La gracia es que la contratación de estas máquinas se realizará en función de los parámetros de uso, como puede ser que la carga de las instancias que hay actualmente supere cierto umbral, y cuando la carga de las máquinas baje de cierto punto, dichas instancias se devolverán y ya no supondrán más coste para nosotros. Con este sistema no tendremos que pagar por máquinas que no estemos utilizando en un momento determinado, al mismo tiempo que nadie tiene que estar pendiente de conectar o desconectar máquinas en el sistema, todo funcionará automáticamente.

Extrayendo la imagen a utilizar

Todas las instancias que se lancen con el autoescalado serán iguales. Todas tendrán el mismo sistema operativo, los mismos programas, tareas, etc. Serán exactamente iguales. Esto es bueno porque sólo hay que configurar una máquina para que todas estén funcionando de igual manera. Es posible que la aplicación web que corres con este sistema se actualice a mayor ritmo del que puedes actualizar tus imágenes. Es decir, las imágenes deberán ser actualizadas con el tiempo para incluir los últimos parches del sistema operativo, software de servidor (Apache, PHP, etc) y configuraciones (políticas de iptables, optimizaciones de memoria, etc), pero tu aplicación web tal vez evolucione mucho más rápido, puedes tener decenas de actualizaciones diarias y no es plan de crear una imagen cada vez que haya una actualización. En estos casos, antes de arrancar la máquina puedes hacer un git pull origin master nada más arrancar para que todo esté al día antes de empezar a servir.

Una vez tengamos preparada una instancia nueva con todo configurado y listo para ser nuestra instancia modelo, debemos crear una imagen de la misma, para ello, en el panel de EC2 hacemos click con el derecho en la instancia, vamos a Image y luego Create Image:
instancia_image. Con esto, vamos a crear una AMI a partir de la instancia que hemos seleccionado. Nos presentará algo como esto, le damos nombre, descripción y aceptamos:
Screenshot 04-11-2016-111137

Configurando el envío de mensajes

Cada vez que se superan umbrales de CPU o transferencia, cada vez que se lanza una máquina o se desactiva otra, Amazon nos puede enviar notificaciones de estos estados por diferentes vías. Ya que Amazon lo tiene todo bien atado estas notificaciones se enviarán a través de SNS (Simple Notification Service, del que comentamos algo hace tiempo). El objetivo para nosotros será estar al tanto en todo momento de qué pasa con nuestros servidores.

Por lo que configuraremos rápidamente SNS, yendo a su panel de control y luego Create topic:
Screenshot 04-11-2016-121145
Estableceremos un nombre para nuestro tema de mensajería y un display name (un nombre algo más bonito y visual, aunque por rarezas de la vida debe ser muy corto también):Screenshot 04-11-2016-121128.
Por último definimos el protocolo (en este caso, para probar, el e-mail) y en EndPoint ponemos nuestra dirección de correo. Cuando queramos hacer algo más serio podemos utilizar el protocolo HTTP o HTTPS para mandar el mensaje directamente a un servidor web (o un servidor de control dentro de nuestra red):
Screenshot 04-11-2016-121141_2

Configurando el auto-escalado

Ahora, dentro de nuestro panel de EC2, nos vamos a Auto Scaling, Launch Configurations y creamos una nueva configuración. Nos preguntará por la AMI a utilizar (la imagen que hemos creado de la instancia anterior):
Screenshot 04-11-2016-111107.
Tras ello, configuramos nuestra configuración de lanzamiento, le damos nombre (en la captura de pantalla el nombre tiene un espacio, no es muy recomendable, a veces da problemas; establecemos opciones de compra (Las Spot Instances nos pueden salir más baratas, pero puede que no haya disponibles o que las perdamos. Finalmente en el tipo de dirección IP, para este caso no es necesario que tenga una IP pública asignada, normalmente no vamos a entrar a esas máquinas desde Internet y no queremos que nadie entre a ellas directamente:
Screenshot 04-11-2016-111120

Continuamos estableciendo los volúmenes (nos facturarán por esto, por lo que debemos tener cuidado eligiendo. Aunque elegir algo muy pequeño puede que nos deje sin espacio en el transcurso del servicio, nos deje tirados y nos terminen cobrando más por tener que lanzar más máquinas de forma innecesria).
Screenshot 04-11-2016-111140.

Es momento de configurar el grupo de seguridad. No tenemos por qué aceptar SSH si no queremos:
Screenshot 04-11-2016-111138.

Ahora, crearemos el grupo de auto escalado, para ello debemos dar un tamaño (número de máquinas inicial del grupo), VPC, subred y. como lo creamos para ser utilizado con un balanceador de carga, configuramos el balanceador que estamos utilizando (testinglb), el tiempo que se esperará antes de empezar la monitorización de salud y la protección. Protect From Scale In, evitará que se desconected las máquinas cuando dejan de ser utilizadas, normalmente no lo activaremos porque en caso de servidores web independientes, estos podrán desactivarse y no será necesario saber nada de ellos pero, en ocasiones, puede que en ciertas configuraciones estas máquinas tengan que realizar tareas importantes que no deben ser interrumpidas y su desconexión puede causar un desastre.
Screenshot 04-11-2016-111123

Creación de alarmas y políticas de auto escalado

Lo siguiente será crear políticas de auto escalado, por lo que definimos el número mínimo y máximo de máquinas que tendremos dentro del grupo y estableceremos las políticas que seguiremos para incrementar este número o decrementarlo. Este no es el número de máquinas dentro de nuestro balanceador, podemos tener tanto máquinas predefinidas introducidas a mano como grupos de autoescalado que funcionarán por sí solos. Lo comento por si alguna máquina dentro del balanceador va a destinarse a hacer tareas más duras, o no debe ser retirada bajo ningún concepto o debe tener una configuración ligeramente diferente:
Screenshot 04-11-2016-121115.
Dentro de las políticas de incremento de máquinas, tendremos que establecer una política de monitorización que debe cumplirse para añadir una o más máquinas:
Screenshot 04-11-2016-121126_2.
En mi caso, lanzaré más máquinas cuando iguale el 83% de uso de CPU de media en las máquinas del grupo de auto escalado al menos durante 5 minutos. Como siempre, esto depende de la carga de CPU que introduzca nuestra aplicación, debemos probar el valor óptimo para que el servicio no pierda calidad.
Luego definiremos el tiempo que esperaremos antes de empezar otro escalado. Nuestra máquina tendrá que arrancar, actualizar sus repositorios, identificarse a otros servicios que tengamos conectados y empezar a servir. Normalmente el arranque incrementará el uso de CPU, pero cuando esta máquina sea tenida en cuenta en el balanceador la carga global de nuestro sistema empezará a bajar (se supone), por lo que si tardamos unos 30 segundos en arrancar y otros 30 segundos en ponernos al día, 120 segundos es un buen valor, aunque podemos subirlo un poco más. Pero como siempre, depende de nuestra aplicación.

Haremos lo mismo con las políticas para que esas máquinas sean destruidas:
Screenshot 04-11-2016-121127.

Por último definiremos la política de notificaciones de Amazon (con la que nos enviará notificaciones acerca de las instancias):
Screenshot 04-11-2016-121116_2.

Ya lo tenemos

¡Ya tenemos todo montado y funcionando! En unos segundos, el número de instancias iniciales especificado será lanzado y empezarán a trabajar dentro del balanceador. ahora bien, ¿cómo vemos que está funcionando todo bien? Para eso dejé el SSH funcionando antes. Dentro del mismo VPC inicio una instancia que conecte con la IP de una de las máquinas que se acaba de lanzar y le pido que calcule por ejemplo dígitos del número pi en python:

1
2
3
4
5
6
7
8
#!/bin/bash
while (( 1 )); do echo "from decimal import Decimal, getcontext
getcontext().prec=10000
print sum(1/Decimal(16)**k *
          (Decimal(4)/(8*k+1) -
           Decimal(2)/(8*k+4) -
           Decimal(1)/(8*k+5) -
           Decimal(1)/(8*k+6)) for k in range(100))"
| python ; uptime; done

Con esto, pronto la CPU de las máquinas subirá y en unos minutos podremos ver que las máquinas empiezan a crearse y, por desgracia, a facturarse.

Ideas para tenerlo todo bien atado

Es importante que personalicemos los scripts de arranque y apagado de la máquina para que esta no sea accesible por el balanceador de carga demasiado pronto. Si tenemos que copiar nuestros datos con git, debemos esperar a que éste termine y si tenemos que hacer conexiones con otras máquinas, debemos establecerlas antes de nada.

Lo mismo antes de que se desconecten las máquinas, debemos sincronizar logs, hacer verificaciones y desconexiones antes de apagar la máquina del todo.

Problemas de conectividad

Tal vez cuando accedáis a instancias internas no tengáis conexión a Internet. Se podrá acceder a ellas, gracias al Internet Gateway, pero éstas no tendrán conexión a Internet. Esta conectividad se puede utilizar creando una NAT Gateway.Para conectar a Internet se necesita una IP pública y dado que no tenemos IP pública necesitamos una forma de conseguirla, así igual que todos los dispositivos de casa (ordenadores, tablets, móviles conectan a Internet a través de nuestro router doméstico (que gracias a nuestro proveedor de Internet tendrá una IP pública), aquí debemos hacer lo mismo, asignar un router.
Puede ser un poco engorroso, pero debemos tener una subred que tenga conexión a este NAT.
Este router puede ser una NAT Gateway (que por supuesto Amazon nos cobrará aparte), o puede ser una instancia de nuestro sistema que sí tenga una IP hacia el exterior, y como tiene una IP puede hacer de puerta de enlace. Esto es, que todas las instancias que quieran tener conexión a Internet deberán pasar por mi instancia puerta de enlace para que ésta las conecte a Internet.

Una pequeña aproximación a una instancia NAT sería utilizar IP Forwarding:

sudo echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo iptables -t nat -A POSTROUTING -o eth0 -s 0.0.0.0/0 -j MASQUERADE

Aunque podéis coger ideas para esto en este post, con el fin de que podamos seleccionar a qué instancias damos permiso a conectarse.

Añadir o quitar áquinas del balanceador desde consola

Algo que también nos puede resultar útil es el hecho de iniciar una instancia EC2 desde la consola de AMAZON y añadirla al balanceador a mano. Esto puede ser útil cuando antes de entrar en el balanceador necesitemos ejecutar ciertas tareas de mantenimiento o incluso podemos utilizar estos comandos a mano para hacer un diagnóstico avanzado de una máquina individual.

ec2start --region YOUR_REGION INSTANCE_ID
aws elb deregister-instances-from-load-balancer --region YOUR_REGION --load-balancer-name YOUR_LOADBALANCER --instances INSTANCE_ID
aws elb register-instances-with-load-balancer --region YOUR_REGION  --load-balancer-name YOUR_LOADBALANCER --instances INSTANCE_ID

Visto aquí.

Y tu, ¿utilizas el auto escalado de Amazon?

¿Qué te parece la idea? Deja tu comentario más abajo.

Foto principal: Calum MacAulay

También podría interesarte...

Leave a Reply