Autor: uncleemil

Yosemite, Linux y rEFInd en un Macbook pro viejuno (Update)

Pues resulta que al final sí que le compraron un Macbook nuevo al autor de rEFInd… no, en realidad no lo se, puede ser. O puede que se lo comprara él o se lo dejase un amigo. Sea como sea, la nueva versión de rEFInd hace lo que os comentaba en el post anterior, pero ella solita. Así que ya podéis disfrutar con normalidad de vuestro arranque dual.

Se puede descargar de aquí y es JRATIS. Pero el hombre acepta donaciones, las cuales, recomiendo que hagais aunque sea de dos euretes. Que os gastáis más en chorraditas.

Saludos, amigos.

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.

Google es satán o regenerar el directorio de data de postgreSQL sin reinstalar

Una hora buscando una chorrada que, porque hoy tenía el cuerpo así, no conseguía recordar. Y nada, buscando:

Regenerate data folder on postgresql, corrupted postgresql data directory fix, how to restore a corrupted postgresql installation… y así innumerables veces. El PUTO google me llevaba todo el rato a páginas de LUSERS de mierda cuya magnifica solución para el asunto era un apt-get –purge remove.

Aplausos, campeones.

Pues bien, para aquellos a los que también os irrita el auge de los retrasados mentales en internet y tengáis mala memoria como yo, aquí os recuerdo como se practica algo tan sencillo:

Asumo que hacéis backups de vuestras bases de datos. Y que sois limpios y aseados.

Copiáis vuestros scripts maravillosos que podáis (o no) tener en vuestro data de postgres para no perderlos en otra parte. Ejecutáis:

