sysadmin

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:

Anuncios

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.

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

Recientemente he profundizado en la instalación y puesta en marcha de pgpool-II. Y, por lo que he visto en Internet, en mi opinión, la documentación no acaba de quedar clara en algunos puntos. Me ha tocado pelearme bastante con ello y, por eso, voy a publicar un modesto “manual” basado en la configuración real que he realizado yo. Compilando información de un montón de sitios pero, principalmente, siguiendo esta guía (bastante completa solo que ambigua en algunos puntos).

Todos los scripts y ficheros de configuración mencionados en esta entrada están disponibles aquí.

Antes de empezar


En mi caso he instalado y configurado pgpool-II en dos servidores físicos. Aunque previamente configuré una maqueta con máquinas virtuales. La configuración es independiente del escenario que elijáis, siempre que sean servidores y no lavadoras, claro. Como ejemplo usaremos:

  • master.eltioemil.com -> 192.168.1.2
  • esclavo.eltioemil.com -> 192.168.1.3
  • pgpool.eltioemil.com -> 192.168.1.4

Lo más sencillo para juguetear es que añadáis los datos anteriores al fichero /etc/hosts de vuestras máquinas. Si pretendéis utilizarlo en un entorno serio o, ¿qué se yo, en producción?, convendría que utilizarais bind o cualquier tinglado de resolución de nombres, en mi caso uso bind. Como sistema operativo se ha utilizado Debian 7.1 en ambos nodos. Locales en en_US.UTF-8 por necesidades especificas de mi entorno, aunque de igual manera, como si lo ponéis en Chino. Funciona prácticamente igual con cualquier distribución de Linux normal, y seguramente con alguna no tan normal… Cada cual con sus manías.

Para los scripts que usaremos más adelante necesitaremos las siguientes herramientas. Instalaremos las que nos falten:

apt-get install ntp openssl file psmisc sysstat bzip2 unzip nmap dstat rsync wget ccze tcpdump pciutils dnsutils host

Lo primero que haremos, por organizarnos, es instalar postgreSQL 9.3, en mi caso (O la versión que queramos por encima de la 8.2, que está descontinuada y, ¿por qué la usaríais teniendo la 9.3 y casi la 9.4?). Pero os recomiendo esta versión puesto que los amiguetes de postgreSQL le han dado un buen empujón a las últimas dos versiones en cuanto a prestaciones. Para ello, después de añadirnos los repositorios de postgreSQL que están en su weben ambos nodos realizaremos lo siguiente:

apt-get update
apt-get install libpq-dev postgresql-server-dev-9.3 bison build-essential
apt-get install postgresql-9.3 postgresql-contrib-9.3 postgresql-doc-9.3 uuid libdbd-pg-perl

Esto nos dejará en cada nodo una instalación funcional de postgreSQL a la que haremos unas pequeñas modificaciones básicas en la configuración (Ya nos encargaremos de afinar el rendimiento cuando la empecemos a usar en serio). En ambos nodos he optado por guardar las bases de datos en un directorio llamado /data por cuestiones de arquitectura de hardware, en dicho directorio monto un RAID 1 de discos SSD para que la escritura vaya fina, fina. Modificaremos en la configuración de postgreSQL (Ubicada en /etc/postgresql/9.3/main/postgresql.conf) el siguiente valor:

#——————————————————–
# FILE LOCATIONS
#——————————————————–
# …

data_directory = ‘/data’

# …

El resto de valores que modificaremos serán comunes a todos los nodos, dejando en el esclavo el directorio data por defecto. Solo modificaremos esto de momento.

listen_addresses = ‘*’

Crearemos el usuario pgpool2:

su – postgres
createuser –superuser pgpool2

Editaremos ahora el fichero /etc/postgresql/9.3/main/pg_hba.conf y añadimos el acceso para todos los usuarios en el segmento de red (si vamos a utilizar esto en un entorno de producción tendremos que limitar el acceso solo a los nodos y a los usuarios que utilicemos, ya sea postgres o pgpool2):

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             postgres                                peer
local   all             all                                     peer
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5
host    all             all             192.168.1.1/24        trust 

