Archivos de Categoría: Sistemas

PostgreSQL en Debian: Actualizar el cluster

PostgreSQL es uno de esos servidores que imponen. Frente a la asequibilidad friqui de MySQL, perdón, MariaDB, PostgreSQL tiene un aire de señor trajeado con cara de pocas bromas. Pero funciona muy bien, que es lo que importa; y el empaquetado en Debian es, como de costumbre, impecable.

Una de las cosas que distinguen a PostgreSQL es que se toma muy en serio eso de las versiones. Tanto que es posible tener varias corriendo a la vez en un servidor sin más que instalarlas con su nombre (postgresql-13, por ejemplo) y ponerle un puerto a cada una en su fichero/directorio de configuración (/etc/postgres/13/main/postgresql.conf, por seguir con el mismo ejemplo).

Actualizar entre versiones puede hacerse a mano, claro. Pero hay una herramienta que viene con el servidor que lo hace todo, y generalmente bien: pg_upgrade.

¿Y cómo se usa pg_upgrade? Como es habitual, la documentación es extensa y explicativa, pero no cuenta el caso de uso más habitual para actualizar en cinco minutos. Que se resuelve de esta manera que sigue a continuación:

1. Parar los servidores:

sudo systemctl stop postgresql

2. Ejecutar la migración con pg_upgrade:

sudo su - postgres 
postgres@servidorimportantequetecagas:~$ /usr/lib/postgresql/versionnueva/bin/pg_upgrade -b /usr/lib/postgresql/versionantigua/bin -B /usr/lib/postgresql/versionnueva/bin -d /var/lib/postgresql/versionantigua/main -D /var/lib/postgresql/versionnueva/main -o ' -c config_file=/etc/postgresql/versionantigua/main/postgresql.conf' -O ' -c config_file=/etc/postgresql/versionnueva/main/postgresql.conf'

Se puede añadir -c al final, para que no haga la migración sino que se limite a ver si todo parece preparado.

3. Cambiar el puerto

Editar la configuración de los servidores, típicamente en /etc/postgresql/versionantigua/main/postgresql.conf y /etc/postgresql/versionnueva/main/postgresql.conf, y poner el puerto deseado en el nuevo, para que las aplicaciones conecten al cluster nuevo.

4. Hacer limpieza:

alfredo@servidorimportantequetecagas:~$ sudo dpkg --purge postgresql-versionantigua postgresql-client-versionantigua

5. Arrancar los servidores:

sudo systemctl start postgresql

Listo. Este sencillo procedimiento, funciona con casi cualquier pareja de versiones de PostgreSQL desde allá por la 9, hasta la actual.

Ya no hace falta la copia de seguridad recién sacada. Porque hay una copia de seguridad recién sacada… ¿Verdad?

ConnectX4 LX: Molan, hasta que se atascan

nVidia (nacida Mellanox) dice en sus notas de actualización de firmware que es un «rare case». Pero a todos nos mira un tuerto de vez en cuando, y ese día no fue de extrañar que un Dell r630 dejara de ver sus dos puertos SFP28 (en la tarjeta rNDC, pero esto es irrelevante; es PCIe, al fin y al cabo).

En lugar de los SFP28, nos gratificó con un arranque bastante lento y un críptico error en syslog:

mlx5_core 0000:01:00.0: mlx5_function_setup:995:(pid 252450): Firmware over 120000 MS in pre-initializing state, aborting
mlx5_core 0000:01:00.0: probe_one:1484:(pid 252450): mlx5_init_one failed with error code -16

Los dispositivos, en consecuencia, no aparecieron en el sistema operativo, convirtiendo este servidor en un nada práctico pisapapeles.

¿Y qué es lo que pasaba? Una bonita tarde de domingo escarbando (con el dueño del servidor cerca de un desfibrilador), reveló esta perla en las notas de versión del firmware:

- Fixed a rare case where the the device hanged while running the sw reset flow under heavy stress and with many open resources.

Bueno, no era mucho, pero tras haber rearrancado mil veces el servidor y hasta haberlo apagado y encendido, no quedaba mucho más que pudiera ser. Bien fuera este caso o un primo hermano, suele merecer la pena actualizar el firmware de los diferentes subsistemas: El mantenimiento de firmware suele consistir casi siempre en correcciones de errores, siendo la introducción de errores nuevos relativamente infrecuente.

