Banner_Etool

AWS: Escalar detrás de un ELB x Métricas de CPU/Memoria

Por: Emilio Torrens  /  En: , ,

.

auto-scaling-aws-374x258

Para escalar instancias detrás de un balanceador lo mas natural, por lo menos en nuestro caso, seria auto escalar instancias por la media de utilización de CPU o Memoria de las instancias que hay detrás de un Balanceador.

Eso en AWS no se puede hacer ya que no te dan esa métrica, puedes escalar por las métricas de una de las instancias, cosa que no me parece optima ni recomendable ya que ese server podría estar sirviendo un request pesado y los demás estar sin hacer nada, o escalar por las métricas propias del ELB, latencia, numero de requests etc .. pero para nosotros cuando saltan esas alarma ya es tarde.

La solución, crear una métrica personalizada que mande la media de utilización de CPU/Memoria de las instancias que hay detrás del balanceador y escalar por esa métrica.

Aquí dejo un script de Python para poder tener esas métricas, tiene dos modos:

1- Si no le pasas parámetros busca todos los balanceadores de una cuenta de AWS y manda métricas personalizadas para tener la media de uso de CPU y Memoria de las instancias que tiene detrás.

2- Para que te haga la métrica de un grupo de servidores aunque no estén en un balanceador le has de pasar el nombre de la métrica y los ids de los servidores separados por ; (Ejemplo: python aws-elb-metrics.py ELASTICSEARCH-CLUSTER i-73f85435430;i-88cc6sdasd4cb;i-99c06dasd8da;i-7addd0239)

Ojo que las métricas de memoria no aparecen en AWS, hay que instalar unos scripts en los servidores para que se manden aquí dejo los enlaces por si lo queréis instalar Amazon CloudWatch Monitoring Scripts for WindowsAmazon CloudWatch Monitoring Scripts for Linux

__author__ = 'emilio.torrens'
 
access_key = 'TU_KEY
access_secret = 'TU_SECRET'
 
import sys
import datetime
from time import sleep
import threading
import boto.ec2.elb
import boto.ec2.cloudwatch
 
c = boto.ec2.cloudwatch.connect_to_region('eu-west-1', aws_access_key_id=access_key, aws_secret_access_key=access_secret)
elb = boto.ec2.elb.connect_to_region('eu-west-1', aws_access_key_id=access_key, aws_secret_access_key=access_secret)
 
 
def put_metric_cpu_from_instances(name, instance_ids):
    print name
    total_avg = 0
    metric_count = 0
    max_datetime = datetime.datetime.utcnow() - datetime.timedelta(hours=600)
    for instance_id in instance_ids:
        metrics = c.get_metric_statistics(
            300,
            datetime.datetime.utcnow() - datetime.timedelta(seconds=600),
            datetime.datetime.utcnow(),
            'CPUUtilization',
            'AWS/EC2',
            'Average',
            dimensions={'InstanceId': [instance_id]}
        )
 
        if len(metrics) != 0:
            m = max(metrics, key=lambda x: x['Timestamp'])
            if m['Timestamp'] > max_datetime:
                max_datetime = m['Timestamp']
 
            #print str(instance_id) + " : " + str(m)
            avg = float(m['Average'])
            total_avg += avg
            metric_count += 1
 
    if metric_count != 0:
        print 'Sending CPUUtilization data - DateTime: ' + str(max_datetime) + " Value: " + str(total_avg / metric_count)
        result = c.put_metric_data('e-tooltech', name + '-CPUUtilization', value=total_avg / metric_count,
                                   timestamp=max_datetime)
        print 'Result: ' + str(result)
 
 
def put_metric_memory_from_instances(name, instance_ids):
    print name
    total_avg = 0
    metric_count = 0
    max_datetime = datetime.datetime.utcnow() - datetime.timedelta(hours=600)
    for instance_id in instance_ids:
        # print instance.id
        metrics = c.get_metric_statistics(
            300,
            datetime.datetime.utcnow() - datetime.timedelta(seconds=600),
            datetime.datetime.utcnow(),
            'MemoryUtilization',
            'System/Windows',
            'Average',
            dimensions={'InstanceId': [instance_id]}
        )
 
        metrics += c.get_metric_statistics(
            300,
            datetime.datetime.utcnow() - datetime.timedelta(seconds=600),
            datetime.datetime.utcnow(),
            'MemoryUtilization',
            'System/Linux',
            'Average',
            dimensions={'InstanceId': [instance_id]}
        )
 
        if len(metrics) != 0:
            m = max(metrics, key=lambda x: x['Timestamp'])
            if m['Timestamp'] > max_datetime:
                max_datetime = m['Timestamp']
 
            #print str(instance_id) + " : " + str(m)
            avg = float(m['Average'])
            total_avg += avg
            metric_count += 1
 
    if metric_count != 0:
        print 'Sending MemoryUtilization data - DateTime: ' + str(max_datetime) + " Value: " + str(total_avg / metric_count)
        result = c.put_metric_data('e-tooltech', name + '-MemoryUtilization', value=total_avg / metric_count,
                                   timestamp=max_datetime)
        print 'Result: ' + str(result)
 