Ahora vamos a configurar write ahead log, editamos de nuevo /etc/postgresql/9.3/main/postgresql.conf y cambiamos los siguientes parámetros:

archive_mode = on
archive_command = ‘exit 0’
wal_level = archive

Y creamos el siguiente directorio en ambos nodos:

mkdir –mode=700 /data/pg_xlog_archive
chown postgres:postgres /data/pg_xlog_archive

Reiniciamos PostgreSQL para activar los cambios:

/etc/init.d/postgresql restart

Una vez instalado y configurado postgreSQL en ambos nodos. Instalamos pgpool2 solamente en el nodo maestro (master.eltioemil.com). Lo descargamos de la web en /opt (hemos instalado la versión 3.3.1), lo descomprimimos y lo instalamos:

./configure –prefix=/opt/pgpool2
make
make install
cd /opt/pgpool-II-3.3.1/sql/pgpool-recovery
make
make install
su – postgres -c “psql -f /usr/local/src/pgpool-II-3.1/sql/pgpool-recovery/pgpool-recovery.sql template1”

Con esto configuraremos la aplicación en el directorio /opt/pgpool2 para su instalación. Después, creamos un template con las propiedades de replicación y recuperación que heredarán el resto de bases de datos.

Vamos a configurar pgpool2 en el nodo maestro. Copiamos el fichero /opt/pgpool2/etc/pcp.conf del repositorio y generaremos una clave para el usuario root con el siguiente comando:

/opt/pgpool2/bin/pg_md5 -p
password:
1dd0e5bfc954bc46fe800952be7e2a69

Editaremos el fichero y colocaremos esa linea “root:1dd0e5bfc954bc46fe800952be7e2a69” en lugar la que se encuentra en el fichero del repositorio. (Evidentemente con vuestra propia clave y no con esta que os invito a que le hagáis un reverse md5 lookup 😉 ).

Copiaremos /opt/pgpool2/etc/pgpool.conf el cual se encuentra aquí para el nodo maestro. Os aconsejo explorar todas las carpetas del repositorio. Disponéis de las configuraciones para maestro y esclavo.

Nos copiaremos también del repositorio el script de inicio, personalizado para este ejemplo (abridlo y echadle un vistazo) y lo añadiremos al arranque. Modificaremos :

update-rc.d pgpool2 defaults

Si podemos, reiniciaremos para comprobar que arranca correctamente. Y pediremos un status del script para comprobar que todo funciona correctamente.

Si lo hemos hecho bien deberá mostrar algo así:

root@master:~$ /etc/init.d/pgpool2 status
Status of pgpool-II:
/usr/bin/psql -h master.eltioemil.com -p  9999 -U pgpool2 -d postgres -c ‘show pool_nodes’
 node_id |    hostname     | port | status | lb_weight |  role
———+—————–+——+——–+———–+——–
 0       | 192.168.1.2 | 5432 | 2      | 0.500000  | master
 1       | 192.168.1.3 | 5432 | 2      | 0.500000  | slave
(2 filas)

El status debe de ser 2 para asegurarnos de que esta en modo de replicación y balanceo. 

Si es 3 significa que no está conectado el nodo al pool.

Si queréis saber más de esto, os leéis la documentación oficial de pgpool que ahí os contarán hasta lo que han desayunado.

Con esto dispondremos de replicación (podemos realizar las pruebas propuestas en la guía que hemos ido siguiendo para comprobar que todo funciona como debe).

Recuperación en linea


Lo primero que haremos, puesto que lo necesitaremos para mandar comandos por ssh, es añadir las claves publicas de un nodo en otro y viceversa. De este modo podrán acceder de forma segura entre ellos. Si no hacemos esto, no podremos levantar postgreSQL de un nodo en otro.

