26 dic

HaProxy con Consul-Template y zero downtime reload

¿Por qué HaProxy con Consul-template?

HaProxy con Consul-template en Docker

HaProxy con Consul-template en Docker

Llevamos un tiempo trabajando en Docker con el dinamismo que ello nos supone, HaProxy con Consul-template nos ofrece una solucion muy similar a marathon-lb, el cual habíamos hablado en como usar marathon-lb para conectar nuestras aplicaciones dentro del cluster de Apache Mesos.

Marahon-lb es una maravilla, pero no dispone de algunas características que nos hacen falta, así que pensamos, bueno pues nos lo montamos nosotros.

Idea principal

La idea principal es utilizar la información que tenemos de nuestros servicios registrados en Consul, para poder generar la configuración de HaProxy con Consul-template. Fácil.

Lo haremos en docker así lo podremos lanzar en la plataforma de Apache Mesos, y claro esta si queremos que HaProxy tenga una configuración dinámica deberemos implementar el zero downtime reload

¿Qué es el Zero downtime reload HaProxy?

Cada vez que tengamos un cambio de configuración en HaProxy deberemos hacer una recarga del servicio, en el caso que tengamos conexiones establecidas esta recarga nos llevara a perderlas y claro, eso no es para nada deseable, ¿cómo solventamos este problema?

Pues seguiremos las indicaciones de Willy Tarreau CTO de HAPROXY,  lo que nos comenta es que podemos implementar una solución para descartar los paquetes SYN durante el reinicio de HaProxy, y aprovecharnos del funcionamiento de TCP para que se recupere automáticamente, añadiremos la solución en la imagen.

A esta solución hay una vuelta de tuerca mas, que lo explican maravillosamente bien la gente de Yelp, True Zero Downtime HAProxy Reloads.

Creación de los Dockers

Vamos a crear dos imágenes de Docker, por un lado la imagen con Consul-Templat y por otro la imagen de HaProxy que heredara de la primera imagen.

Toda la explicación y los ficheros necesarios están en mi github y la imagen de haproxy la podeis bajar de https://hub.docker.com/r/maauso/docker-consul-template/

Consul-template

Una de las partes mas importantes es entender el Consul-template que utilizaremos para HaProxy, gracias a Raul Fiestas por la creación del mismo :), podéis pasaros por su github, que tiene cosas muy interesantes https://github.com/rfiestas o su tumblr http://sudevops.tumblr.com/

La idea no es hacer una clase de consul-template, pero lo importante es saber las opciones que podemos usar, explicadas a continuación y que también podéis encontrar en https://github.com/maauso/docker-haproxy

¿Qué necesitamos para añadir un nuevo servicio a nuestro HaProxy?

Toda la información del servicio deberá estar en Consul, haremos un ejemplo con el servicio “www”

SERVICE_NAME=www

Este será en nombre de nuestro backend y frontend en la configuración de HaProxy, también será la url de acceso, que se concatenará al valor de HAPROXY_DOM, www.maauso.com

frontend app_http_in
  bind *:8080
  mode http
  acl host_www.maauso.com hdr(host) -i www.maauso.com
  use_backend www.maauso.com if host_www.maauso.com

Deberemos usuar Consul Tags, para decidir que servicios de Consul queremos añadir a nuestro HaProxy

HAPROXY.ENABLE=true

Y tendremos otras opciones del backend usando tags.

HAPROXY.PROTOCOL=http
HAPROXY.BACKEND.BALANCE=roundrobin
HAPROXY.BACKEND.MAXCONN=10000
backend www.maauso.com
  balance roundrobin
  mode http
  option forwardfor
  option tcp-check
  default-server inter 10s fall 1
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }
Opciones de configuración para HaProxy 

Variables Globales que podemos modificar

HAPROXY_MAXCONN_GLOBAL=50000
HAPROXY_SPREAD_CHECKS=5
HAPROXY_MAX_SPREAD_CHECKS=15000
HAPROXY_SPREAD-CHECKS=5

Variables que no tienen valor por defecto

HAPROXY_DOM=maauso.com

Variables por defecto que podemos cambiar

HAPROXY_RETRIES=3
HAPROXY_BACKLOG=10000
HAPROXY_MAXCONN=10000
HAPROXY_TIMEOUT_CONNECT=3s
HAPROXY_TIMEOUT_CLIENT=30s
HAPROXY_TIMEOUT_SERVER=30s
HAPROXY_TIMEOUT_HTTP_KEEP_ALIVE=1s
HAPROXY_TIMEOUT_HTTP_REQUEST=15s
HAPROXY_TIMEOUT_QUEUE=30s
Por último zero downtime reload. 

Para conseguir el zero downtime reload consul-template enviará un SIGHUB al proceso que maneja a HaProxy, este proceso recibirá la señal con un trap y realizará el DROP de los paquetes SYN con iptables.

Acto seguido creara un nuevo proceso de HaProxy con la opción -sf $LATEST_HAPROXY_PID y eliminara la regla de iptables

 

28 jun

¿Cómo usar Marathon-lb en Apache Mesos?

marathon-lb

Voy a explicar como trabajar con Marathon-lb (sustituto de marathon-haproxy-bridge) para Apache Mesos, hay parte teórica y parte práctica :),  hace un tiempo expliqué qué era Apache-Mesos y cómo empezar a trabajar con uno de su Frameworks llamado Marathon, también comentamos como utilizar marathon-haproxy-bridge para balancear peticiones de los Dockers que tengamos esparcidos por todo el cluster.

Antes de empezar nos debemos poner un poco en contexto, os recomiendo que leáis las entradas anteriores, para entender el ecosistema.

Parte teórica 

¿Qué es marathon-lb?

Marathon-lb es una solución que nos da la gente de Mesosphere para poder balancear de forma sencilla los servicios que tenemos en nuestro cluster de Apache Mesos, como sabemos por norma general cuando vamos desplegando Dockers en Apache Mesos estos empezaran a correr en slaves de Mesos aleatorios y en puertos aleatorios, esta dinámica hace complicado que podamos en trabajar con esos Dockers a no se que tengamos algún punto de entrada. Eso exactamente es lo que nos da marathon-lb.