Con Dell hemos topado

En general, Dell hace las cosas bastante bien y el Open Manage Enterprise, que permite actualizar firmwares sin dolor y masivamente, por sus muchos defectos, es una herramienta de lo más útil. Si el servidor en cuestión está integrado, claro. Lo cual no era este caso porque es un servidor de un cliente; y, para añadir insulto a la ofensa, ni la iDRAC, ni el lifecycle controller local veían posible actualizar el firmware. Decían que ese dispositivo no está en el sistema. Lo sabrán ellos.

Total.

  • Descargar las herramientas de gestión de firmware de nVidia;
  • Descargar el firmware de Dell para la tarjeta en cuestión;
  • Desempaquetar el firmware del putrefacto .EXE que suministra Dell (unzip es suficiente).
  • Averiguar gracias a lspci -vv cuál de los tres firmwares sin más explicación es el correcto para la tarjeta rNDC (lspci da el nombre de la pieza, que forma parte del nombre del archivo de uno de los tres .bin que el paquete de Dell incluye en payload/). Como para unas prisas:
# lspci -vv | grep PN
        [PN] Part number: 0R887V
        [PN] Part number: 0R887V
# ls networkfirmware900n0/payload/ | grep 0R887V
fw-ConnectX4Lx-rel-14_31_1014-0R887V-UEFI-14.24.13-FlexBoot-3.6.403.bin
  • Quemar
# flint -d 01:00.0 -i networkfirmware900n0/payload/fw-ConnectX4Lx-rel-14_31_1014-0R887V-UEFI-14.24.13-FlexBoot-3.6.403.bin b
  • Rearrancar el firmware
# mlxfwreset -d 01:00.0 reset

Y listo, a funcionar. Rearrancamos y actualizamos todo, ya que estamos, hacemos un bonito artículo por si alguien se ve en las mismas, y nos acabamos el café.

ix0: Unsupported SFP+ module detected!

Ya el año pasado, me tocó lidiar con la estúpida decisión de Intel de que sus chips de 10G no funcionan con los SFP que no entran en la corta lista de los que tienen probados.

La historia se repite, y esta vez ha sido un venerable FreeNAS 11.1 en un nuevo armario y con nuevos y flamantes cables AOC el que lleva el controlador de Intel que ha decidido, vaya hombre, que los AOC no son lo bastante flamantes; que si eso, que compre otros.

Uno no tiene tiempo ni ganas de dejarse llevar por las veleidades de una empresa que tiene gente trabajando en puestos que llevan a la vez la palabra technical y la palabra marketing (pobrecicos).

Usando la clásica técnica de poner en un buscador el mensaje de error que sale en dmesg y que da título a este artículo, en seguida se llega a algún ticket del redmine de IXsystems / FreeNAS; no en vano es uno de los mayores distribuidores de FreeBSD del momento.

El caso es que, como suele suceder, las cosas no pueden ser tan fáciles.

¿Es cierto que añadir a /boot/loader.conf las palabras mágicas:

hw.ix.unsupported_sfp=1

resuelve el problema? Si.

Pero no es menos cierto que en la versión 11.1, no. Vamos, lo ignora completamente en la versión que va en el kernel de la 11.1.

Así que, usando la clásica y probada por la experiencia técnica de la huida hacia delante, me bajé la ISO de la última estable de FreeNAS y le hice una actualización in situ. Las actualizaciones de FreeNAS son una gozada, si bien hacerlas sobre uno de esos KVM viejos de Supermicro no son la mejor experiencia del mundo. Pero en una máquina virtual Windows bien añeja (de Windows 7 para atrás) funcionan, así que no me voy a quejar demasiado. Total, hace años que por estas cosillas dejé de comprar Supermicro y pasé a comprar Dell.

Una vez hecha la actualización, arrancado el sistema nuevo, ya todo…

…Una mierda. Resulta que la actualización instala su propio /boot/loader.conf. Bueno, no pasa nada: Otra vez KVM basado en Java y volver a añadir hw.ix.unsupported_sfp=1 al final del ficherito.

Y esta vez sí, por fin, quejándose como un abuelo hablando de política en el bar del pueblo, por fin levantó los puertos de 10G. Y el resto, como se suele decir… Es historia.