Cambiaremos en la configuración de postgreSQL del nodo maestro la siguiente información:

archive_command = ‘exit 0’

por

archive_command = ‘/bin/cp %p /data/pg_xlog_archive/%f’

Y recargaremos postgresql (reload) en ambos nodos.

Hay un script que se llama wal_archiving (es distinto para cada nodo) que cambia automáticamente estos valores en la configuración de postgreSQL. Lo usaremos más adelante puesto que los pasos a seguir ante la caída de un nodo son el de activar wal_archiving, realizar la recuperación y volver a desactivar wal_archiving. Lo copiaremos en /etc/init.d y lo invocaremos mediante los comandos start, stop y status.

En la guía están bien explicada la configuración necesaria para realizar la recuperación en línea. Hay una serie de scripts pero no son exactamente los que hemos usado, los hemos adaptado ligeramente a nuestra maqueta. Están todos en el repositorio, en la carpeta data_scripts. Deben de estar en el nodo que tenga pgpool instalado, en la carpeta /data. Aunque, si configuramos en el futuro la alta disponibilidad, deberán estar en ambos, pero eso ya lo veremos. Nos aseguraremos de que los permisos son de ejecución y para el usuario postgres.

Ante la caida del nodo esclavo lo primero será activar el archivado:

/etc/init.d/wal_archiving start

Seguidamente invocaremos el siguiente comando (que realizará automáticamente los tres pasos descritos en la guía):

/opt/pgpool2/bin/pcp_recovery_node 5 master.eltioemil.com 9898 root 1

Desactivaremos el archivado si todo ha ido como debe:

/etc/init.d/wal_archiving stop

El comando pcp_recovery_node encadenará una serie de pasos implicando los scripts que hemos copiado en /data con los parámetros adecuados. Si se ha escrito algo en la base de datos mientras el nodo estaba caído, lo rescatará y lo copiará en la base de datos esclava para evitar incoherencias en los datos. Es capaz de levantar el servicio postgreSQL y añadir el nodo al pool de pgpool. Para más detalle de esto, la guía. Si la falla consiste en un apagado físico de la máquina no podrá hacer nada, evidentemente, hasta que la levantemos.

Lo siguiente que vamos a intentar configurar es la automatización de estos tres comandos, para que se ejecuten automáticamente ante la caída del nodo esclavo. Seguidamente intentaremos configurar la alta disponibilidad para que puedan caer indistintamente ambos nodos y no se pierdan datos.

Alta disponibilidad


Para la alta disponibilidad necesitaremos, antes que nada, instalar pgpool2 en todos los nodos. En nuestro caso, en esclavo.eltioemil.com

Simplemente cambiaremos algunos valores (el concepto es “instalarlo a la inversa”) en el fichero pgpool.conf del nodo esclavo.eltioemil.com:

# – Backend Connection Settings –
backend_hostname0 = ‘192.168.1.3’
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = ‘/data’
#backend_flag0 = ‘ALLOW_TO_FAILOVER’
backend_hostname1 = ‘192.168.1.2’
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = ‘/data’
#backend_flag1 = ‘ALLOW_TO_FAILOVER’
# …
pgpool2_hostname = ‘esclavo’


Configuración de heartbeat


En mi caso particular, mis dos servidores tienen bonding. ¿Qué es lo que es?, pues esto. Voy a explicarlo aquí como si tuvieramos una sola tarjeta de red, pero voy a copiar un ejemplo de como se haría en bonding por si a alguien le viene bien. De todas formas es muy sencillo. Pero como siempre me quejo de que en la documentación de internet se dan cosas por supuestas, no voy a ser hipócrita y lo voy a ejemplificar.

Como se explica en el guión, heartbeat se sirve de una IP de servicio sobre la IP real de los nodos. De modo que para quien tenga que usar el clúster (Nuestros amigos los devops o los developers más osados) solamente tendrán que dirigirse a esta IP de servicio puesto que a ellos les da igual cuantos nodos hay detrás, como balancean o si son un señor de Cuenca. Por tanto, en cada nodo, tenemos que crear dicha IP que heartbeat gestionará.