¿Qué nos ofrece?

  1. Integración directa con Marathon, dependencia únicamente del Framework de Marathon
  2. Punto de entrada a los Dockers que tengamos corriendo en Apache Mesos
  3. Escalabilidad horizontal
  4. Actualizaciones de configuracion en tiempo real, conectando marathon-lb a Martahon usando SSE
  5. HealthChecks, tanto del propio HAProxy como a través de  Marathon
  6. TLS/SSL
  7. HaProxy Templates (la configuracion de HAProxy se realiza a través de labels de Docker, sublime)
  8. Imagen Docker para correrlo en Apache Mesos

¿Cómo funciona?

El funcionamiento en si es de lo más sencillo, marathon-lb “solo” es un script hecho en python que una vez conectado a Marathon  a través de SSE, y va actualizando la configuración del HAProxy que lleva en su interior, por cada aplicación que lancemos en Apache Mesos marathon-lb hará la asociación entre el punto de entrada que le hayamos dicho y el los Dockers con sus respectivos puertos.

La asociación entre HAProxy y los Dockers lo podemos hacer por dos métodos, puerto o usando un virtual host.

En el caso de querer una asociación por puerto, o sea que la url de acceso sea del tipo lo


http://marathon-lb.company.com:10001

Deberemos lanzar el Docker definiendo un puerto de servicio que será utilizado por marathon-lb como puerta de entrada, en este caso el 10001

Otro caso de uso es la asociación por virtual host, en este caso la url de entrada podría ser algo como.


http://miservicio.company.com

Para usar esta opción deberemos lanzar el Docker con la label

HAPROXY_{n}_VHOST

Por ejemplo

HAPROXY_VHOST = "http://miservicio.company.com" 

Antes de pasar a la parte practica decir que

Parte práctica

Objetivos

  • Tener un único punto de entrada que nos de acceso a todos los Dockers de un servicio que estén corriendo en nuestro Apache Mesos, en este ejemplo será un Nginx

Características de práctica

  1. Utilizaremos el acceso por Virtual Host
  2. Conectaremos marathon-lb a Marathon usando SSE
  3. Lanzaremos el docker de marathon-lb en modo Host.

¿Como lanzamos marathon-lb en Apache Mesos ?

Como es lógico primero de todo deberemos montar el JSON para poder lanzar marathon-lb en nuestro Apache Mesos a través del Framework Marathon, el JSON tiene una pinta tal que así y explicamos cada punto más abajo

Campos:

“cmd” :

  •  /marathon-lb/run sse : Ejecucion de marathon-lb en modo sse
  • –marathon: Url de nuestro Marathon
  • –group : Con esta opcion estamos diciendo cuales son los dockers que queremos que se usen a través de marathon-lb, en nuestro caso aquello que lleven HAPROXY_0_GROUP: “qa“.
  • –health-check:  Con esta opcion estamos diciendo que HAProxy no active el docker hasta que el healthcheck de Marathon este ok. 

 “ports”:

  • Por seguridad al ejecutar el Docker en modo HOST, deberemos asegurar que los puertos que utiliza nuestro HAProxy están disponibles en el Slave de Mesos, junto con “requirePorts” : true, añadiendo los puertos tendremos  en PORT0-1-2 que los utilizaremos para hacer el healtcheck de HAProxy

“constraints”:

  • Con estas dos constraints nos aseguramos que no vayamos a tener dos Marathon-lb en el mismo host (puede ser redundante con la opción de ports) y decidimos en que datacenter queremos lanzadlos.

 “healthchecks”:

  • Con este COMMAND comprobamos que el servicio este levantado y Marathon pueda darnos información del estado de HAProxy

Lanzamos marathon-lb

curl -X POST -H "Content-Type: application/json"  --data @marathon-lb-test.json 'http://marathon.company.com:8080/v2/apps'

Veremos en Marathon:

marathon-lb

¿Cómo lanzamos Nginx para que trabaje con Marathon-lb?

Ejemplo de JSON que deberíamos lanzar para que trabajara con marathon-lb, la explicación mas abajo.

Aquí la parte más importante, los labels que hemos añadido en el JSON, a través de labels en nuestro Docker haremos la configuración de nuestro HAProxy, tenemos una lista bastante extensa de opciones, en este ejemplo explicare los que me parecieron más comunes de utilizar.

Podemos encontrar la lista en el github de Mesosphere

“labels”

  • “HAPROXY_BACKEND_WEIGHT”: Peso que tendrá esta backend en HAProxy respecto a otros.
  • “HAPROXY_MODE”: http o tcp
  • “HAPROXY_BALANCE”: Tipo de balance
  • “HAPROXY_GROUP”:  Grupo al que pertenece, con esta opcion asociaremos nuestro nginx al HAProxy que queramos.
  • “HAPROXY_BACKEND_STICKY_OPTIONS” :  Una sticky cookie 
  • “HAPROXY_VHOST”:  Pues lo más importante a que fqdn nuestro HAPoxy nos dará acceso 

Lanzamos nginx

curl -X POST -H "Content-Type: application/json"  --data @nginx.json 'http://marathon.company.com:8080/v2/apps'

Veremos en Marathon:

Apache Mesos Nginx Marathon

Escalamos a 5 nginx

Apche Mesos Marathon scale

Si nos fijamos tenemos, como esperábamos cada nginx en un puerto diferente.

Si comprobamos HAProxy veremos en el log interno qué es lo que hizo.

