martes, 5 de junio de 2012

Alineando las particiones de un volumen RAID 5

"DISK FAILURE IS IMMINENT!"

Este es el mensaje que me apareció recientemente mientras me encontraba trabajando tranquilamente en mi computadora. El mensaje apareció no una, sino en repetidas ocasiones en ventanas emergentes que poco ayudaban a controlar el pánico. Además de llenarnos de terror, este mensaje es un buen recordatorio de porqué debemos tener un buen sistema de respaldo. En mi caso, utilizo un conjunto de 4 discos de 1TB configurados en RAID 5. Esto me permite tener un nivel aceptable de redundancia, donde mis datos quedan intactos siempre y cuando solo falle un disco a la vez.

Después de cerrar todas las ventanas y desactivar futuras amenazas de muerte de datos, me puse a investigar el supuesto daño.

$ sudo smartctl --health /dev/sdb

smartctl 5.41 2011-06-09 r3365 [x86_64-linux-3.0.0-19-generic] (local build)
Copyright (C) 2002-11 by Bruce Allen, http://smartmontools.sourceforge.net

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: FAILED!
Drive failure expected in less than 24 hours. SAVE ALL DATA.
Failed Attributes:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  5 Reallocated_Sector_Ct   0x0033   023   023   036    Pre-fail  Always   FAILING_NOW 3168


Basado en mi experiencia, puedo decir que en este punto al disco le queda un lapso de vida de un día hasta 3 meses. Si, así de poco confiable es SMART, y así de impredecibles son los discos duros. Podría jugármela y esperar a que ese "Pre-fail" se convierta en muerte total, pero decidí mejor comprar un disco nuevo y quitarme este pendiente de una vez.

La conveniencia de tener un sistema RAID 5 también trae consigo algunas complicaciones, y fue con este nuevo disco que encontré una de ellas. Poco sabía que dentro del mundo de los discos duros existe un nuevo concepto llamado Advanced Formatting. En realidad el concepto solo es nuevo para mi, ya existía desde hace muchos años, pero fue hasta el 2011 cuando los fabricantes comenzaron a mudar la mayoría de sus discos a este formato. Básicamente, se trata de que antes se usaban discos duros con sectores de 512 bytes, y ahora se usan de 4096 para mayor eficiencia. Si te interesa conocer a detalle como funciona y las ventajas que Advanced Formatting otorga, este pdf de Hitachi es ampliamente recomendable.

Como era de esperarse, los discos que ya tenía, aunque los compré en el 2011, son de sectores 512 bytes. Por lo tanto, cuando intenté agregar el disco a mi arreglo usando Ubuntu Disk Utility, me tocó lidiar con mensajes como este:

WARNING: The partition is misaligned by 1024 bytes. This may result in very poor performance. Repartitioning is suggested.

¿Mal desempeño? ¡A nadie le gusta eso! Comprobé que efectivamente mi disco era uno de los nuevos:

$ cat /sys/block/sdd/queue/physical_block_size
4096

$ cat /sys/block/sdd/queue/logical_block_size
512

Al hacer la misma prueba con mis otros discos, el tamaño fue 512 en los dos casos. Esto empezó a preocuparme. Una alternativa era devolver este disco a Amazon y buscar alguna reliquia que funcionara con el tamaño antiguo, pero la realidad es que iba a tener que actualizarme eventualmente. ¿Sería posible agregar un disco con sectores de diferente tamaño a un volumen RAID existente?

La respuesta es que si, es posible, y la verdad es que esto poco tiene que ver con el problema de la partición mal alineada. El asunto aquí es que el Disk Utility esta intentando crear una partición basándose en los discos existentes, que tienen sectores de diferente tamaño. La solución es simplemente crear la partición manualmente utilizando gparted. Dado que RAID utiliza bloques mucho mas grandes (en mi caso de 64KB), lo único que importa es que el tamaño del bloque sea un múltiplo del tamaño de los sectores.

$ sudo gparted