while True:
 
    try:
 
        if len(sys.argv) == 1:
 
            for lb in elb.get_all_load_balancers():
                ids = []
                for instance in lb.instances:
                    ids.append(instance.id)
 
                t2 = threading.Thread(target=put_metric_memory_from_instances(lb.name, ids))
                t2.start()
                t3 = threading.Thread(target=put_metric_cpu_from_instances(lb.name, ids))
                t3.start()
 
                t2.join()
                t3.join()
 
        else:
 
            metric_name = sys.argv[1]
            ids = sys.argv[2].split(';')
 
            put_metric_cpu_from_instances(metric_name, ids)
            put_metric_memory_from_instances(metric_name, ids)
 
        print 'Sleep for 60 seconds'
        sleep(60)
 
    except Exception, e:
        print str(e)

Padel, III Prueba Ruta Solidaria Trofeo BP

Por: Emilio Torrens  /  En: ,

Cincopa WordPress plugin

Deploy de aplicaciones Mono: de Windows a Linux

Por: Emilio Torrens  /  En: , , , , ,

.

Después de postear como instalar la ultima versión de Mono y como configurar tus aplicaciones con Apache quedaba el tema de automatizar los Deploys, asi que aqui esta.

En realidad es bastante sencillo ya que con algunos ejecutables de Putty podemos hacernos un bat para automatiza el deploy en los servidores Linux.

Necesitaremos el scp.exe y el plink.exe, ambos podéis descargarlos desde aquí

En el siguiente ejemplo haremos deploy de nuestra aplicación a un servidor Ubuntu en Amazon por lo que necesitaremos la key de los servidores en formato para Putty, puedes ver como convertirla aquí.

Este ejemplo lo saco desde nuestro bamboo que ya ha compilado y publicado la aplicación a un directorio, si lo vas a hacer como un bat solitario deberías incluir antes este comando para publicar tu aplicación a un directorio:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe
  -v
  /MyWebApp
  -p
  "C:\build-dir\production\My.Web.App"
  -f
  "C:\build-dir\production\Published"

Además después de publicar bamboo reinicia la aplicación Mono,  recarga el Apache o hace un touch de Web.config, luego tu ya metes los comandos que quieras al final del deploy.

El script asume que tienes un fichero “Web.config.production” en el que tienes la configuración de producción.

El script va guardando las versiones que subes y lo que hace es modificar un link que apunta a la ultima versión, algo parecido a lo que hace el Capistrano, de esta manera es fácil tirar para atrás un deploy.

Bueno creo que el script se auto-describe asi que aqui lo dejo:

@echo off
For /f "tokens=1-4 delims=/ " %%a in ('date /t') do (set mydate=%%c%%b%%a)
For /f "tokens=1-2 delims=/:" %%a in ('time /t') do (set mytime=%%a%%b)
set remotefolder=%mydate%%mytime%
 
echo creating remote release folder %remotefolder%
 
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "sudo mkdir -p /var/www/my_app/releases"
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "mkdir  -p /home/ubuntu/my_app/%remotefolder%"
 
echo Uploading files...
 
C:\pscp\scp.exe -i C:\git\key_amazon\my_aws_key_putty.ppk -C -r "C:\build-dir\production\Published\Published\*" ubuntu@10.0.1.69:/home/ubuntu/my_app/%remotefolder%
 
echo Files Uploaded. Moving Files
 
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "sudo mv /home/ubuntu/my_app/%remotefolder% /var/www/my_app/releases/%remotefolder%"
 
echo Remaking current simbolic link.
 
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "sudo rm /var/www/my_app/current"
 
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "sudo ln -s /var/www/my_app/releases/%remotefolder%/ /var/www/my_app/current"
 
echo Updating Web.config.
 
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "sudo rm /var/www/my_app/current/Web.config"
 
c:\pscp\plink.exe -i C:\git\key_amazon\my_aws_key_putty.ppk ubuntu@10.0.1.69 "sudo mv /var/www/my_app/current/Web.config.production /var/www/my_app/current/Web.config"
 