marathon_lb: received event of type deployment_success
marathon_lb: received event of type health_status_changed_event
marathon_lb: fetching apps
marathon_lb: received event of type deployment_step_success
marathon_lb: GET http://marathon.company.com:8080/v2/apps?embed=apps.tasks
marathon_lb: got apps ['/test/ha/nginx/nginx', '/tools/docker/registry', '/prova-logs','/test/ha/marathon-lb-test']
marathon_lb: generating config
marathon_lb: HAProxy dir is /marathon-lb
marathon_lb: configuring app /test/ha/nginx/nginx
marathon_lb: frontend at *:10001 with backend test_ha_nginx_nginx_10001
marathon_lb: adding virtual host for app with hostname miguel.haproxy.com
marathon_lb: adding virtual host for app with id /test/ha/nginx/nginx
marathon_lb: backend server 192.168.1.100:50071 on server
marathon_lb: backend server 192.168.1.101:58437 on server
marathon_lb: backend server 192.168.1.102:12213 on server
marathon_lb: backend server 192.168.1.103:45197 on server
marathon_lb: backend server 192.168.1.104:14673 on server
marathon_lb: reading running config from /marathon-lb/haproxy.cfg
marathon_lb: updating tasks finished, took 0.24720096588134766 seconds

Podemos ver como marathon-lb

  1. Detecto un nuevo deploy
  2. Comprobó las aplicaciones y únicamente se quedo con las que cumplen la opción –group que explicamos mas arriba
  3. Creo el backend para nuestro ngnix y asigno el virtul host miguel.haproxy.com
  4. Añade todos los dockers que tenemos en nuestro mesos slave en
  5. Actualiza la configuracion
  6. Todo esto en 0.2472 segundos.

Si  comprobamos la pagina de stats de HAProxy podremos ver .

Apache Mesos HAPoxy

Por último comprobamos que nos contesta

curl -H "Host: miguel.haproxy.com" http://192.168.1.10
Welcome to nginx!
Thank you for using nginx.

Todo funcionando!

 

 

03 ene

Raspberry + Tor + HAVP + SQUID + Privoxy

Squid HAVP Privoxy

Tengo vacaciones, tengo vacaciones y una Raspberry apagada en una esquina, pobre de ella. Voy a explicar como utilizar raspberry para montar un sistema para mantener a “salvo” nuestra privacidad usando la red Tor + Privoxy + HAVP + SQUID, a más explicaré como añadir un antivirus que analice todas las peticiones que se hagan a través del sistema

La privacidad, que importante y que fácil es perderla.

La solución tiene diferentes piezas, vamos a ver que hace cada una de ellas.

Tor : Bien conocido por la mayoria https://es.wikipedia.org/wiki/Tor_(red_de_anonimato)

HAVP: Antivirus que escanea el trafico usando ClamAV http://www.server-side.de/features.htm

SQUID: Proxy https://es.wikipedia.org/wiki/Squid_(programa)

Privoxyhttps://es.wikipedia.org/wiki/Privoxy (filtra el contenido indeseable de las páginas, aumenta la seguridad del equipo, evita archivos que nos rastrean y elimina la publicidad.)

La idea viene siendo que las peticiones que hagamos a través de Squid se escaneen utilizando HAVP y se envien a Privoxy, este las limpie y las envíe a la red tor, algo así

RSHPT (3)

Squid HAVP Privoxy

 

En primera instancia lo que vamos a montar es la parte mas estandar que es 1 SQUID + PRIVOXY+TOR, esta solución funciona perfectamente en Raspberry

Algo así

RSHPT (2)

Squid HAVP Privoxy

 

 

La parte del segundo SQUID + HAVP es opcional y si queréis montarlo en Raspberry deberéis tener el modelo de 1GB. Por ello montamos la primera parte, que debe funcionara para todos y después ampliamos con a la parte del antivirus.

Empezamos.

[email protected]# aptitude install tor
[email protected]# aptitude install privoxy
[email protected]# aptitude install squid

Los tres paquetes esenciales, comenzaremos configurando los servidores tor.

Configuración del servicio Tor

Vamos a crear los ficheros de configurar tor

vim /etc/tor/torrc
SocksPort 9050 # what port to open for local application connections
SocksBindAddress 127.0.0.1 # accept connections only from localhost
AllowUnverifiedNodes middle,rendezvous
Log notice syslog
RunAsDaemon 1
User tor
Group tor
DataDirectory /var/lib/tor
Log notice file /var/log/tor/notices.log

Básicamente configuramos el puerto donde queremos que escuche el servidor de tor en nuestro caso por defecto en el 9050

Configuración del servicio Privoxy

Configuraremos Privoxy, este servicio tiene muchas opciones, segun comentan en la pagina del proyecto salir con las opciones por defecto es recomendable, después podremos jugar con más opciones si lo deseamos,  lo que debemos hacer es asociar un Privoxy con un Tor, ajustando el puerto en la linea froward-socks5

vim /etc/privoxy/config
confdir /etc/privoxy
logdir /var/log/privoxy
actionsfile standard.action  # Internal purpose, recommended
actionsfile default.action   # Main actions file
actionsfile user.action      # User customizations
filterfile default.filter
logfile logfile
listen-address  127.0.0.1:8118
toggle  1
enable-remote-toggle  0
enable-remote-http-toggle  0
enable-edit-actions 0
enforce-blocks 0
buffer-limit 4096
forward-socks5   /               127.0.0.1:9050 .
forwarded-connect-retries  0
accept-intercepted-requests 0
allow-cgi-request-crunching 0
split-large-forms 0

Con privoxy y tor ya tendremos las dos piezas esenciales, levantamos los servicios y comprobamos que si realizamos una petición al puerto del privoxy este ya se comunica con tor y nos envia por la red tor.

La idea de poner el SQUID por delante es que nos permite si lo deseamos aplicar acl y diferentes reglas, a mi parecer es algo más potente que privoxy

Configuración del servicio SQUID 1

Como hemos explicado en otro post, podéis montar vuestro propio paquete Squid para habilitar algunas opciones, en mi casa por ejemplo la posibilidad de añadir certificados ssl.

La instalación es sencilla

[email protected]# aptitude install squid3

Una vez instalado modificamos el fichero de configuración

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
acl user src 192.168.1.138/32 ::1
acl userlist src all
http_access allow user
http_access allow userlist
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access deny all
http_port 3400
cache_peer 192.168.1.101 parent 8118 0 no-query no-digest
never_direct allow all
coredump_dir /var/spool/squid3
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320
access_log /var/log/squid3/access_squid.log

Las lines que son un poco diferentes son

