linux

Yosemite, Linux y rEFInd en un Macbook pro viejuno

Hola queridos lectores.

Salió Yosemite y los fanboys se empezaron a masturbar pensando en Steve Jobs desnudo en una piscina de iphones 6. Pero algunos power users que queremos tener también linux en nuestro precioso y hojalatado Macbook, o por lo menos yo, no estábamos tan contentos con el cambio. Para empezar han cambiado la versión de Ruby y, los que usamos brew, ya nos ha tocado reinstalar todo. También les ha dado por joder con el journaled y OBLIGAR a usarlo. También han guarreado la EFI, en fin… pero es super cuqui y super bonito el diseño, eso sí.

A mi, manías que tengo, me gusta tener mi partición con $LinuxDistribution. Y hace un tiempo que encontré una herramientita que se llamaba rEFIt, que luego pasó a llamarse rEFInd, muy maja y sencillita, que funcionaba muy bien para tener nuestro arranque dual. Con sus themes y sus cositas. Pues claro, al joder la marrana con la EFI, pues no funcionaba. Me puse a indagar.

Lo primero que vi es que el creador de rEFInd quería que le comprásemos un mac nuevo porque su comentario en la web de la herramienta era el siguiente:

Recently, Apple released OS X 10.10 (aka Yosemite), and I’ve been getting e-mails with problem reports. Unfortunately, my only Mac is an ancient 32-bit model that can’t run the latest version, so I can’t investigate the cause of the problems myself.

Que en cristiano significa: “No tengo ganas de marearme en arreglaros vuestros problemas con mi herramienta, pero si queréis que lo haga, necesito un mac en el que pueda instalar Yosemite”. A lo que los usuarios respondieron pasando de él bastante, preguntándole cosas sueltas, y probando.

Parece ser que la solución pasaba por instalar la EFI modificada en una partición ESP, que es lo que usaban los que no quería tener el disco particionado y lo instalaban en uno externo. Esto lo que hace es instalarlo en una partición msdos que tiene nuestro querido Mac, montarla en el directorio /Volumes/ESP, guarrear con la EFI tuneada y a correr.

De aquí surgían dos problemas:

  1. No detectaba la magnifica partición de MacOSX.
  2. Tardaba más de 30 segundos en aparecer el menú del bootloader, un coñazo, vaya.

Bueno, el primer problema era muy sencillo, basta con descomentar la opción “dont_scan_volumes” (que viene comentada) y a correr. Os aparecerá una opción de arranque que rezará “Recovery HD” pero es mentira, no es el recovery, es la partición donde está Yosemite. La renombrais y tal con la conf, que pa eso está.

El segundo problema ya era un poco más complejo. En la web de rEFInd hay unas pinceladas que da el muchacho de cómo arreglarlo, pero se marea poco, porque claro: no le hemos comprado el Mac que quería. Pero bueno, en un hilo de discusión de sourceforge encontré a un tal Uncle Sam, “tío Sam”, que me gustó su nombre mucho y además parece que entendía de la movida.

Básicamente el tío Sam lo que hace es renombrar la EFI modificada al nombre que MacOSX espera ver como EFI, que es bootx64.efi que tiene que estar dentro de la carpeta BOOT. En lugar de ser refind_x64.efi como venía siendo hasta ahora. Se renombra y con bless se le dice al sistema que la EFI nueva es esa, y ya está. Solucionado. El muchacho propone un script muy majo en este hilo. Script que me he permitido el lujo de rematar para los más vagos del lugar:

#!/bin/bash
mkdir /Volumes/esp
read -p “Press [Enter] key to continue…”

mount -t msdos /dev/disk0s1 /Volumes/esp
read -p “Press [Enter] key to continue…”

mv /Volumes/esp/EFI/refind/ /Volumes/esp/EFI/BOOT
read -p “Press [Enter] key to continue…”

mv /Volumes/esp/EFI/BOOT/refind_x64.efi /Volumes/esp/EFI/BOOT/bootx64.efi
read -p “Press [Enter] key to continue…”

bless –mount /Volumes/esp –setBoot \
–file /Volumes/esp/EFI/BOOT/bootx64.efi –verbose
read -p “Press [Enter] key to continue…”

diskutil unmount /Volumes/esp
read -p “Press [Enter] key to continue…”

Se tiene que ejecutar como root. Basicamente lo que hace es montar la partición, renombrar el fichero y el directorio, hacer el bless y desmontar. En el script original del tío Sam utiliza un umount que en Yosemite ya no funciona. En Yosemite se desmonta con diskutil.

Y con esto tendréis vuestro maravilloso boot dual, amigos. Espero que si alguno llega rebotando desde google todo esto le pueda servir de ayuda.

nginx

Docker y Nginx

Previously, on eltioe1000…

DOCKER. CONTENEDORES LIGEROS PARA LEVANTAR APLICACIONES EN SEGUNDOS.