echo Deploy Done :)

Configura tu aplicación web mono en apache

Por: Emilio Torrens  /  En: , , , ,

.

mono_apache1Si has instalado el Mono con el script que publique ya tienes todo configurado y solo hay que añadir el VirtualHost en el http.conf del apache, si no, instalatelo con el script o pegale un vistazo para ver lo que te puede faltar.

A partir de aquí asumimos que tenemos mono, xsp, mod_mono instalado y apache configurado.

La publicación de la aplicación es igual que si fueras a hacer deploy en un IIS, haces un publish desde el “visual studio” o copias los ficheros después de compilar, los subes al servidor y listo.

En este ejemplo tenemos un subdominio “myapp.myserver.com” en el que publicaremos 2 aplicaciones una en /pro y la otra en /develop, que ejecutaremos en modo Debug.

La ruta de los archivos en el ejemplo es:

pro : /var/www/myapp/current

develop: /var/www/myapp-develop/current

Además creamos un sitio /mono donde tendremos una consola para reiniciar las aplicaciones ver numero de peticiones, peticiones en marcha, en cola etc.

En este ejemplo el acceso a /mono esta restringido solo accesible desde la red local 10.* y desde la propia maquina 127.0.0.1

Y este es el VirtualHost que configuraríamos en el http.conf del apache para correr estas dos aplicaciones:

<VirtualHost *:80>
  ServerName myapp.myserver.com
  ServerAdmin web-admin@myserver.com
 
  Alias /pro "/var/www/myapp/current"
  Alias /develop "/var/www/myapp-develop/current"   
 
  MonoServerPath pro "/usr/bin/mod-mono-server4"
  MonoServerPath develop "/usr/bin/mod-mono-server4"  
 
  MonoDebug pro, false  
  MonoDebug develop, true
 
  MonoSetEnv pro MONO_IOMAP=all;MONO_STRICT_MS_COMPLIANT=yes
  MonoSetEnv develop MONO_IOMAP=all;MONO_STRICT_MS_COMPLIANT=yes  
 
  MonoApplications pro "/pro:/var/www/myapp/current"
  MonoApplications develop "/develop:/var/www/myapp-develop/current"
 
  <Location "/pro">
    Allow from all
    Order allow,deny
    MonoSetServerAlias pro
    SetHandler mono
    SetOutputFilter DEFLATE
    SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
  </Location>
  <Location "/develop">
    Allow from all
    Order allow,deny
    MonoSetServerAlias develop
    SetHandler mono
    SetOutputFilter DEFLATE
    SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
  </Location>  
  <Location "/mono">
    SetHandler mono-ctrl
    Order deny,allow
    Deny from all
    Allow from 10 127.0.0.1
  </Location>
  <IfModule mod_deflate.c>
     AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
  </IfModule>
 
</VirtualHost>

Certificados SSL en ELB de Amazon EC2

Por: Emilio Torrens  /  En: , , ,

awsLa mejor manera, y la que lleva menos mantenimiento, de usar conexiones HTTPS en AWS es instalar los certificados en el balanceador, de esta manera puedes redirigir en el balanceador las peticiones desde HTTPS a HTTP y no tienes que tener configurados los certificados en cada maquina.

Aquí dejo un pequeño tutorial para instalar certificados SSL en los Balanceadores de Amazon.

Lo primero tienes que tener los archivos del certificado, algo como:

mysite.key, mysite.crt, mysite.gd_bundle.crt

Tienes que convertir estos ficheros al formato pem, eso lo puedes hacer con el openssl, desde un linux o desde una consola de git en Windows, con estos comandos:

$ openssl rsa -in mysite.key -outform PEM -out mysite.key.pem
$ openssl x509 -inform PEM -in mysite.crt -out mysite.crt.pem
$ openssl x509 -inform PEM -in mysite.gd_bundle.crt -out mysite.bundle.crt.pem

Una vez los tienes en el formato pem hay que subirlos a amazon:

  • Vas a EC2/Load Balancers, seleccionas el Balanceador.
  • Creas un nuevo listener desde el HTTPS del ELB al HTTP de las instancias.
  • En SSL Certificate seleccionas Change y Upload a new SSL Certificate
    • Name: El nombre que quieras
    • Private Key: El contenido de mysite.key.pem
    • Public Key Certificate: El contenido de mysite.crt.pem
    • Certificate Chain: El contenido de mysite.bundle.crt.pem

Guardas y listo, ya lo tienes configurado.