Como hemos dicho, el guión que hemos seguido no contempla que tengamos bonding en las tarjetas de red, como es nuestro caso, para configurar heartbeat. Pero no difiere mucho crear una IP de servicio aunque tengamos un bonding. Después de instalar heartbeat, antes de configurarlo, pararemos la red y modificaremos el fichero /etc/network/interfaces de una forma similar a esta (Ojito con parar networking si estamos conectados remotamente, amigos)

# 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
iface bond0:0 inet static
    address     192.168.1.4
    netmask     255.255.255.0
    network     192.168.1.0
    broadcast   192.168.1.255

Simplemente hemos añadido una interfaz bond0:0 en lugar de la eth0:0 que propone el tutorial. Pero es lo mismo.

Con eth0 quedaría así:

# The loopback network interface
auto lo
iface lo inet loopback
# The primary network interface
auto eth0
iface eth0 inet static
    address 192.168.1.2
    network 192.168.1.0
    netmask 255.255.255.0
    gateway 192.168.1.1
iface eth0:0 inet static
    address 192.168.1.4
    network 192.168.1.0
    netmask 255.255.255.0
    broadcast 192.168.1.255

Así que lo podéis hacer como queráis. Esto es una mera cuestión de red, vamos al lío.

Antes de nada, modificaremos la configuración de pgpool para que en lugar de escuchar en todas las interfaces, solamente escuche en la IP de servicio:

# Pasará de ser así
listen_addresses = ‘*’
# A ser así
listen_addresses = ‘192.168.1.4’

Instalaremos heartbeat (apt-get install heartbeat). 

Una vez instalado encontraremos los ficheros de configuración de Heartbeat en /etc/ha.d. Necesitamos crear tres ficheros que normalmente están en /usr/share/doc/heartbeat como samples, pero que tenéis en el repositorio con las modificaciones pertinentes hechas.

  • ha.cf: fichero de configuración principal. Disponible aquí 
  • haresources: fichero de configuración de recursos. Disponible aquí
  • authkeys: información de autenticación. Disponible aquí. Generaremos el password que nosotros queramos.

CUIDADO: Modificaremos en ha.cf el nombre de la interfaz de red según corresponda. Como hemos explicado, si usamos bonding o no, o nuestra interfaz se llama pepito0.

También añadiremos esto al fichero /etc/hosts si no estamos usando otra cosa para resolver nombres:

192.168.1.1   router
192.168.1.2   master.eltioemil.com        master
192.168.1.3   esclavo.eltioemil.com       esclavo
192.168.1.4   pgpool.eltioemil.com        pgpool

El fichero haresources tiene diferencias con respecto al propuesto en el tutorial. Puesto que las versiones de heartbeat utilizadas en dicha guía son distintas a las utilizadas por nosotros. Debemos de especificar la dirección IP de servicio con mascara de subred (/24) y nombre de la interfaz de red. Por tanto será distinta en función de nuestra interfaz de red.

También difiere el link simbólico a realizar en /etc/ha.d/resource.d. Que será así:

ln -s /etc/init.d/pgpool2

El resto de pasos serán igual que en la guía. Se han copiado los ficheros de configuración finales después de configurar heartbeat. Por ejemplo el script de init de pgpool tiene variaciones en la opción status. Ya que apuntamos a la dirección IP de servicio y no a la del nodo en sí.

El fichero /etc/logd.cf no presenta ninguna diferencia con el propuesto en el tutorial.

Con esto, si todo ha ido bien, dispondréis de un clúster de postgreSQL que presenta ciertas ventajas con respecto a otras opciones. Al que añadir nodos es facilisimo, es un proyecto vivo que está avanzando bastante y muy estable. En el futuro iré afinando la configuración del mismo y veremos como rinde en producción.

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.