Esta aplicación nos permite crear una nueva partición en el disco, y además alinearla por megabyte, no por cilindro como lo esta haciendo Disk Utility. Simplemente le ponemos que inicie en 1MB y termine en el máximo espacio disponible. Después nos vamos a "Manage Flags" y habilitamos la bandera de RAID. Con esto queda preparada nuestra partición para agregarla al arreglo utilizando mdadm:

$ sudo mdadm --add /dev/md0 /dev/sdd
$ sudo mdadm --detail /dev/md0
$ cat /proc/mdstat
md0 : active raid5 sdd[3](S) sdc1[0] sdb1[2] sde1[1]
      1953519872 blocks level 5, 64k chunk, algorithm 2 [3/3] [UUU]

Como podemos ver, nuestro nuevo disco ahora esta marcado como disco de reserva ([S]pare), y estamos listos para desactivar el disco moribundo:

$ sudo mdadm --manage /dev/md0 --fail /dev/sdb1
$ cat /proc/mdstat
md0 : active raid5 sdd[3] sdc1[0] sdb1[4](F) sde1[1]
      1953519872 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
      [>....................]  recovery =  0.0% (155976/976759936) finish=208.6min speed=77988K/sec

Parece que todo va muy bien. El disco viejo ya esta marcado como [F]ailed y mdadm ya comenzó a usar el nuevo para regenerar el arreglo. Ahora si podemos quitar el disco viejo por completo:

$ sudo mdadm --manage /dev/md0 --remove /dev/sdb1

$ cat /proc/mdstat
md0 : active raid5 sdd[3] sdc1[0] sde1[1]
      1953519872 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
      [>....................]  recovery =  1.7% (16652688/976759936) finish=226.0min speed=70789K/sec


Le tomará un buen rato regenerar el arreglo, pero una vez mas, RAID salvó el día.

domingo, 3 de junio de 2012

Configuración de PowerDNS

Para que procrastinar hoy, si lo puedo hacer mañana...

Hace ya más de dos años, contraté un cloud server con Rackspace, cuya finalidad era eventualmente reemplazar un servidor moribundo que tengo en GoDaddy. Durante ese tiempo me ha servido para realizar todo tipo de pruebas, pero nunca me dediqué a configurarlo para lo que realmente era su objetivo.

Para no seguir pagando la renta de dos servidores, hoy pensé en seguir en donde me había quedado. Durante mis pruebas, la seguridad de mi servidor desafortunadamente pasó a segundo plano, y como era de esperarse, al revisar los logs encontré evidencia de intrusos. Como realmente no tenía información importante en ese servidor, decidí utilizar la excelente herramienta de Rackspace para borrar todo y volver a empezar de cero, ahora utilizando Ubuntu 12.04 LTS.

En este post seguiré paso a paso la configuración incial del servidor, llegando hasta el punto en que logremos tener una instalación funcional de PowerDNS.

Elegí PowerDNS porque necesito tener un backend basado en MySQL, y lograr esto con BIND se complica un poco. Además, de todos programas de DNS (excluyendo a BIND), este es el que me pareció mas popular, y esto normalmente se traduce a mejor documentación...aunque después de terminar la configuración he de decir que hay algunas cosas no están tan bien documentadas (como la integración con DNSSEC). Aún así, creo que fue una buena elección.

Una vez que la imagen haya terminado de cargarse en el servidor, lo primero que hay que hacer es conectarse por ssh y cambiar el password de root.

$ passwd 

Me siento sucio al estar haciendo todo como root, entonces mejor creamos un usuario normal, y lo agregamos a la lista de sudoers:

$ adduser kenneth
$ adduser kenneth sudo

Accedemos usando el nuevo usuario e instalamos los paquetes iniciales:

$ sudo apt-get update
$ sudo apt-get install vim subversion rar unrar apache2 php5 php5-mysql mysql-server php5-mcrypt ack-grep pdns-backend-mysql

Como podrás notar, en este punto ya estamos instalando PowerDNS. Apt se encargará de conseguir los demás paquetes requeridos. En este paso también quedarán instalados MySQL y Apache 2.

Lo primero que me gusta hacer con la instalación de Apache, es cambiar el DocumentRoot de lugar, para que quede en /www. En este directorio descargamos y descomprimimos los paquetes de PHPMyAdmin y PowerAdmin.