Acl de acceso, aqui teneis dos ejemplos, en uno limitamos por ip y en el otro damos permiso a todo (es un ejemplo y son redundantes entre ellas, es mas mejor no dar acceso a todo el mundo )

acl user src 192.168.1.138/32 ::1
acl userlist src all

Puerto del squid3

http_port 3400

Y a donde se enviará las peticiones, en este caso al puerto del privoxy

cache_peer 192.168.1.101 parent 8118 0 no-query no-digest
never_direct allow all

El log

access_log /var/log/squid3/access_squid.log

Arrancamos el servicio y comprobamos que la solución funciona

systemctl start squid3

Vamos a realizar 2 curls, el primero normal y el siguiente utilizando el sistema que hemos montado.

Sin Proxy

[email protected]:~#  curl ipv4.icanhazip.com
37.135.18.39

Con Proxy

curl -x 192.168.1.101:3400 ipv4.icanhazip.com
207.244.70.35

Claramente podemos ver el cambio de ip ya que estamos saliendo por la red TOR, con lo que conlleva.

Vamos a por la segunda parte, instalación y configuración de Squid 2 y HAVP

 Instalación de paquetes

Recordar que allí donde vayamos a instalar HAVP deberemos tener como mínimo 1 GB de RAM.

Configuración de Squid 2
vim /etc/squid3/squid.conf
acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
acl user src 192.168.1.138/32 ::1
acl userlist src all
http_access allow user
http_access allow userlist
http_access allow localhost manager
http_access deny manager
http_access allow localhost
http_access deny all
http_port 3128
cache_peer 127.0.0.1 parent 3410 0 no-query no-digest
never_direct allow all
coredump_dir /var/spool/squid3
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320
access_log /var/log/squid3/access_squid.log

Es la misma configuración que el anterior proxy pero lo que haremos es cambiar el puerto de entrada (en el caso que lo tengamos en la misma maquina) y apuntar el cache_peer al puerto del HAVP en este caso el 3410

cache_peer 127.0.0.1 parent 3410 0 no-query no-digest
 Configuración de HAVP

Deberemos decirle al servicio que todas aquella peticiones desde el SQUID 2 las debe reenviar al SQUID 1.

USER havp
GROUP havp
DAEMON true
PIDFILE /tmp/havp.pid
SERVERNUMBER 1
MAXSERVERS 1
SCANTEMPFILE /tmp/havp-XXXXXX
TEMPDIR /tmp
DBRELOAD 60
PARENTPROXY 192.168.1.101
PARENTPORT 3400
FORWARDED_IP false
X_FORWARDED_FOR false
PORT 3410
BIND_ADDRESS 127.0.0.1
ENABLECLAMLIB true
ENABLECLAMD false
ENABLEFPROT false
ENABLEAVG false
ENABLEAVESERVER false
ENABLESOPHIE false
ENABLETROPHIE false
ENABLENOD32 false
ENABLEAVAST false
ENABLEARCAVIR false
ENABLEDRWEB false

Por ultimo deberemos montar el sistema de ficheros donde tengamos HAVP con la opcion -o mand.

/dev/mmcblk0p2  /  ext4    defaults,noatime,mand  0       1
mount -o remount /

Arrancamos y comprobamos

 /etc/init.d/havp start
Starting havp (via systemctl): havp.service.
Comprovación

En el gif podeis ver 4 ventanas cada una de ellas es una de las piezas principales del sistema, la idea es lanzar un curl desde un cliente y ver como la peticion pasa por todas las piezas.

status

Lanzamos

curl to NSA

Como podemos ver la petición pasa por todos los sistemas, si que es verdad que introducir la pieza de HAVP hace que la petición sea mas lenta.

¿Cómo podemos utilizar la solución de forma sencilla?

En mi caso utilizo la extensión  para chrome FoxyProxy, con ella de forma sencilla podemos tener más de un proxy configurado y decidir cual utilizar en cada momento.

Por último un resultado de una página con bloqueos de Privoxy es

Captura O una prueba completa en una pagina que tiene bastantes anuncios, cookies y cosas raras y feas

Result_maauso.com

29 dic

¿Cómo compilar Squid con SSL?

Como bien sabemos Squid con ssl no viene por defecto, para activar esta opción debemos compilar el paquete Squid con la opción –enable-ssl, entonces ¿cómo compilar squid con ssl?

En mi caso me hizo falta para arm, pero el procedimiento es igual para arquitecturas x86

Paquetes necesarios

[codeBusc]
sudo apt-get install devscripts build-essential fakeroot libssl-dev
[/code]

Código fuente de Squid3

apt-get source squid3
apt-get build-dep squid3

Dependencias

dpkg-source -x squid3_3.4.8-6+deb8u1.dsc
Preparación del paquete

Añadimos las opciones de compilación en el fichero rules


vim squid3-3.4.8/debian/rules

DEB_CONFIGURE_EXTRA_FLAGS := --datadir=/usr/share/squid3 \
                --sysconfdir=/etc/squid3 \
                --mandir=/usr/share/man \
                --enable-inline \
                --disable-arch-native \
                --enable-async-io=8 \
                --enable-storeio="ufs,aufs,diskd,rock" \
                --enable-removal-policies="lru,heap" \
                --enable-delay-pools \
                --enable-ssl \
                --enable-ssl-crtd \
Compilación de Squid con SSL

Y por último a compilar y a esperar, en mi caso fueron varias horas, pobre Raspberry

 dpkg-buildpackage -rfakeroot -b 

Una vez finalizado dispondremos de diferentes paquetes, los dos que nos hacen falta son

squid3_3.4.8-6+deb8u1_armhf.deb
squid3-common_3.4.8-6+deb8u1_all.deb

Una vez instalados podremos comprobar que mirando la versión de squid tendremos activada la opcion –enable-ssl 