Recuperando datos a lo bruto

Recuperar datos es una de esas actividades que consisten en un largo periodo de marrón, coronado (a veces) por un momento de euforia.

Vamos a correr un tupido velo sobre la historia que llevó al punto de partida de nuestro marrón de hoy. Describamos, simplemente, dicho punto de partida: Hay un contenedor OpenVZ corriendo en un servidor, en el cual «se» (¿no son utilísimos los reflexivos en las empresas?) ha hecho un DROP DATABASE seguido del nombre de una base de datos. Base de datos de la que no solamente no hay copia de los datos; sino que, puestos a giñarla, tampoco la hay de la estructura.

Así a primera vista, después de los preceptivos frontomanotazos y pelotiramientos, quedaron dos cosas claras:

  1. Para recuperar una tabla MyISAM (las InnoDB son otra historia), se necesitan al menos su .frm (estructura) y .MYD (datos propiamente dichos). Si solo se tienen los datos, ahí están, pero usarlos es un trabajo más bien de chinos.
  2. Cuanto más tiempo pase y más se escriba en el volumen afectado, mucho peor.

El primer intento, que tenía posibilidades de no haber pasado ya unas horas en un hipervisor un tanto activo, fue con ext4magic. Tiene su cosa, el asunto. Si el servidor se puede parar, es más fácil. Si no, hay que trabajar haciendo una copia del journal del sistema de ficheros, en este caso un ext4:

debugfs -R "dump <8> /root/copiadeljournal" /dev/mapper/pve-data

En este caso, almacenamos la copia del journal en /root, y el sistema de ficheros conteniendo lo que deseamos recuperar está en /dev/mapper/pve-data. Un Proxmox, como habrá adivinado ya el lector avezado.

Luego, burguesamente, podemos pedir a ext4magic que nos recupere todo lo del directorio en cuestión:

./ext4magic /dev/mapper/pve-data -j /root/copiadeljournal -f private/666/var/lib/mysql/pordiosmibasededatos -a $(date -d "-5day" +%s) -b $(date -d +%s) -R

En este caso, «666» es el identificador del contenedor. No es coincidencia; es que uno es así de paranoico filtrando lo que publica.

Pero claro… Si ha pasado tiempo, dependiendo de exactamente lo que se le pida, dice que el inodo ya está siendo reutilizado, o que simplemente aquello ya no ta.

Otro intento fue con testdisk. Testdisk es un gran invento, pero en este caso hubo el mismo problema: Había pasado demasiado tiempo. Mejor dicho: Demasiadas escrituras.

¿Qué hacer, qué hacer? El datario amenazaba alternativamente con suicidarse y con homicidar al causante del desaguisado; se seguían sucediendo el tiempo y las escrituras, y no estábamos más cerca de una solución que al principio.

Llamé a mi escriptillo, un tanto gráficamente, aladesesperada.sh. Era este:

#!/bin/bash

Bloque=0
 while [ $Bloque -le 157313 ]
 do
      echo " $Bloque "
      dd if=/dev/mapper/pve-data of=/root/tmp-$Bloque bs=10M skip=$Bloque count=1 status=noxfer > /dev/null
      grep -q 'cadenapeculiarquetepasas' /root/tmp-$Bloque
      if [ $? -eq 0 ]; then
     echo Encontrado algo
      else
     rm /root/tmp-$Bloque
      fi
      Bloque=$[$Bloque +1]
 done

No me darán un premio a la elegancia, pero esto es como funciona. El numerete es simplemente el tamaño de la partición donde estamos recuperando los datos expresada en cachos de 10 megas. Luego, simplemente vamos cogiendo cachitos de 10 megas en 10 megas y, si algún cachito contiene una cadena que sabemos que está en la base de datos, la conservamos. Si no, la borramos.

Luego hice una pequeña reforma que multiplicó por varias veces la velocidad de ejecución, usando un tmpfs:

mount -t tmpfs -o size=20m tmpfs /root/tmp

Y correspondientemente:

#!/bin/bash