Os contaba un poco sobre la existencia de Docker, no sé si os interesa, no sé si alguien me lee… ¿hola?, ¿hay alguien ahí?, ¿no?, bueno… seguiré hablando solo, tampoco pasa nada.

Hoy, incautos amigos, os voy a contar un poco sobre como levantar un contenedor en docker, con sus comanditos y sus pasitos uno por uno. Y cómo llegar hasta el servicio con la ayuda de nginx. Cosa facilonga para todos los públicos, incluido yo mismo.

Al lío.

Se me antoja, como ejemplo, así a bolapie; levantar un sphinx en docker por el puerto 3312. ¿Vale tetes?

Pues bien, empecemos.

Antes que nada, docker está en pañalitos. Acaba de empezar a andar, como quien dice. Por tanto todavía hay unas consideraciones previas sobre estabilidad que yo creo que, con el tiempo, desaparecerán. Se puede instalar en cualquier distribución siempre y cuando se respeten unos requisitos de versión de kernel, etc. Pero lo ideal, para que funcione guay, guay; es ponerlo en Ubuntu Server 13.10. Así que eso he hecho yo y va bien, no he visto todavía errores. Aquí podéis leer sobre cómo instalar docker en una Ubuntu, pero es tan sencillo como:

Añadimos con un editor el repositorio a nuestro sources.list:

deb http://get.docker.io/ubuntu docker main

Añadimos la clave para el repositorio de docker y actualizamos apt:

sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9

sudo apt-get update

sudo apt-get install lxc-docker

Opcionalmente, podemos verificar que todo ha funcionado poniendo en marcha un contenedor con bash:

sudo docker run -i -t ubuntu /bin/bash

Con estos simples pasos tendremos docker funcionando. Vamos al nginx.

En Ubuntu, oh, sorpresa:

sudo apt-get install nginx

Y YA ESTA. Ya tenemos un nginx funcionando.

La mandanguilla: Aquí tenéis un Dockerfile del repositorio oficial de docker con el que tenéis un primer pasito para poner sphinx en docker. Pero en realidad no hay que instalar tantas cosas como las que dice ahí para hacerlo funcionar. Por otro lado, ese Dockerfile es interactivo y el que os voy a enseñar yo es no interactivo.

¿Que, qué es esto?, me alegra que me hagáis esta pregunta.

“Grosso modo”, el modo interactivo es lo que hemos hecho antes para comprobar que docker funcionaba. Levantar un contenedor (con o) sin Dockerfile con “algo” (/bin/bash) con lo que podamos utilizar el contenedor como si fuera una máquina virtual. De modo que una vez ahí podemos utilizar apt, instalarnos vim, top, htop, etc y montarnos la máquina que queramos nosotros. Ojo, que docker es no persistente y en cuanto la paréis todos los cambios desaparecerán en la nada. Para hacer los cambios persistentes hay que currárselo, hablaremos de eso otro día, o no, porque me da mucha pereza el tema. La verdad. El modo no interactivo es aquel en el que escribiremos nuestra recetita en el Dockerfile, le diremos que no es interactivo y le daremos un punto de entrada (en el caso de sphinx, le diremos que lo arranque). Con lo cual, en cuanto levantemos el contenedor, empezará a correr sin tener nosotros que entrar a levantarlo o gestionarlo de manera alguna. Esta es la gracia del asunto, amigos.

Inciso hecho. Haré otro inciso.

Existe el comando “docker attach <CONTAINER ID>” con el que podéis entrar dentro de un contenedor y gestionarlo. Ojo con poner “exit” para salir. A colación de lo que os he contado anteriormente. Imaginad que entráis, os ponéis a tirar comandos como si no hubiera un mañana y os montáis ahí la rehostia de contenedor que hace virguerías. Pagados de vosotros mismos, una vez habéis terminado decidís que es buena idea salir del contenedor con el comando “exit“. Error. Con eso pararéis el contenedor y, como no es persistente, todo el trabajo se perderá en el limbo. Para salir de un contenedor al que nos hemos enganchado usaremos Ctrl+P+Q. Esto es, mantener control y pulsar la P y la Q sin soltarlo. Con esto haremos un deattach y no se parará el contenedor. Lo podéis comprobar con el comando “docker ps” que os muestra todos los contenedores que tenéis corriendo y, ya que estoy, con “docker ps -a” veis todos los contenedores corriendo y sus estados por si os da por arrancar uno en algún estado previo a una cagadita, Emilconsejo©.

A partir de este punto os recomiendo que os leáis un poco la documentación sobre buenas prácticas de docker. Pero bueno, sin entrar en detalles tendréis que decidir un lugar donde poner los ficheros de configuración que queráis pasarle al contenedor y los lugares donde queráis que el contenedor os deje ficheros que no queráis perder. Por ejemplo, un sphinx (o un elasticsearch) suele tener un directorio donde guardan todos los índices de búsqueda. Del mismo modo suelen requerir unos ficheros de configuración con vuestra configuración particular para funcionar. Lo normal es usar /var/docker para crear dentro vuestro árbol de directorios para cada contenedor que uséis. En el caso de sphinx es buena idea crear /var/docker/sphinxsearch y dentro el siguiente árbol:

.
├── etc-sphinxsearch
│       └── sphinx.conf
└── var
├── lib
├── log
│      ├── query.log
│      └── searchd.log
└── www
└── sphinx

Como veis tenemos un directorio para guardar la configuración de sphinx en etc, un directorio var con su espacio para lib y con su espacio para logs. Un directorio www requerido por sphinx donde él ya dentro creará los índices y todo lo que necesita. ¿Y cómo sabe el contenedor que tiene que guardar las cosas aquí?, eso lo explicaremos dentro de un momento. Pero primero, el Dockerfile (que estará en el directorio del usuario con el que ejecutemos docker, en la carpeta que hemos creado previamente llamada sphinx, originalidad al poder). Un ejemplo sería:

###  DockerFile for sphinx

FROM debian
MAINTAINER Joh Doe (johndoe@whatever.com)

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update && apt-get –yes upgrade
RUN apt-get install –yes libpq5 unixodbc sphinxsearch

ADD sphinx.conf /etc/security/limits.d/sphinx.conf
ADD sphinxsearch /etc/default/sphinxsearch

ENTRYPOINT [“/usr/bin/searchd”]

# docker run -p 3312:3312 -d -v /var/docker/sphinxsearch/etc-sphinxsearch:/etc/sphinxsearch -v /var/docker/sphinxsearch/var/log:/var/log/sphinxsearch -v /var/docker/sphinxsearch/var/lib:/var/lib/sphinxsearch -v /var/docker/sphinxsearch/var/www:/var/www debian/sphinx

Es fácil. Se ve que lo que hacemos es simplemente decirle lo que os he comentado antes, que no es interactivo. Instalar lo necesario para sphinx y luego veis que añadimos ficheros de configuración (que deben de estar en el mismo directorio que el Dockerfile) a los lugares típicos donde deberán estar, solo que personalizados. Esta parte ya dependerá de vosotros. Y le decimos, por último, el punto de entrada que será, precisamente, el demonio de sphinx.

Podéis extrapolar este ejemplo a cualquier otra cosa que no sea sphinx. Es exactamente igual solo que con las particularidades de lo que sea que tratéis de instalar.

El último comando viene comentado, no vale para el Dockerfile, es un mero recordatorio del comando que hay que lanzar para levantar este contenedor. Ahí, si os fijáis, le decimos que ejecute docker abriendo el puerto 3312, el -d significa “no interactivo” y las -v sirven para indicarle a docker dónde están los directorios donde queremos que guarde y encuentre cosas. Lo que os he comentado antes. Le diremos todos esos directorios y esto nos levantará un contenedor con sphinx con nuestra configuración adaptada a nuestras necesidades.

Añadiremos también un fichero llamado sphinxsearch en el que debemos de indicar lo siguiente:

START=yes

Esto es una particularidad de sphinx, sin más, para que arranque solo.

Por tanto si ejecutamos el comando que viene al final del Dockerfile tendremos nuestro contenedor con sphinx funcionando y listo.

Vamos con la parte de nginx.

Acordaros que antes hemos instalado nginx. Bien, en /etc/nginx/ es donde se encuentra todo lo bueno. Profundizar en el maravilloso mundo de nginx puede ser algo arduo que os dejo para vuestros ratos libres entre paja y paja. Aquí solamente os voy a decir como exponemos el puerto 3312, ¿os suena, verdad? para que se pueda acceder a nuestro sphinx desde fuera.

En el directorio de nginx tenemos un par de carpetas peculiares (en las nuevas versiones, en las viejas la cosa es distinta y desordenada, pero eso ya os lo miráis vosotros). Una se llama “sites-available” y la otra “sites-enabled”. Si sabéis usar apache, ya sabéis de que va. Si no, es tan simple como que en la primera se generan los ficheros de configuración de los diferentes sitios que vayamos creando y en la segunda se enlazan simbólicamente para indicar a nginx que están activos. Tan fácil como eso. Pues bien, vamos a “sites-available” y creamos el fichero llamado “sphinx” en otro alarde de originalidad por nuestra parte. Y lo rellenamos así:

server {
    server_name sphinx.vuestrodominio.com;
    listen 80;

    # keep logs in these files (¿os acordáis del directorio de logs?
    access_log /var/log/nginx/sphinx.access.log;
    error_log /var/log/nginx/sphinx.error.log;

    location / {
        proxy_pass http://localhost:3312;
        proxy_redirect off;

        proxy_read_timeout 5m;

        # make sure these HTTP headers are set properly
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Con esto le diremos a la máquina de docker que cuando alguien venga preguntando a un CNAME llamado sphinx.vuestrodominio.com (que apunta a la máquina de docker y habéis creado como os de la gana, en mi caso con bind) por el puerto 3312 le tenemos que mandar a localhost:3312. Tan simple como eso. Es un proxy. Ya está. No tiene misterio. Fin.

Crearemos el enlace simbólico en la carpeta “sites-enabled” y recargaremos sphinx. Suponiendo que estamos en “sites-enabled

ln -s ../sites-available/sphinx

Ya tenemos sphinx en docker con un proxy nginx, amigas. Hasta la próxima. Besitos.

www.docker.io

Docker. Contenedores ligeros para levantar aplicaciones en segundos.

Hola chicas, hoy os voy a hablar de Docker. Aunque todavía no lo conozco mucho ya lo he usado para algún servicio pequeño. Pero para entender bien de que va, echadle un vistazo a estas diapositivas tan majas que se han currado los desarrolladores. (En general el sitio web de Docker es bastante bueno, tiene tutoriales interactivos y el tutorial normal, de toda la vida, tiene un auto test al final para comprobar que has entendido bien el concepto. Tiene un aire educativo muy, muy currado.)

Bien, ahora que habéis entendido un poco de que va os cuento un poco la idea que yo he cogido de todo esto.

Para un administrador de sistemas, en ocasiones, se presenta la necesidad de tener muchos servicios pequeños distintos, o el mismo pero repetido muchas veces. Por ejemplo en un entorno de pruebas, donde los developers necesitan cada uno su chiringuito y quieren ir probando cositas. Lo normal era levantarle una máquina virtual a cada uno con sus necesidades, o varias máquinas virtuales con diferentes versiones del mismo servicio, etc. El gasto de recursos de una máquina virtual, para según que cosas, era desmesurado. Te podías meter perfectamente en decenas de Gigas de disco y ocupar un entorno virtual casi al completo. Para este tipo de situaciones Docker puede resultar útil.

Por ejemplo, levantar un contenedor en Docker que simule un servicio de mysql en un Ubuntu server puede pasar de ocupar varios Gigas en una máquina virtual completa (que no vas a usar entera) a solamente 400 MEGAS en un contenedor de Docker. Porque Docker solamente te va a levantar lo estrictamente necesario (para que os hagáis una idea de lo que significa “lo necesario”, Docker no os va a instalar ni tan si quiera top, ni vim, ni vi ni leches… ¿para qué?). Además, si lo hacéis bien, tampoco vais a saber ni cómo se llama ese host, ni dónde está, ni nada de nada. De nuevo, ¿para qué?. Solo vais a saber que tenéis un contenedor con mysql dentro, con vuestra configuración personal, y punto pelota. Eso sí, vais a necesitar tener una forma de llegar a ella, puesto que Docker (si os leéis la documentación) dice claramente que los contenedores son para usar dentro de Docker. Que es mentira, pero verdad al mismo tiempo. Os montáis un proxy en Docker, por ejemplo Nginx. Y ya en el proxy le decís que cuando alguien venga a Docker preguntando por un puerto, vaya al localhost a ese puerto y engancháis ahí el contenedor para que sea visible desde fuera. Ya os pondré ejemplos de esto.

La gracia es que, cuando tengáis la recetita hecha (Dockerfile) y vuestros ficheros de configuración customizados, podréis lanzar un contenedor o setecientos en cuestión de segundos. Por ejemplo, levantar un contenedor de mysql sobre Debian tarda exactamente 30 segundos. Si vuestra conexión de internet es más lenta, tardará algo más (porque tardará más en bajarse los paquetes de mysql, básicamente). Pero la cuestión es que no tardará más de unas cuantas decenas de segundos. Y tendréis un contenedor que parecerá una Debian a todos los efectos, con vuestro mysql customizado (o vuestro cluster de mysql, que también se puede, amigos). De repente tenéis un racimo de mysql’s en lo que tardáis en ir a por un café y volver, y configurados como queréis.

¿Qué pasa si cambiais algo en el Dockerfile?, ¿volverá a descargarse todo de cero y montarlo limpio?

No, o no necesariamente. Dependerá de vosotros.

El Dockerfile es lineal, se ejecuta desde arriba hacia abajo por ese orden estricto (por eso tenéis que pensar bien los pasos al confeccionarlo, pero no pasa nada, es la forma natural humana de hacer las cosas. Una lista de pasos a seguir, básicamente, ordenados del primero al último). De repente, en el paso 5 se os ha olvidado añadir una instrucción. La añadís y volvéis a lanzar el contenedor. Él mirará qué pasos antes del 5 están hechos ya y en el orden correcto y no los repetirá. Empezará a partir del nuevo paso que, y aquí viene lo bonito de Docker, se comporta como Git. Sí, amigos. Se registran los cambios como los “commits” de Git y podéis resetear al gusto, volver atrás, etc. Como veis, Docker mantiene una filosofía de ahorrar tiempo en los procesos. ¿Que de repente has metido la pata?, no pasa nada, vuelves al punto previo antes de meterla y continúas. No tienes que empezar de cero. Y además se puede considerar esto auditoría (aunque anónima), y ver qué cambios se han hecho en un contenedor cuando las cosas no funcionan como deben.

Otra cosa que no os he contado sobre Docker que está muy bien es que Docker dispone de un repositorio de contenedores genéricos. Por ejemplo, si quieres una Ubuntu limpia, solo tienes que ejecutar:

docker pull ubuntu

Se descargará una lista de contenedores de Ubuntu por versiones, para que dispongáis de la versión que necesitéis en cada momento. Si ejecutáis el comando “docker images” podréis ver los contenedores disponibles:

root@docker:~$ docker images
REPOSITORY        TAG        IMAGE ID              CREATED       VIRTUAL SIZE
ubuntu                       13.10      9f676bd305a4     3 weeks ago     178 MB
ubuntu                       saucy      9f676bd305a4     3 weeks ago     178 MB
ubuntu                       13.04      eb601b8965b8    3 weeks ago     166.5 MB
ubuntu                       raring     eb601b8965b8    3 weeks ago     166.5 MB
ubuntu                       12.10       5ac751e8d623      3 weeks ago     161 MB
ubuntu                       quantal  5ac751e8d623      3 weeks ago     161 MB
ubuntu                       10.04      9cc9ea5ea540      3 weeks ago     180.8 MB
ubuntu                       lucid        9cc9ea5ea540      3 weeks ago     180.8 MB
ubuntu                       12.04      9cd978db300e    3 weeks ago     204.4 MB
ubuntu                       latest      9cd978db300e    3 weeks ago     204.4 MB
ubuntu                       precise   9cd978db300e    3 weeks ago     204.4 MB

Pero no solamente existe el repositorio oficial. En esta web tenéis un índice de contenedores Docker de todo tipo, hechos por usuarios o bien desde cero o bien usando los oficiales, etc.

Podéis jugar con el tutorial de la propia web, que está muy bien. En el próximo post hablaré de cómo configurar Nginx para acceder a los contenedores desde fuera.

Recursos:

Replicación, recuperación en linea y alta disponibilidad con pgpool2 (3.1.1) Parte II

A continuación os voy a exponer algunas cosas que he aprendido con pgpool en producción. Cosas que en una maqueta no ocurren, pero al utilizar la herramienta en el mundo real… peta y te cagas en su puta madre. Básicamente.


Pool de conexiones y conexiones persistentes


Si os leéis bien la documentación, no como yo, el creador de pgpool menciona que no se deben de utilizar conexiones persistentes a la base de datos porque se llena el pool de conexiones y os lo tira abajo, como un ataque de denegación pero vosotros solitos, sin ayuda de “juaquers” ni nada.

En mi caso existían unas conexiones idle persistentes, no muchas, pero las había. Y por la naturaleza de lo que hay montado, no se pueden cambiar. Deben de ser persistentes. ¿Qué hacemos si nos ocurre esto y no podemos utilizar conexiones no persistentes?, afortunadamente el creador de pgpool pensó en ello y disponemos de varios parámetros de la configuración que podemos modificar para que funcione nuestro pool:

#——————————————————————————
# POOLS
#——————————————————————————

# – Pool size –

num_init_children = 128
                                   # Number of pools
                                   # (change requires restart)
max_pool = 4
                                   # Number of connections per pool
                                   # (change requires restart)

# – Life time –

child_life_time = 300
                                   # Pool exits after being idle for this many seconds
child_max_connections = 0
                                   # Pool exits after receiving that many connections
                                   # 0 means no exit
connection_life_time = 300
                                   # Connection to backend closes after being idle for this many seconds
                                   # 0 means no close
client_idle_limit = 450
                                   # Client is disconnected after being idle for that many seconds
                                   # (even inside an explicit transactions!)
                                   # 0 means no disconnection
En la sección de “pool size” tenemos dos valores claros. El número de pools y las conexiones máximas por pool. Estos valores dependerán de vuestra instalación, en mi caso con esos dos valores es más que suficiente, de hecho con 64 hijos sería suficiente, pero me reservo el doble porque puedo (está montado en un pepino de servidor) y porque en epocas de trafico intenso no vendrá mal ir sobrado. Esto os dará margen de maniobra, tener el pool bastante libre, para jugar con los timeouts que están en la sección “Life time”.
Por defecto cada pool tiene un tiempo de vida de 300 segundos. Bien, este parámetro está bien así. El segundo parámetro tampoco es necesario tocarlo, pero tampoco pasa nada si se establece un límite de conexiones (dependerá de para que lo queráis). Ahora, lo importante. El tiempo de las conexiones están abiertas después de entrar en idle. Lo ideal sería que pusieseis aquí un valor elevado y monitorizaseis vuestra base de datos en producción. En mi caso he utilizado una gráfica de munin para saber la media de tiempo que están mis conexiones en idle y he ajustado este valor en función de esto mismo. Mi media estaba en torno a 230 segundos, pero me he dejado margen para no cortar nada vivo. Por otro lado está el parámetro “client_idle_limit”, para las persistentes. Lo mismo, averiguad a partir del punto en el cual vuestra persistente se vuelve idle y poned el valor con cierto coeficiente de seguridad extra. Esto cortará esas persistentes después de estar idle durante 450 segundos. Podréis elevar este valor más en función del número de pools que hayáis configurado en la sección “pool size”. Si vais muy justos de conexiones, no podréis elevar mucho este valor porque entonces la frecuencia de apertura de conexiones será mayor que la frecuencia de cierre de las idles y se llenará. Cuidado con esto.

Comandos PCP de recuperación de un nodo caido en producción.

En la maqueta todo funciona fetén, ¿verdad?, probamos cuarenta veces la simulación de un nodo caído y la recuperación en línea. Y todo marchaba viento en popa a toda vela. Lo ponemos en producción y ocurre, un nodo se sale del pool. Genial, vamos a probar la recuperación en linea en producción. Te excitas, se te pone el vello de punta, los pezones endurecen, vas a recuperar un nodo en linea sin downtime. Te dispones a ello, escribes el comando tecleando como si estuvieses tocando en un piano la pieza más difícil de Rachmaninov ante un público exigente y en el mejor teatro del mundo (respirad). Respiras unos segundos y relees el comando, está correcto, el tiempo se para y… le das a intro esperando los aplausos y la gloria pero…
Una mierda. Te comes una mierda. Y bien gorda.
No solo el nodo no recupera, no… además te causa un downtime en producción. Los lobos se te echan encima y, menos mal Diocito Santo, existe un timeout para los comandos pcp que avispadamente e inadvertidamente habías puesto a 90 segundos y, solamente en ese tiempo, vuelve todo a funcionar.
Menos mal. Respiras. Los usuarios vuelven a lo suyo después de amenazarte con ir a tu casa a violar a tu mujer y matar a tus hijos mientras miras. Y tu no entiendes que coño pasa. Si en pruebas todo iba genial. Hiciste millones de pruebas: apagando la máquina, reiniciando el servicio, parando el servicio e incluso apagando de botón. Y siempre, siempre, recuperaba el nodo; ¡y rapidisimo!
Y te pasas una semana no entiendo nada, intentando diferentes cosas hasta que; una vez más, te lees bien la documentación y descubres que el pool no recupera un nodo si hay conexiones idle abiertas. Cojones. Otra vez topamos con las peuteas idles.
Deduciréis, amigos, que a pgpool no le gustan las persistentes. Pero es que a nadie le gustan las persistentes y no deberían de usarse. Pero se usan a veces. Aunque sea esa sesión abierta en un screen para hacer pruebas de vez en cuando y consultas a pelo. Eso es una persistente idle, amigos. Y vuestros devops seguro que tienen más de un screen de esos abierto desde 2011 y ni se acuerdan.
Otra vez más, amigos, parametritos pensados para salvar esta inconveniencia:
#——————————————————————————
# ONLINE RECOVERY
#——————————————————————————

recovery_user = ‘postgres’
                                   # Online recovery user
recovery_password = ‘postgres’
                                   # Online recovery password
recovery_1st_stage_command = ‘base-backup’
                                   # Executes a command in first stage
recovery_2nd_stage_command = ‘pgpool-recovery-pitr’
                                   # Executes a command in second stage
recovery_timeout = 500
                                   # Timeout in seconds to wait for the
                                   # recovering node’s postmaster to start up
                                   # 0 means no wait
client_idle_limit_in_recovery = 10
                                   # Client is disconnected after being idle
                                   # for that many seconds in the second stage
                                   # of online recovery
                                   # 0 means no disconnection
                                   # -1 means immediate disconnection
En la sección de “Online recovery” encontramos nuestros famosos comandos de primera y segunda fase que ya comentamos en su momento (ver el archivo de este blog si no sabes de que mierda hablo). Y luego dos maravillosos parámetros, recovery_timeout que podeis poner el tiempo máximo que asumis que vais a esperar a que vuestro nodo recupere y será exactamente el mismo tiempo que vuestra base de datos no acepte conexiones.
Sí amigos, pgpool se vende como algo maravilloso con lo que no sufriréis más downtime pero es mentira. Como todo en esta vida, siempre hay letra pequeña. Esto es falso pero puede parecer verdadero, como las tetas operadas. Supongamos que tenéis una WEB que se conecta a un postgresql. Bien, vuestra WEB es normalita y no tenéis muchas conexiones simultaneas ni nada. Lanzáis una recuperación de nodo y no notáis ese downtime. ¿Por qué?, porque pgpool va a encolar las peticiones hasta que el nodo recupere, son muy pocas y recupera en un segundo. Por tanto, a lo sumo, notáis un pequeño retraso en la consulta. Retraso que puede ocurrir por otros motivos como que vuestra conexión sea lenta o cualquier otra situación cotidiana utilizando Internet. Y pensáis, pgpool es la hostia. Pero, ¿qué pasa cuando tenéis una WEB grande con mucho trafico?. Pues ocurre que pgpool para las peticiones hasta que el nodo recupera (es normal si queréis tener consistencia en los datos, que de eso va esta movida), como tenías chorrocientas idles esperando, pcp no recupera hasta que esas idles no terminan. Aquí entra en juego el parámetro “client_idle_limit_in_recovery” que cortará todas las idles en un máximo de 10 segundos (en mi caso, que si sois valientes deberíais de poner vuestro tiempo idle medio). Pero ojo. Hay persistentes en transacción que puede que no sean cortadas o que puede que sean cortadas pero originen errores. Lo más recomendable es parar vuestra WEB (y aquí está la mentira cazada, hay downtime), cortar a mano las idles y aseguraros de que no tenéis a nadie pidiendo nada. Pero bueno, todo dependerá de vuestro caso concreto y de lo osados que seáis.
Si no tenéis persistentes abiertas y todo va como debe y de verdad de deporte, recuperará el nodo correctamente.
Y por hoy, amigos, esto es todo. Espero que estas aclaraciones os sirvan de algo.

Ethernet bonding

¿Tienes una máquina cualquiera, servidor, pc-doméstico y/o lavadora por red con dos interfaces ethernet y solo usas una?


Hazle bonding, que está feo que coja polvo el conector de red… ¿no?

Además, es sencillo. Hasta Paquirrín podría hacerlo.

¿Qué es el bonding de ethernet?

Pues bien, grosso modo, consiste en balancear una conexión de red por ethernet en dos tarjetas de red físicas. Cada una con su MAC. Convirtiéndolas en una sola interfaz con una sola MAC que se autogestiona y redirecciona la conexión por la que más le convenga o, en el caso de que ocurra, por la que no esté rota. Nos da protección ante rotura de una de las dos tarjetas y minimizamos así las posibilidades de quedarnos sin red en un servidor. Si queréis saber más, aquí en la Wikipedia hay más.

Al turrón:

Supongamos que tenemos dos interfaces, llamadas eth0 y eth1.
1.- Instalamos ifenslave con apt (recordad que en este blog todos los ejemplos son en Debian, pero os podéis apañar en otras distros)

apt-get install ifenslave

2.- Creamos el fichero bonding.conf en /etc/modprobe.d, añadimos estas lineas en él y lo cargamos:

alias bond0 bonding
options bonding mode=active-backup miimon=100 downdelay=150 updelay=150

3.- Modificamos /etc/network/interfaces para que quede de forma similar a esta, eliminaremos la configuración de eth0 y eth1 y la sustituiremos con esta pero con vuestra configuración particular (En el ejemplo la red es 192.168.1.0):

# The loopback network interface
auto lo bond0
iface lo inet loopback
# The primary network interface
allow-hotplug eth0
allow-hotplug eth1
iface bond0 inet static
    slaves eth0 eth1
    address     192.168.1.2
    netmask     255.255.255.0
    gateway     192.168.1.1
    network     192.168.1.0
    broadcast   192.168.1.255
    bond_mode active-backup
    bond_miimon 100
    bond_downdelay 150

4.- Si no estamos delante del servidor de forma corpórea tendremos que llevar cuidado en cómo ejecutamos el paso de reiniciar la red. Lo recomendable si no estamos físicamente presentes es levantar primero la interfaz bond0 con:

ifup bond0

Y después tiramos abajo eth0 y eth1:

ifdown eth0
ifdown eth1

Pero si estamos presentes (y no es un servidor en producción en el que se está trabajando, claro), es mejor tirar abajo networking:

/etc/init.d/networking stop

Y levantarlo:

/etc/init.d/networking start

5.- Comprobaremos que todo está correcto:

ifconfig
bond0     Link encap:Ethernet  HWaddr f0:1f:af:d3:48:a8
          inet addr:192.168.1.2  Bcast:192.168.101.255  Mask:255.255.255.0
          inet6 addr: fe80::f21f:afff:fed3:48a8/64 Scope:Link
          UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
          RX packets:29648237 errors:0 dropped:2523856 overruns:0 frame:0
          TX packets:30004957 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:20909383227 (19.4 GiB)  TX bytes:31281472852 (29.1 GiB)
eth0      Link encap:Ethernet  HWaddr f0:1f:af:d3:48:a8
          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
          RX packets:26476124 errors:0 dropped:0 overruns:0 frame:0
          TX packets:30004957 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:20383770558 (18.9 GiB)  TX bytes:31281472852 (29.1 GiB)
          Interrupt:16
eth1      Link encap:Ethernet  HWaddr f0:1f:af:d3:48:a8
          UP BROADCAST RUNNING SLAVE MULTICAST  MTU:1500  Metric:1
          RX packets:3172113 errors:0 dropped:2471750 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:525612669 (501.2 MiB)  TX bytes:0 (0.0 B)
          Interrupt:17
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:1606767 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1606767 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:438725905 (418.4 MiB)  TX bytes:438725905 (418.4 MiB)

Fijaos que todas las interfaces tienen la misma MAC y que eth0 y eth1 rezan “UP BROADCAST RUNNING SLAVE MULTICAST”.
Con esto ya dispondríais de bonding y podéis enchufar las dos interfaces de red físicas a vuestra red.

Nueva vida, nuevo blog. Eso dicen, ¿no?

Nueva vida, nuevo blog. Eso dicen, ¿no?

Pues creo que no… pero a mi me ha venido cojonudo para empezar. Porque empezar siempre es jodido, amigos. Y recientemente he empezado un montón de cosas. Mi intención es escribir algunas de esas cosas o historias, aquí. También, de paso, compartir conocimiento técnico. Me dedico a la administración de sistemas. Sin querer, llevo más de cinco años en ello pese a que mi formación original no iba encaminada a esto. Cosas que pasan.

Hace unas semanas, en una “conversación de frikis“, surgió comentar sobre “esas personas que diseñan sistemas cojonudos o programan cosas putamadre pero no las comparten con los demás”. Eso sumando a que, normalmente, hay poca documentación de sistemas en castellano (y cuando digo castellano, me refiero a legible y entendible, no al idioma solamente) me hizo pensar que, ¿por qué no?, yo podría aportar aunque fuese un pequeñísimo grano de arena al inmenso desierto por el que caminamos día a día los administradores de sistemas. Ese limbo de incomprensión entre usuarios y desarrolladores. Que poético me ha quedado eso último. Olvidadlo.

En realidad, los blogs son para rajar. De toda la vida. Eso es así. Así que me veréis rajar. Que yo antes era mucho de eso, luego perdí esa maravillosa costumbre. Como perdí la bella costumbre de ser BOFH. Pero claro, esa costumbre la perdí cuando dejé mi anterior trabajo. Iba de la mano. Esto me sirve como pie introductorio a mi siguiente historia.

Fui cuatro años y nueve meses administrador de sistemas Windows y estuve a cargo de unos 140 lusers y de unos 20 usuarios normales. También tuve la ocasión de coincidir con una rareza en la especie, un LOFH. Pero esa es otra historia que ya contaré. En ese tiempo aprendí mucho, sobre todo aprendí como no hacer las cosas. Aprendí que para hacer cualquier mierda con Windows necesitas tener panoja a espuertas. Aprendí lo que se sufre sin un entorno de pruebas virtualizado, aprendí lo que se sufre cambiando cosas a pelo en producción y aprendí cómo vivir con servidores que por la edad que tenían bien podrían haber hecho la comunión hacía ya unos años. Y aprendí también a dormir por las noches ante semejante panorama.

De repente un día mi vida giró. En parte por azar, en parte por voluntad propia y en parte por decisiones de terceras personas. Lo pasé mal, como le pasa a mucha gente muchas veces en su vida y luego apareció ella. No sé si sabéis eso que ocurre cuando conoces a una persona que te hace querer ser mejor, mejor de lo que hubieras querido ser por ti mismo. Pues eso me ocurrió a mi. Y me dio el punto de confianza que necesitaba para buscar otro trabajo mejor, que me gustase más, que me sirviese para algo. Lo encontré y ya no tengo que ser un BOFH. Ahora trabajo con Linux. Y los usuarios son normales, y saben usar Excel y no me piden que les sume dos columnas de números para ese informe que tienen que presentar al jefe en cinco minutos. Y tampoco me preguntan por donde se le pone la cola a un puzzle. Ni me amenazan con el despido si no les digo bien como se aplica la cola. Ni soy el consultorio de reparación de ordenadores de casa por telepatía. Ya no me siento como Wardog.

Y un poco de eso va esto. De ir compartiendo mis conocimientos. Los que ya tenía y los que voy adquiriendo. Y os contaré historias graciosas que me pasaron o que me pasan ahora. Y os hablaré más de ella. ¡Ah!, y de running. Que también me dio hace año y medio por eso de correr. De los #hijosdelrunning, mis compañeros de fatigas. Nunca mejor dicho.

Así que, nada. Espero que este blog sirva de algo para alguien. Ya sea runner, no runner, sysadmin o no… o para que os echéis unas risas conmigo o de mi.