[email protected]:~# squid3 -v | grep ssl
configure options:  '--build=arm-linux-gnueabihf' '--prefix=/usr' '--includedir=${prefix}/include' '--mandir=${prefix}/share/man' '--infodir=${prefix}/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--libexecdir=${prefix}/lib/squid3' '--srcdir=.' '--disable-maintainer-mode' '--disable-dependency-tracking' '--disable-silent-rules' '--datadir=/usr/share/squid3' '--sysconfdir=/etc/squid3' '--mandir=/usr/share/man' '--enable-inline' '--disable-arch-native' '--enable-async-io=8' '--enable-storeio=ufs,aufs,diskd,rock' '--enable-removal-policies=lru,heap' '--enable-delay-pools' '--enable-ssl' '--enable-ssl-crtd' '--enable-cache-digests' '--enable-icap-client' '--enable-follow-x-forwarded-for' '--enable-auth-basic=DB,fake,getpwnam,LDAP,MSNT,MSNT-multi-domain,NCSA,NIS,PAM,POP3,RADIUS,SASL,SMB' '--enable-auth-digest=file,LDAP' '--enable-auth-negotiate=kerberos,wrapper' '--enable-auth-ntlm=fake,smb_lm' '--enable-external-acl-helpers=file_userip,kerberos_ldap_group,LDAP_group,session,SQL_session,unix_group,wbinfo_group' '--enable-url-rewrite-helpers=fake' '--enable-eui' '--enable-esi' '--enable-icmp' '--enable-zph-qos' '--enable-ecap' '--disable-translation' '--with-swapdir=/var/spool/squid3' '--with-logdir=/var/log/squid3' '--with-pidfile=/var/run/squid3.pid' '--with-filedescriptors=65536' '--with-large-files' '--with-default-user=proxy' '--enable-build-info=Raspbian linux' '--enable-linux-netfilter' 'build_alias=arm-linux-gnueabihf' 'CFLAGS=-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wall' 'LDFLAGS=-fPIE -pie -Wl,-z,relro -Wl,-z,now' 'CPPFLAGS=-D_FORTIFY_SOURCE=2' 'CXXFLAGS=-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security'

Con esto ya disponemos de Squid con SSL, ahora podemos añadir certificados para la creación del una conexión segura cliente servidor.

 

 

17 ago

Añadir nodo a un cluster Voldemort

Después de explicar ¿qué es voldemort? y ¿cómo instalarlo? nos quedamos con un cluster de dos nodos, en este post explicaré como añadir en nuevo nodo a un cluster Voldemort.

cluster voldemort

Como impresiones generales diré, que no es sencillo, no es intuitivo y no es rápido, pero que hacer, se puede hacer.

Me pareció algo así

Tarea

Primero de todo nos ponemos en situación, en el ultimo post, teníamos un cluster de dos nodos, con 5 particiones.


<cluster>
 <name>Test</name>
 <server>
 <id>0</id>
 <host>node1</host>
 <http-port>8081</http-port>
 <socket-port>6666</socket-port>
 <partitions>0, 2, 4</partitions>
 </server>
 <server>
 <id>1</id>
 <host>node2</host>
 <http-port>8081</http-port>
 <socket-port>6666</socket-port>
 <partitions>1, 3, 5</partitions>
 </server>
</cluster>

Como sabemos al ser la particiones estáticas deberemos utilizar las 6 que disponemos, el sistema de voldemort trae herramientas que nos dan una idea de cómo debería quedar el cluster.

Los pasos son

  1. Reparticionar
  2. Rebalancear
  3. Lanzar la tarea
  4. Limpiar datos huérfanos

Paso 1 .- Repartition.

Para una expansion del cluster deberemos crear un fichero cluster xml provisional  “interim”, en el que añadiremos los nuevos nodos , pero con la parte de particiones vacía.


<cluster>
<name>qacluster</name>
<server>
<id>0</id>
<host>nodo1</host>
<http-port>8081</http-port>
<socket-port>6666</socket-port>
<partitions>0, 2, 4</partitions>
</server>
<server>
<id>1</id>
<host>nodo2</host>
<http-port>8081</http-port>
<socket-port>6666</socket-port>
<partitions>1, 3, 5</partitions>
</server>
<server>
<id>2</id>
<host>nodo3</host>
<http-port>8081</http-port>
<socket-port>6666</socket-port>
<partitions></partitions>
</server>
</cluster>

Como podemos ver añadimos el nodo 3 en un fichero cluster-interim, pero con las particiones vacías.

Lanzamos la herramienta de RepartitionerCLI, la encontramos dentro de la carpeta bin.

bin/run.class.sh voldemort.tools.RepartitionerCLI --current-cluster <current-cluster> --current-stores <current_stores> --interim-cluster <interim-cluster> --output-dir <output_dir>

Os recomiendo que os creáis unas carpetas para tener cada fichero ordenado, deberemos añadir todos los stores en un solo fichero, el ejemplo de la llamada sería.

bin/run-class.sh voldemort.tools.RepartitionerCLI --current-cluster repo_stores/cluster.xml --current-stores repo_stores/prueba.xml --interim-cluster repo_stores/interim/cluster.xml --output-dir repo_stores/plan/

Dentro de la carpeta repo_stores/plan tendremos

current-cluster.xml.analysis
final-cluster.xml
final-cluster.xml0
final-cluster.xml0.analysis
final-cluster.xml.analysis

En los ficheros de analysis tendremos los pasos que realizar para llegar a la estructura final del cluster, que es el fichero final-cluster.xml

Paso 2 .- Rebalancing 

Deberemos crear el plan para hacer el rebalancing, usaremos el fichero final-cluster.xml que obtuvimos del paso anterior.

bin/run-class.sh voldemort.tools.RebalancePlanCLI --current-cluster repo_stores/cluster.xml --current-stores repo_stores/prueba.xml --final-cluster repo_stores/planRepartitioner/final-cluster.xml --output-dir repo_stores/planRebalance/

En la carpeta planRebalance deberemos tener el fichero final-cluster.xml, recordemos que tenemos 2 nodos que estan trabajando, pero un tercero que no esta dentro del cluster ni tienes las stores, asi que debemos añadirlo y  crear las stores en el tercer nodo antes de continuar.