Bloque=0
 while [ $Bloque -le 157313 ]
 do
      echo " $Bloque "
      dd if=/dev/mapper/pve-data of=/root/tmp/tmp-$Bloque bs=10M skip=$Bloque count=1 status=noxfer > /dev/null
      grep -q 'cadenapeculiarquetepasas' /root/tmp/tmp-$Bloque
      if [ $? -eq 0 ]; then
      mv /root/tmp/tmp-$Bloque /root/encontrado-$Bloque
      else
     rm /root/tmp/tmp-$Bloque
      fi
      Bloque=$[$Bloque +1]
 done

Con esto, vino uno de esos escasos y preciados momentos de suspiro: Aparecieron los datos. Al menos, la mayoría de ellos. Hubo que hacer varios intentos, concatenar varios cachos y recortarlos a base de dd, pero al final aparecieron.

Pero hay un problema, ¿no? ¿Qué hemos dicho sobre las tablas MyISAM?

al menos su .frm (estructura) y .MYD (datos propiamente dichos)

Total. Que necesitamos recuperar del disco unos .frm, que como cadena para buscar solamente tienen unos nombres de campo… Nada peculiares. Y encima, tienen un formato tirando a complejo y ni siquiera del todo bien documentado.

Así que, para esto, echamos mano del amigo de testdisc: Photorec.

Photorec es una pequeña maravilla de recuperador de datos. No poca gente debe algo parecido al perdón divino de su falta de copias de seguridad a esta utilidad escrita y mantenida desde hace muchos años por Christophe GRENIER. Photorec busca a lo bruto y recupera un montón de formatos de ficheros; entre ellos, los frm de MyISAM.

Dicho y hecho, una ejecución rápida de Photorec en el volumen pronto encontró varios archivos de MySQL. Varios. Unos pocos… Miles. Mêrde. Y ahora, ¿qué?

Pues se coge ./aladesesperada.sh buscando por los nombres de los campos (lo cual genera «solamente» unos cientos de ficheros de a diez megas), y seguidamente… Corremos photorec sobre la concatenación de todos esos ficheros.

Eso y un poco de recortes más con dd, algo de ensayo y error, y ¡por fin!. Poner los ficheros finales en /var/lib/mysql, usuarios, permisos, arrancar el servidor (no harás todo esto con el servidor MySQL andando, ¿verdad?), y no sin quejarse un poco…

mysql> REPAIR TABLE tablon USE_FRM;

+----------------+--------+----------+----------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+----------------+--------+----------+----------------------------------------------------------------+
| basedepatos.tablon | repair | info | Found link that points at xxxxx (outside data file) at yyyyy |

[…]

| basedepatos.tablon | repair | warning | Number of rows changed from 0 to 4711 |
| basedepatos.tablon | repair | status | OK |

Como dicen, el resto es historia: Intentar recoger los cachitos que faltan, y hacer un mysqldump final y largarlo al dueño, que ya a estas alturas estaba pensando en un duelo a pistola a tres pasos.

MacOS: Mola, salvo cuando se le va la pinza creando Preboots

Lo malo de solo tener un culo es que hay que aceptarlo como es, y el mío es inquieto. Vamos, que a media lectura de la página de Apple sobre las bondades de Catalina, ya mi culo estaba firmando que recaerá sobre mí y mi descendencia hasta la octava generación el karma por correr betas, y que bla bla bla aceptaryaleche.

Pero las cosas a veces van y otras veces se arrastran, y en mi caso el arrastre por todos los motores de búsqueda conocidos por el hombre empezó con un misterioso mensaje de error: Could not create a preboot volume for APFS install.

Por la Internet alante se encuentra todo tipo de recetas para salir de esa. Para variar, ninguna me funcionó. Pero salí de esa. ¿Cómo?

Observé que mi directorio /Volumes contenía una cantidad enfermiza de directorios cuyo objetivo en la vida, aparentemente, es montar el volumen Preboot:

alfredo@Alfredobot-274 /Volumes> ls

InstallESD    Preboot 18  Preboot 29  Preboot 4   Preboot 50  Preboot 61  Preboot 72  Preboot 83  Preboot 94

Macintosh HD    Preboot 19  Preboot 3   Preboot 40  Preboot 51  Preboot 62  Preboot 73  Preboot 84  Preboot 95

Preboot        Preboot 2   Preboot 30  Preboot 41  Preboot 52  Preboot 63  Preboot 74  Preboot 85  Preboot 96