Después de configurar PHPMyAdmin, podemos fácilmente crear un usuario y una base de datos para PowerDNS.

El siguiente schema incluye los campos nuevos requeridos en la versión 3.0 de PDNS:

create table domains (
 id   INT auto_increment,
 name   VARCHAR(255) NOT NULL,
 master   VARCHAR(128) DEFAULT NULL,
 last_check  INT DEFAULT NULL,
 type   VARCHAR(6) NOT NULL,
 notified_serial INT DEFAULT NULL, 
 account         VARCHAR(40) DEFAULT NULL,
 primary key (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX name_index ON domains(name);

CREATE TABLE records (
  id              INT auto_increment,
  domain_id       INT DEFAULT NULL,
  name            VARCHAR(255) DEFAULT NULL,
  type            VARCHAR(10) DEFAULT NULL,
  content         VARCHAR(64000) DEFAULT NULL,
  ttl             INT DEFAULT NULL,
  prio            INT DEFAULT NULL,
  change_date     INT DEFAULT NULL,
  primary key(id)
) Engine=InnoDB;

CREATE INDEX rec_name_index ON records(name);
CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);

create table supermasters (
  ip VARCHAR(25) NOT NULL, 
  nameserver VARCHAR(255) NOT NULL, 
  account VARCHAR(40) DEFAULT NULL
) Engine=InnoDB;

-- Cambios necesarios para la version 3.0

create table domainmetadata (
 id   INT auto_increment,
 domain_id       INT NOT NULL,
 kind   VARCHAR(16),
 content TEXT,
 primary key(id)
);

create index domainmetaidindex on domainmetadata(domain_id);               


create table cryptokeys (
 id  INT auto_increment,
 domain_id      INT NOT NULL,
 flags  INT NOT NULL,
 active  BOOL,
 content TEXT,
 primary key(id)
);   

create index domainidindex on cryptokeys(domain_id);           

alter table records add ordername      VARCHAR(255);
alter table records add auth bool;
create index orderindex on records(ordername);

create table tsigkeys (
 id  INT auto_increment,
 name  VARCHAR(255), 
 algorithm VARCHAR(50),
 secret  VARCHAR(255),
 primary key(id)
);

create unique index namealgoindex on tsigkeys(name, algorithm);
alter table records change column type type VARCHAR(10);

Ahora podemos empezar a configurar PowerDNS. Empezamos por deshabilitar las funciones de DNSSEC:

#/etc/powerdns/pdns.d/pdns.local.gmysql

gmysql-dnssec=no

Después probamos que PDNS funcione y que la conexión a MySQL sea exitosa:

$ /etc/init.d/pdns monitor
Jun 03 18:53:29 Creating backend connection for TCP
% Jun 03 18:53:29 gmysql Connection successful

Si todo parece estar bien, podemos empezar a configurar PowerAdmin. Esta es una interfaz web que facilita la interacción con la base de datos de PowerDNS.
Para configurarlo, primero debemos asegurarnos de que apache tenga el acceso correcto a los archivos:

$ sudo chown -R www-data /www/poweradmin

Navegamos a http://host/powerdns/install para entrar al script de configuración. Aquí se crearán unas tablas extra en la base de datos para guardar plantillas y usuarios.

Hablando de plantillas, ya que esté configurado PowerAdmin, podemos crear una plantilla como la siguiente:

Name Type Content TTL Priority
[ZONE] SOA localhost hostmaster@[ZONE] [SERIAL] 86400
[ZONE] NS ns1.knet.mx 86400
[ZONE] NS ns2.knet.mx 86400
*.[ZONE] CNAME [ZONE] 120
[ZONE] MX mail.[ZONE] 120 25
[ZONE] CNAME 173.203.206.44 86400 10

Después de agregar la zona "example.com", podemos probar la resolución usando dig y host:

$ dig example.com
$ host example.com knet.mx

Ese último comando básicamente quiere decir "Pregúntale a knet.mx cuáles son los registros DNS de example.com".


¡Y listo! Con esto queda el servidor preparado para atender los dominios que quieras, solo hay que agregarlos utilizando la plantilla.