rm -rf <VUESTRO DIRECTORIO DE POSTGRES DATA>/*

En mi caso:

rm -rf /var/lib/postgresql/9.3/main/*

Lo dejáis limpito como una patena. Y ahora ejecutais:

<PATH DE VUESTRO BIN DE POSTGRES>/initdb <VUESTRO DIRECTORIO DE POSTGRES DATA>

En mi caso:

/usr/lib/postgresql/9.3/bin/initdb /var/lib/postgresql/9.3/main/

Y ya está, ya tenéis un data fresquito y limpito para volver a hacer el punki. Ya váis restaurando vuestros backups y, por vuestro bien, espero que esto solo os pase en entornos de testing, como a mi.

Elecciones Europeas de 2014. Mis conclusiones.

Hola amigos. Ya sé que el propósito de este blog era hablar de sistemas y de running. De vez en cuando alguna opinión, pero lo justo. Pero quiero hacer una pequeña excepción con este tema meramente político, por justicia. Y, vaya, para que se me entienda.

Dejar claro, primero, que yo no he votado estas elecciones europeas (y casi me cuesta el divorcio :P). Mis motivaciones eran principalmente el desencanto con la clase política en general, el no estar de acuerdo con un sistema electoral de lista cerrada, ver un hemiciclo lleno de sinvergüenzas; pero ojo, no solamente los corruptos. Indignarme viendo como se unen todos, se ponen de acuerdo, en votaciones como la de bajarse los sueldos (y votan no), o cosas que les tocan directamente a ellos. La clase política. O como se va a poner de moda ahora, “los partidos de la casta”. Como resultado pensé que sería bueno experimentar el sentir de una persona desengañada. Como el 55% de los españoles que no votaron. Ver qué ocurre después, cuando ocurre el proceso electoral. Sacar conclusiones.

Mis pensamientos de partida eran de tono pesimista. Pensaba que igualmente, votásemos o no, todo iba a seguir igual. PPSOE con la mayoría, una merienda de negros. La izquierda dispersa, como siempre. El pueblo, atontado, como siempre.

Anoche me di cuenta de que me equivocaba bastante. Supongo que con matices. Pero que me equivocaba. O eso creo ahora. Que el pueblo no parece estar tan atontado como yo creía, ni la izquierda tan dispersa después de todo. Que yo debería de haber votado a Podemos (que era mi idea original). Que el pueblo responde, aunque lentamente. Pero que parece verse, dentro de este sistema electoral de mierda, algo de luz en la mente de las personas. Al menos.

Todo esto no cambia el sistema electoral de mierda. Todo esto no cambia los sueldos que se llevan muertos esta “casta” política. Que todo lo hacen por y para ellos mismos. Salvando a cuatro que parecen tener buenas intenciones (que ahora deben de demostrar con hechos). Y, bueno, más que nada; me hace recobrar un poco la fe en las personas. En la clase política no, claro está, pero creo que podemos excluir del grupo “personas” a la clase política puesto que ni ellos mismos se consideran iguales a las personas.

Si todo esto al menos sirve para meterle un poquitito de miedo en el cuerpo a algunos. Esos que quieren controlar todo lo que no controlan para dormir tranquilos. Lease twtter, partidos políticos minoritarios que de momento no se venden, derechos fundamentales como el aborto, la (des)educación, etc… pues ya me daré por satisfecho. Me gustaría ver que esto va a más, me gustaría ver este mismo resultado en las elecciones nacionales, me gustaría ver como los partidos del pueblo crecen. Y no solo eso, aunque esto ya es soñar, me gustaría ver como esos partidos del pueblo crecen lo suficiente como para arrebatarles el control a los que puso Franco a dedo, que ahí siguen. Y que se acaben las pensiones vitalicias para los que no las merecen, que se acaben las dietas de más de quinientos mil euros al año para esos mangantes que no tienen la decencia ni tan si quiera de ir a trabajar. Que se acabe la lista cerrada, que se acabe la falsa democracia esta que tenemos y que, ya me vengo arriba. Se termine la monarquía farolera esta que tenemos. De corruptos, también. Ladrones de casta.

Pero bueno. Hay que ir paso a paso, de momento, este primer paso no parece malo. Parece que hay al menos unos cuantos millones de españoles a los que no les gusta que les hagan comulgar con ruedas de molino. Ojalá, repito, esto solo sea el principio de un cambio.

Pido disculpas a las personas, en general; por la arrogancia, por pensar que eran tontos y no iban a saber votar bien. Pido disculpas a aquellos que tienen un voto menos que podría haber sido uno más. Creo que votar sí sirve, aunque el sistema de voto no sea el mejor.

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:

El drama de pagar $0.99 USD

Algunos de vosotros estaréis un poco hartos de leer de manos de vuestros contactos en las redes sobre Whatsapp, Telegram, Facebook y Mark comprando Whatsapp; y la madre que los parió a todos. Yo estoy harto de leer sandeces. Alguna cosa leo medio coherente, pero en general, paja todo. No digo que esto que voy a escribir yo a continuación sea algo medio coherente, es una pequeña reflexión atentando a eso que hacemos tan poco. Recordar el pasado y ponernos en el lugar de otro.

Hace unos años, los creadores de Whatsapp pensaron que sería buena idea crear algo que mandase mensajes entre usuarios, basándose en la agenda del teléfono como un SMS cualquiera, pero a coste cero para el usuario utilizando la conexión de datos del mismo. Es una ideaca aquí y en Pekin. Y seguro que no fueron los primeros en pensarlo, pero sí los primeros con los suficientes recursos y experiencia previa para ponerlo en marcha. Y lo hicieron. Y lo hicieron GRATIS. Y de repente el mundo pasó de ser un lugar donde se mandaban e-mails y SMS a costes brutales por caracter a un lugar donde decir cualquier chorrada era gratis. Y no voy a entrar a hablar del deterioro de las relaciones humanas a partir de ese punto, no me corresponde. Pero, RECORDAD, estuvisteis mucho tiempo sin pagar por mensajes.

Estas personas, mejores o peores personas (no los conozco) invirtieron tiempo y recursos en montar una infraestructura que financiaron como pudieron pero sin pedirle dinero al usuario. Yo entiendo que no sabeis de informática, ni ganas que tenéis. Perfecto. Pero ya os digo yo que montar y mantener la infraestructura de algo tan sencillo aparentemente como Whatsapp no es moco de pavo. Se necesitan servidores, se necesita ancho de banda a cascoporro, se necesita almacenamiento, un lugar donde tener tantos servidores, electricidad suficiente como para abastecer tu casa durante años, etc. Y todo eso, se puso gratis ahí, para el que quisiera. Y nos tiramos todos de cabeza y tuvo éxito. Esa fue la moneda de cambio. Ellos querían éxito y a cambio nos dieron a millones de usuarios un sistema de mensajería bueno, bonito y GRATIS.

Y ahora tengo que sentarme delante del ordenador a leer vuestras gilipolleces de niñatos desagradecidos.

A todos nos gusta ganar dinero por nuestro trabajo, ¿verdad?. No creo que a ninguno de vosotros os sobre la pasta como para trabajar gratis. No creo que ninguno de vosotros hayáis montado sin cobrar al usuario una plataforma gratuita de mensajería, ni de nada. ¿A que no?. Pero os gusta vuestra nomina a final de mes, ¿a que sí?. Pues estas personas que montaron Whatsapp e intentaron que fuera gratis el mayor tiempo posible, llegado cierto punto, a lo mejor pensaron que tenían tantos usuarios que se hacía poco viable mantener esa infraestructura enorme gratis. O, ¿por qué no?, querían ganar más dinero porque, coño, se lo merecen. Y dijeron. Vamos a cobrar un misero dolar a cada usuario, una única vez por dispositivo; que para el  usuario no es nada, pero a nosotros multiplicado por millones, nos viene muy bien para seguir manteniendo el chiringuito abierto.

¿Qué dices?, loco. El apartheid.

Ya estabais ahí todos indignadísimos, buscando alternativas. Apelando a la burda demagogia barata del “es que no es seguro”. Escusas baratas de todo tipo para no pagar un misero dolar a unas personas que han trabajado muy duro para que no tengáis que mandar SMS’s. Qué malas personas, qué egoistas, querer cobrar por su trabajo. Me cago en la puta, el mundo está lleno de personas malas que solo quieren verlo arder. Que son ricos, por ende, deben de pagar nuestra afición a molestar  con mensajes estúpidos a nuestros amigos en desmesura. Claro que sí.

Por eso digo que las cosas que leo al respecto me parecen memeces. No porque no contengan sentido. Es que, de base, son memeces.

Y el problema es que no sabemos ponernos en el lugar del otro. Y mucho peor, no tenemos ni idea de la infraestructura que hay detrás de algo así; pero opinamos de lo que no sabemos. Y se nos olvida el pasado cuando tuvimos que inventar un lenguaje comprimido de símbolos para decirlo todo en 160 caracteres y ahora, nos aburrimos, y mandamos una media de 20.000 caracteres gratis al día. Pero luego hay que entender las injusticias del primer mundo.

Y voy a terminar esto, como siempre, como todo. Aprovechando que os importa tanto que Mark haya comprado Whatsapp y os preocupe tanto que os espíe personalmente. Nadie os obliga a utilizar Facebook, nadie os obliga a comprar Whatsapp y nadie os obliga a nada salvo la presión social y el miedo ese que tenéis a la desconexión social. Podéis, tranquilamente, daos de baja de todas estas cosas y seguro que así vuestra maravillosa privacidad seguirá virgen, impoluta. Vuestras importantes actividades secretas a salvo. Vuestras fotos de las vacaciones, de lo que habéis comido ese día; vuestros absurdos motivacionales y todo lo demás. Y otra cosa más. Ni a Mark ni a mi nos importan una puta mierda vuestros datos publicados por vosotros con vuestro consentimiento en Facebook. Podéis dormir tranquilos.

No paguéis el dolar, de acuerdo. Pero por lo menos pensad un poco en el trabajo que hay detrás de todo esto. Porque no lo sabéis. Sois de esos que le pedís a vuestro primo el informático que os arregle las cosas gratis porque pensáis que nuestro trabajo no vale nada. Que no cuesta. Pues si no cuesta, adelante, que yo os pagaré gustosamente ese dolar.

ERROR: Message hist queue is filling up

Un error de heartbeat, genérico, aunque a mi personalmente me afecta en el tema de pgpool, ya que tengo un pgpool en alta disponibilidad con heartbeat. Al intentar añadir un tercer nodo, pues lo tipico, como la configuración de heartbeat es idéntica en todos los nodos, copias.

Erroooooor!

Por lo visto parece ser un bug, o no bug, no me quedó claro pero francamente no me apetecía seguir leyendo memeces en foros; en el que se conoce que si copias ficheros de configuración de un nodo a otro, mágicamente, la comunicación entre nodos deja de funcionar. De ahí que no se envíen correctamente los mensajes, de ahí que se llene la cola de mensajes.

En un primer momento pensé: firewall o similares. Así que el puerto que tengo configurado en mi ha.cf en heartbeat (que es UDP) lo abrí en todos los nodos, incluído en el que me daba problemas (yo que sé…). Pero nada, al cabo de un rato se vuelve a llenar la cola y en los logs, lloros. Seguí investigando. En mi caso estaba utilizando broadcast a lo loco para la comunicación entre nodos. Lo cual es guay y cómodo si tienes bien montada tu red. Leyendo, leyendo, encontré un artículo en el que hablaba de este mismo bug (no he podido volver a encontrar la fuente, así que no puedo dar crédito al logro. Espero que los Dioses de Internet sepan perdonarme). El colega sufría de la misma dolencia y, por el mismo motivo, copió los ficheros de un nodo a otro a lo loco pensando, ingenuo de él, que como eran iguales iba a dar lo mismo. Lo resuelve de una forma efectiva, segura pero poco eficiente o cómoda en el caso de que tu heartbeat controle muchos nodos. Esto es, unicast.

En tu ficherito de ha.cf te comentas la línea mágica y maravillosa que reza bcast a tu interfaz de red, en mi caso:

bcast bond0

Y la sustituyes por:

ucast bond0 <IP del otro nodo>

Y lo cruzas, es decir: En cada nodo haces lo mismo con el resto de nodos. Por eso digo que si tienes muchos nodos, es una mierda. O te lo curras a manija o te toca currarte un puppet o un rex o lo que sea que uses para automatizar. Que tampoco es un drama, pero semejante chorrada no debería de ocupar a nadie tanto tiempo.

Y así, sí. Así heartbeat decide que le gusta, que va a escuchar los mensajes de los otros nodos, porque el broadcast es muy mainstream. Su puta madre.

En próximas ediciones os contaré mis aventuras y desventuras con HAProxy, porque si va bien, le van a dar por culo a “jeartbit” pero muy rápidamente.

Hasta pronto, corazones.

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.