Preboot 1    Preboot 20  Preboot 31  Preboot 42  Preboot 53  Preboot 64  Preboot 75  Preboot 86  Preboot 97

Preboot 10    Preboot 21  Preboot 32  Preboot 43  Preboot 54  Preboot 65  Preboot 76  Preboot 87  Preboot 98

Preboot 11    Preboot 22  Preboot 33  Preboot 44  Preboot 55  Preboot 66  Preboot 77  Preboot 88  Preboot 99

Preboot 12    Preboot 23  Preboot 34  Preboot 45  Preboot 56  Preboot 67  Preboot 78  Preboot 89

Preboot 13    Preboot 24  Preboot 35  Preboot 46  Preboot 57  Preboot 68  Preboot 79  Preboot 9

Preboot 14    Preboot 25  Preboot 36  Preboot 47  Preboot 58  Preboot 69  Preboot 8   Preboot 90

Preboot 15    Preboot 26  Preboot 37  Preboot 48  Preboot 59  Preboot 7   Preboot 80  Preboot 91

Preboot 16    Preboot 27  Preboot 38  Preboot 49  Preboot 6   Preboot 70  Preboot 81  Preboot 92

Preboot 17    Preboot 28  Preboot 39  Preboot 5   Preboot 60  Preboot 71  Preboot 82  Preboot 93

Y observé, en particular, que había hasta el Preboot 99. Ni uno más, ni uno menos. Así que, cabezazo a cabezazo contra la mesa, acabé por formular la hipótesis de que lo que el programa de instalación quería no era otra cosa que crear un punto de montaje nuevo para el Preboot. Aparentemente, si ya existe /Volumes/Preboot, intenta /Volumes/Preboot 1, y si no /Volumes/Preboot 2, etc… Hasta /Volumes/Preboot 99, y ahí lo deja por imposible. Pero, ¿acaso dice «Unable to create /Volumes/Preboot directory» o algo así clarificador? Noooo, esto lo ha hecho uno que viene de Microsoft, y lo que dice, que al traducirlo despista más todavía, es lo que se ve en el título.

Total. Que me los cargué todos, excepto el primero y el último, por si acaso. Innecesaria precaución: Tras instalar Catalina, no quedó ni uno. Y Catalina funciona, al menos lo bastante como para contarlo.

dehydrated y nginx

dehydrated es un cliente ACME escrito en bash.

Resulta extremadamente sencillo de montar y está empaquetado en Debian (desde jessie-backports en adelante), por lo que desplegarlo es trivial. Sin embargo, la documentación, aunque completa, es quizá algo confusa. Especialmente, considerando que lo que quiere hacer la mayor parte de la gente es obtener su certificado y olvidarse del asunto. Pues bien, esto se hace de la siguiente manera:

  1. apt-get install dehydrated
  2. echo «midominio.mitld» > /etc/dehydrated/domains.txt
  3. Configurar el servidor web
  4. Pedir el certificado
  5. Poner un cron que lo renueve periódicamente

Respecto al punto 3, esta es una configuración de ejemplo para nginx. La parte de SSL no funcionará hasta el final del proceso, por lo que hasta entonces no se puede introducir, o nginx no arrancará:

server {
 listen 80;
 server_name midominio.mitld;
 location /.well-known/acme-challenge {
 alias /var/lib/dehydrated/acme-challenges/;
 }
}

server {
 listen 443 ssl default_server;
 server_name midominio.mitld; 
 
 ssl_certificate /var/lib/dehydrated/certs/midominio.mitld/fullchain.pem;
 ssl_certificate_key /var/lib/dehydrated/certs/midominio.mitld/privkey.pem;
}

Esto puede ir en /etc/cron.monthly/renovar-certificado:

#!/bin/dash

/usr/bin/dehydrated -c && /usr/sbin/nginx -s reload

Y ya está. No hay más que ejecutar una vez /usr/bin/dehydrated -c para pedir el certificado, meter la configuración de ssl en nginx, recargar nginx, y listo.

Editado

  • 23 de Agosto de 2017: Mandar una señal reload a nginx: de lo contrario, no leerá el certificado renovado.
  • 28 de Febrero de 2022: Mejor configuración de SSL, eliminando el uso de ssl_trusted_certificate