Debemos utilziar el fichero de cluster-interim del paso 1, para actualizarlo en todos los servidores, de esta manera el nodo 3 no tendrá particiones y será, la tarea de rebalancing del paso siguiente la que lo actualice las particiones.

bin/vadmin.sh meta set cluster.xml=repo_stores/interim/cluster.xml --node 0 --url tcp://127.0.0.1:6666
bin/vadmin.sh store add --file repo_stores/prueba.xml --node 2 --url tcp://127.0.0.1:6666

Utilizamos la herramienta vadmin.sh con la opcion –node 2, para añadir las stores únicamente en el servidor 3

 Paso 3 .- Lanzar el rebalancing 

Utilizaremos la siguiente herramienta.

bin/run-class.sh voldemort.tools.RebalanceControllerCLI --url $URL --final-cluster final-cluster.xml --parallelism 8 --proxy-pause 900
  • $URL: Será la direccion de uno de los nodos del cluster
  • Final-cluster :  EL fichero final-cluster que obtuvimos en el último paso, que es la situación final que estará el cluster cuando termine la tarea.
  • Parallelism: Numero de tareas de rebalancing que se pueden lanzar en el mismo momento.
  • Proxy-pause : El tiempo que esperará entre la actualizacion de la metadata y el inicio del rebalancing,

Nota: Antes de lanzarlo si paramos en medio del proceso, el sistema queda inestable asi que utilicemos algun screen o tmux o algo asi …

bin/run-class.sh voldemort.tools.RebalanceControllerCLI --url tcp://127.0.0.1:6666 --final-cluster repo_stores/planRepartitioner/final-cluster.xml --parallelism 8 --proxy-pause 900

Nos dará información sobre lo que va ha hacer y comenzara el proceso, ¿cómo podemos ver el estado?

bin/vadmin.sh async-job list --url tcp://127.0.0.1:6666

 

Aquí podemos ver que esta haciendo, como dato informativo en mi caso para 20Gb de información tardo 4 horas, o sea rápido rápido no es

Y por último.

 Paso 4 .- Limpieza de los datos huérfanos.

Este proceso solo mueve datos, con lo que una vez terminado habrá nodos que tendrán datos de particiones que ya no le pertenecen.

bin/vadmin.sh cleanup orphaned-data --all-nodes --url tcp://127.0.0.1:6666

Finalizado, cluster ampliado, en el siguiente post explicaré el concepto de zonas y como aprovecharlas para realizar replicaciones.

 

 Referencias: 

http://www.project-voldemort.com/voldemort/rebalance.html

https://github.com/voldemort/voldemort/wiki/Voldemort-Admin-to

 

 

 

 

 

 

 

 

10 ago

Instalación de Voldemort

Después de explicar una idea general de qué es voldemort, vamos a explicar como realizar la instalación de Voldemort, y montaremos un cluster de 2 nodos. En los siguientes post veremos como ampliarlo a tres nodos.

Preparación del paquete

Si nos vamos a la pagina del proyecto http://www.project-voldemort.com/voldemort/ veremos que la ultima version disponible que nos encontramos en la 1.6, versión muy antigua respecto a la actual, 1.9.12, ¿dónde encontramos esta versión?

https://github.com/voldemort/voldemort.git

Tenemos el código y deberemos compilarlo para poder utilizarlo.

Pues vamos a ello.

En mi caso voy a montar 2 instancias lxc,  lo haremos de la siguiente manera.

Crearemos 2 instancias de lxc, voldemort y voldemort1 (ya que querremos probar el cluster en los siguientes post).


[email protected]:~# lxc-create -t download -n voldemort1 -- --dist ubuntu --release trusty --arch amd64

Arrancamos y nos conectamos a la máquina voldemort


lxc-start -n voldemort1 ; lxc-attach -n voldemort1 

Necesitamos una serie de paquetes para compilar y hacer correr Voldemort.

 sudo apt-get install openjdk-7-jre openjdk-7-jre-headless gradle openjdk-7-jdk git 

Bajamos el codigo de github

 git clone https://github.com/voldemort/voldemort.git cd voldemort 

Compilamos

 ./gradlew clean jar 

Esperamos y nos quedamos con los siguientes directorios.

dist/*.jar
lib/*.jar
contrib/*/lib/*.jar
contrib/*/lib/*.jar
src/java/log4j.properties
config/ bin/

Ya tenemos el paquete montado.

Configuración de Voldemort 

Vamos a ver los ficheros importantes

Cluster.xml – Fichero que debe ser igual en todos los nodos del cluster  y tendrá la información sobre puertos, hostnames, el nombre del cluster y por supuesto las particiones (explicadas en el post), donde definiremos como vamos a repartir los datos por nuestro cluster, debemos recordad que las particiones son estáticas en numero o sea que deberemos pensar bien cuantas seleccionamos.

Stores.xml  – Aquí nos encontraremos la definición de las tablas, así como todos parámetros para las mismas, por ejemplo el número de lecturas y escrituras que tiene que ir bien para dar el dato como bueno, o el tipo de replicación que tendremos por store.

Server.properties – Contiene los parámetros de optimización para cada nodo en particular, por ejemplo el id del nodo (único para todos nodos del cluster), este es un fichero diferente para cada nodo.

Entonces, deberemos tocar en ambos nodos el fichero cluster.xml, podemos poner algo así.

 

<cluster>
 <name>Test</name>
 <server>
 <id>0</id>
 <host>node1</host>
 <http-port>8081</http-port>
 <socket-port>6666</socket-port>
 <partitions>0, 2, 4</partitions>
 </server>
 <server>
 <id>1</id>
 <host>node2</host>
 <http-port>8081</http-port>
 <socket-port>6666</socket-port>
 <partitions>1, 3, 5</partitions>
 </server>
</cluster>

Definimos el hostname de los servidores, los puertos y las particiones, elegí 5 particiones ya que como sabemos son estáticas y tengo pensado añadir un nuevo nodo, con lo que deberemos rehacer la reasignación.

Arrancamos…  La última linea debe ser algo así,

[10:27:01,032 voldemort.server.VoldemortServer] INFO Startup completed in 566 ms. [main]

Si nos fijamos en el log de salida, la verdad es que no nos da mucha información de si el cluster esta activo o no, nuestro gran amigo para interactuar con el cluster es vadmin (lo encontramos en la carpeta /bin)

Podemos lanzar algo así.

bin/vadmin.sh meta check-version --url tcp://10.2.11.201:6666
Node : 0 Version : version() ts:1438175142424
Node : 1 Version : version() ts:1438175142424
All the nodes have the same metadata versions.
avro-example=0
stores.xml=0
cluster.xml=0
test=0

Parece que tenemos un cluster de voldemort!

Creación de Stores

Ahora que tenemos el cluster montado debemos crear algún store, podemos utilizar algunos de los xml que vienen de prueba en el paquete de instalación.


<store>
 <name>Primer_Store</name>
 <persistence>bdb</persistence>
 <description>Test store</description>
 <owners>[email protected], [email protected]</owners>
 <routing-strategy>consistent-routing</routing-strategy>
 <routing>client</routing>
 <replication-factor>1</replication-factor>
 <required-reads>1</required-reads>
 <required-writes>1</required-writes>
 <key-serializer>
 <type>string</type>
 </key-serializer>
 <value-serializer>
 <type>string</type>
 </value-serializer>
 <hinted-handoff-strategy>consistent-handoff</hinted-handoff-strategy>
</store>

Deberemos fijarnos en los siguientes campos.

routing-strategy: Definimos el tipo de estrategia para grabar los datos, en el caso que nuestro cluster no tenga zonas utilizaremos consisten-routing.
required-reads: Numero de lecturas necesarias para que la operación se de por buena.
required-writes: Numero de escrituras necesarias para que la operación se de por buena.

Creamos el store.

bin/vadmin.sh store add --file repo_stores/primer_store.xml --url tcp://nodo1:6666

Podemos comprobar en el log algo tal que así

Aug 02 10:57:47 voldemort-server.sh[3563]: [10:57:47,572 voldemort.utils.StoreDefinitionUtils] INFO Validating schema for store: Primera_Store [voldemort-admin-server-t8]Aug 02 voldemort-server.sh[3563]: [10:57:47,595 voldemort.store.metadata.MetadataStore] INFO Updating routing strategy for all stores [voldemort-admin-server-t8]
Aug 02 10:57:47 voldemort-server.sh[3563]: [10:57:47,595 voldemort.server.protocol.admin.AdminServiceRequestHandler] INFO Successfully added new store 'Primera_Store' [voldemort-admin-server-t8]

Por último vamos a realizar una pequeña prueba de stress, para comprobar si es tan rapido como dicen.

./bin/voldemort-performance-tool.sh --record-count 500000
                                    --value-size 10240
                                    --ops-count 1000000
                                    --target-throughput 100
                                    --url tcp://prod:6666
                                    --store-name Primera_Store
                                    -r 90 -m 10

Donde

record-count: Numero de registros insertados
value-size: tamaño de cada registro
target-throughput: Numero de operaciones por segundo.
Y 95% de lecturas.


bootstrapTime=1438673554246 [0/1956]
context=
deploymentPath=/opt/voldemort-1.9.12
localHostName=
sequence=0
storeName=prueba
updateTime=1438673554021
releaseVersion=1.9.18
clusterMetadataVersion=0
max_connections=50
max_total_connections=8
connection_timeout_ms=500
socket_timeout_ms=1500
routing_timeout_ms=1500
client_zone_id=-1
failuredetector_implementation=voldemort.cluster.failuredetector.ThresholdFailureDetector
failuredetector_threshold=95
failuredetector_threshold_count_minimum=30
failuredetector_threshold_interval=300000
failuredetector_threshold_async_recovery_interval=10000
[main]
Running warmup
[warmup] RunTime(ms): 1088442
[warmup] Throughput(ops/sec): 9187.4441
======================= iteration = 0 ======================================
[benchmark] RunTime(ms): 36187
[benchmark] Throughput(ops/sec): 13955.2878
[reads] Operations: 152027
[reads] Average(ms): 0.0179
[reads] Min(ms): 0
[reads] Max(ms): 201
[reads] Median(ms): 0
[reads] 95th(ms): 0
[reads] 99th(ms): 0
[writes] Operations: 251929
[writes] Average(ms): 0.0972
[writes] Min(ms): 0
[writes] Max(ms): 213
[writes] Median(ms): 0
[writes] 95th(ms): 0
[writes] 99th(ms): 1
[transactions] Operations: 50742
[transactions] Average(ms): 0.1662
[transactions] Min(ms): 0
[transactions] Max(ms): 212
[transactions] Median(ms): 0
[transactions] 95th(ms): 1
[transactions] 99th(ms): 2
[deletes] Operations: 50302
[deletes] Average(ms): 0.0149
[deletes] Min(ms): 0
[deletes] Max(ms): 132
[deletes] Median(ms): 0
[deletes] 95th(ms): 0
[deletes] 99th(ms): 0
[09:51:18,948 voldemort.common.service.VoldemortService] INFO Stopping scheduler-service [main]

Esto parece que va, ya tenemos hecha la Instalación de Voldemort con una media de:

0.017ms en lectura

0.09 en escritura

0.014 en borrado

No esta nada mal para las 13900 operaciones por segundo que le lanzamos….

 

Notes

http://www.project-voldemort.com/voldemort/

04 ago

Voldemort sistema de cache distribuida

En los últimos dias me topé con la necesidad de aprender y montar Voldemort, voy a intentar que este sea el primero de una serie de post donde explicaré todo aquello que vaya descubriendo sobre Voldemort sistema de cache distribuida

Empecemos, como todos sabemos Voldemort es bien conocido por ser el incomprendido de la serie de libros Harry Potter, pues entre hechizo y hechizo planeando su maquiavélica victoria y ayudado por Linkedin monto un sistema de cache distribuida, y la verdad es que no le quedó nada mal!

¿Cómo salio este proyecto?

Básicamente se unieron dos ideas, por un lado Amazon Dynamo Storage system que nos ofrece:

  • Poder trabajar en diferentes datacenters
  • Eventual Consistency
  • Y facil de poner en marcha.

Y por otro lado el bien conocido Memcache

  • Multiples lecturas y escrituras
  • Consisten Hashing para la distribución de datos
  • Clave-Valor
  • Versionado de datos

Si juntamos estos dos conceptos tendremos una idea de lo que es Voldemort.

¿Qué nos ofrece Voldemort?

Eligiendo las 2 opciones del Teorema de CAP

  • Particionamiento de datos a través del cluster
  • Alta disponibilidad

A más

  • Escalavilidad Horizontal
  • “Transparencia” para la aplicación

¿Qué no nos ofrece Voldemort?

Consistencia estricta de los datos, es muy importante el adjetivo estricto, nos ofrece Eventual Consistency, podemos “asegurar” que el dato escrito por el cliente será leído por la siguiente petición.

¿Cómo funciona  Eventual Consistency de Voldemort?

Principalmente necesitaremos dos puntos

  • Saber cual es el ultimo valor
  • Saber que valores no son comparables.

Soluciones

  • Timestamps
  • Vector Clocks
    • Nos ofrecen una manera de tener eventos ordenados en un sistema distribuido, cada vector es una tupla.
    • Como tenemos un sistema con particiones, cada valor tendrá un master del cluster
      • Cuando un dato es escrito en el master, todas las replicas reciben la misma versión
      • Con lo que no tenemos necesidad de bloqueos

¿Cómo trabajamos con los datos?

  • Los datos se organizan dentro de Stores, podríamos pensar que son como tablas en los sistemas tradicionales.
  • Solo disponemos de clave->valor, pero podremos hacer listas, mapas, juntando combinaciones
  • Los datos se reparten en particiones.

Partition voldemort distributed cache system

  • Repartimos los datos en particiones y las particiones entre los nodos.
  • Definimos en replicación de cada dato por store
  • Definimos el numero de lecturas/escrituras necesarias.
    • Esto quiere decir que si tenemos 3 nodos en un cluster, cuando un cliente lee o escribe, podremos definir cuantos OK de escritura debemos tener para que se de por buena la operación
    • O sea que si el numero de R+W > N(Numero de nodos) podremos leer nuestras propias escrituras.

Zonas

Disponemos de Zonas.

Zones architecture voldemort distributed cache system

Podemos crear tantas zonas como queramos, con ellas podemos conseguir tener servidores repartidos en diferentes datacenters, de esta manera el cluster sabrá donde tiene mas o menos latencia.

También las podemos utilizar en el caso de la virtualización, si disponemos de 4 zonas en 2 servidores, nos interesara que las replicaciones no se realicen en los nodos que corren en el mismo servidor, ya que en el caso de fallo del mismo… pues mal asunto.

Detección de errores

  1. Necesitamos que sea muy rápido
  2. Encontrar los servidores que tienen inconsistencia
    1. El servidor A puede hablar con el servidor B, pero C no puede
    2. A puede hablar con C, B puede hablar con A, pero no con C
    3. Actualmente se controla por los timeout, periodicidad de fallos

Mecanismos de Reparación

  • Read Repair
    1. Un cliente recibe valores de múltiples nodos
    2. Notifica al nodo si uno de los valores es antiguo entonces en nodo actualiza su valor
  • Hinted Handoff
    1. Si una escritura falla en cualquier nodo, es marcada como escritura especial
    2. Cada nodo periódicamente intenta deshacerse de todas las escrituras especiales.

Visión general tenemos 3 arquitecturas posibles

Architecture voldemort distributed cache system

  1.  La aplicación no conoce donde se encuentran los datos en el cluster, por cada petición, el cluster deberá ir a buscar el dato al nodo que a través de la partición lo tenga y lo entregara al cliente.
  2. La aplicación sabe que nodo tiene el dato, de tal manera que la petición es directa.
  3. Asociamos una instancia de Voldemort a cada servicio del Backend.

 

26 jul

¿Cómo crear registros SPF de más de 255 caracteres?

Después de varios años en el mundo de la informática, hace poco me encontré con esta limitación de los registros spf, que la verdad ni me la imaginaba.

¿Qué es un registro SPF?

SPF es el acrónimo de Sender Policy Framework, una protección contra la falsificación de direcciones en el envío de correo electrónico. Identifica a los servidores de correo SMTP autorizados para el transporte de los mensajes a través de los registros de nombres de dominio (DNS).

¿Cómo crear registro SPF de más de 255 caracteres?

Pues la idea esencial es dividir los registros en spf más pequeños, tal que así.

@ IN TXT "v=spf1 include:_spf1.myhost.com include:_spf2.myhost.com a mx ?all"
_spf1 IN TXT "v=spf1 ip4:xxx.xxx.xxx.xxx ip4:xxx.xxx.xxx.xxx a mx ?all"
_spf2 IN TXT "v=spf1 ip4:xxx.xxx.xxx.xxx ip4:xxx.xxx.xxx.xxx ip4:xxx.xxx.xxx.xxx a mx ?all"

Generamos 3 registros TXT, el primero referencia a los dos siguientes, en los cuales repartiremos toda la lista de ips, con lo que hemos abierto la posibilidad de añadir registros nuevamente.

Notas interesantes:

El carácter anterior al all puede variar según nuestras necesidades.

Value                          Description
+                                   Default. Pass. Domain owner deems this a conclusive test.
–                                   Fail. Domain owner deems this a conclusive test.
~                                  Softfail. Domain owner deems this an inconclusive test – mail should be treated as if no SPF existed.
?                                  Neutral. Domain owner deems this an inconclusive test – mail should be                                       accepted.
Leer más

26 may

Presentación Apache Mesos

Despúes de las explicaciones llegó la presentación, podeis obtener mas información en:

  1. ¿Qué es Apache-Mesos?
  2. ¿Cómo instalar Apache-Mesos?
  3. Apache-Mesos

 

26 may

Presentación Marathon Framework para Apache Mesos

Más información en

1.- Marathon framework para Apache-Mesos

2.- Balanceo de servicios con Marathon en Mesos