Discuta este tópico no fórum

Se este conteúdo te ajudou, deixe um presente!

segunda-feira, 15 de outubro de 2012

Transformando partições para RAID1

Armazenamento é uma questão crítica para grande partes dos serviços. Uma das falhas comuns no armazenamento de dados em computadores é a falha nos dispositivos de armazenamento, principalmente quando se trata de um disco com partes móveis. Uma técnica clássica de mitigar este tipo de problema é a utilização de RAID (Redundant Array of Inexpensive Drives).

Existem diversas combinações de arranjo de discos, RAID1, RAID5, RAID6, e combinações, que buscam manter a integridade dos dados mesmo na eventual falha de discos. Neste artigo, não vou entrar em detalhes sobre cada uma das técnicas, apenas dizer que o RAID1 (mirroring), espelha todos os dados em ambos os discos.

Para pobres mortais que não possuem o suporte a RAID em Hardware, a solução é utilizar os recursos do Linux para prover a segurança. Basicamente será utilizado apenas o comando mdadm, responsável por toda a gerência de RAID em software no Linux. Neste artigo, vou mostrar como montar um RAID1 a partir de uma partição com dados, sem a necessidade de copiar os dados de um lado para outro.

O mdadm cria um dispositivo MD que agrupa os diversos discos. Por exemplo, ao juntar as partições sda3 e sdb4 em um RAID1, você terá um md0 com um tamanho igual ao menor dos discos (na verdade, ligeiramente menor do que isto, mas vemos isto mais adiante):
mdadm --create /dev/md0 --level 1 /dev/sda3 /dev/sdb4
Você não mais irá acessar os dados em sda3 ou sdb4, apenas em md0. O dispositivo md0 pode ser usado como uma partição/disco normal, criando sistema de arquivos e montando para uso.

O mdadm assume que ambas as partições não possuem dados importantes e, portanto, nada precisa ser mantido. No meu caso, quero manter os dados em um dos discos.

O primeiro passo para entender a gamb...técnica é compreender como são mantidos os metadados do disco RAID. Os metadados armazenam informações como data da última alteração no disco, dispositivos participantes. No Linux, este metadado pode ser volátil,  e portanto, perdido a cada parada, ou embutido na partição/disco do RAID em um superblock.

Quando os metadados são voláteis, cada disco terá, bit a bit, os mesmos dados mostrados. No exemplo anterior, todos os bits em /dev/md0 estarão na mesma sequência que em /dev/sda3  e /dev/sdb4. Isto traz alguns problemas como a possibilidade de montar inadvertidamente um dos discos e corromper os dados. Não existe qualquer controle de alteração, ficando a cargo do administrador proteger os dados quanto a alterações fora do RAID. Também, para RAID com diversos discos, caso o arquivo de configuração seja perdido, será uma tarefa possivelmente complicada identificar o papel de cada disco no RAID (exceto para o RAID1 onde todos armazenam a mesma função).

A solução mais indicada segura para armazenar os metadados é mantê-los em um superblock embutido na partição/disco. Existem atualmente 4 formatos deste superblock:
  1. versão 0.90
  2. versão 1.0
  3. versão 1.1
  4. versão 1.2
A primeira versão, 0.90 está em desuso e é indicada apenas para casos especiais onde o gerenciador de boot não reconhece os novos formatos (grub2 trabalha com LVM e RAID sem problemas). Esta versão também possui outros limitadores como o tamanho máximo do disco e o número de dispositivos. Em geral, as versões mais novas são mais indicadas.

A versão padrão em ambientes atualizados é a 1.2. A diferença entre as versões 1.x está basicamente na posição do disco onde este metadado será armazenado. A primeira, 1.0 fica no final do disco/partição. A versão 1.1 logo no início do disco/partição e a versão fica 4k de distância do início do disco.

Voltamos ao problema em questão de transformar um disco não RAID para RAID1. A posição onde ficará o metadado possui dados do sistema de arquivos. Precisamos liberar estes blocos antes da criação do RAID. Para as versões 1.1 e 1.2, isto seria no começo do disco. Porém, seria necessário liberar um pedaço no final do disco e deslocar todos os dados para poder utilizar o começo do disco. O mais simples seria utilizar a versão 1.0 e liberar a porção final do disco. Felizmente, isto não é um problema no Linux. Os sistemas de arquivos podem ser redimensionados com simples comandos.

Inicialmente temos a seguinte situação:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |               ext3                  |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                                                   |
+---------------------------------------------------+

O disco sda possui duas partições, ambas com sistema de arquivos ext3 e ocupando todo o espaço da partição. O disco sdb não possui qualquer partição. Vamos primeiro liberar o espaço para o metadado na partição sda2. O metadados é pequeno mas, por garantia, pode ser liberado umas dezenas de megabytes do sistema de arquivos. No pior dos casos, libere todo o espaço disponível. Ao final do processo, este espaço será recuperado. Para saber quanto é o mínimo, tente reduzir o tamanho para 1 bloco. Ex:
# resize2fs /dev/sda2 1
resize2fs 1.41.9 (22-Aug-2009)
resize2fs: New size smaller than minimum (54176)
Na sequência, escolha um valor mais apropriado, maior ou igual ao mínimo. Ex:
# resize2fs /dev/sda2 54180
O comando provavelmente solicitará a execução do fsck antes do processo. Ao final do processo, teremos:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |        ext3    :         livre      |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                      livre                        |
+---------------------------------------------------+

É importante lembrar que a partição continua com o mesmo tamanho. Apenas o sistema de arquivos foi reduzido. 
Nota: Para os antigos usuários do Partition Magic, ele fazia as duas tarefas: reduzia o sistema de arquivos e a partição. 
Agora, criamos o RAID1. Iremos utilizar o metadado 1.0, que ocupará a parte do espaço livre liberado no passo anterior:
# mdadm --create /dev/md0 --metadata 1.0 --level=1 --raid-devices=2 /dev/sda2 missing
Ele alertará que existe um sistema de arquivos nesta partição. Ignore o aviso. Após este passo, você já terá o dispositivo RAID pronto, mas com apenas um disco. O "missing" no comando anterior informou que um dos discos está ausente. Você pode ver a situação de seu dispositivo em /proc/mdstat:
# cat /proc/mdstat
Personalities : [raid1]
md0 : active raid1 sda2[0]
      208884 blocks super 1.0 [2/1] [U_]
           
unused devices: <none>
O símbolo "_" em "[U_]" indica que apenas um dos dois dispositivos deste RAID estão em operação/presentes.

E o disco ficou desta forma:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |     ext3       : livre  :  metadado |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                      livre                        |
+---------------------------------------------------+

Agora o espaço livre após o sistema de arquivos e antes do metadado pode ser recuperado. Porém, isto deve ser feito já no disco RAID e nunca no dispositivo original sda2! Basta reexecutar o resize2fs sem definir o tamanho para ele ocupar todo o espaço disponível:
# resize2fs /dev/md0
E o disco ficará:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |           ext3          :  metadado |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|                      livre                        |
+---------------------------------------------------+


Para completar o RAID1, basta adicionar as partições/discos espelhos:
mdadm --manage /dev/md0 --add /dev/sdb
OBS: Coloquei intencionalmente um disco inteiro como exemplo que é possível combinar partições e discos mas também seria possível particionar o disco sdb e utilizar uma de suas partições para o comando anterior:
Neste ponto, o disco já estará em processo de sincronia. Acompanhe pelo arquivo /proc/mdstat. Sugiro utilizar o comando watch:
watch cat /proc/mdstat
O layout final ficará:

+---------------------------------------------------+
|     sda1    |               sda2                  |
+.............+.....................................+
|     ext3    |           ext3          :  metadado |
+---------------------------------------------------+

+---------------------------------------------------+
|                       sdb                         |
+...................................................+
|           ext3          :  metadado :    livre    |
+---------------------------------------------------+

O espaço livre ao final de sdb é devido ao fato de que sdb é maior do que a partição sda2. Se este for seu caso, o disco sdb poderia ser dividido em partições, sendo uma do tamanho exato da sda2. Assim, o restante do disco poderia ser utilizado para outras partições com dados diversos.

Seu disco está pronto para uso. Se o sda2 estava em uso, lembre de retirar qualquer configuração de montagem deste disco (em /etc/fstab) antes de reiniciar o computador. Porém, é possível que este RAID não seja "ligado" automaticamente quando o sistema for reiniciado.

Em algumas distribuições, todos os RAID encontrados serão ligados. Porém, em outros casos, por cautela dos desenvolvedores, é necessário explicitamente indicar o que o administrador deseja. Isto depende de cada distribuição. Para OpenSUSE/SLES, crie o arquivo /etc/mdadm.conf, se não existir, e inclua uma linha como esta:
ARRAY /dev/md0 UUID=2de1a56d:717ce2cc:231893bb:4e44f123
O UUID é diferente para cada RAID e pode ser encontrado executando o comando:
mdadm --detail /dev/md0
Ative o serviço boot.md (provavelmente outro nome em outras distribuições):
chkconfig boot.md on
Reinicie o sistema para testar sua configuração.


Em sistemas modernos, a montagem direta de dispositivos que formam o RAID (como a sda2 e sdb) irá falhar por causa das verificações de proteção do sistema de arquivos.

Caso seja necessário retornar ao estado original:
  1. Remova a configuração do disco no /etc/fstab e no /etc/mdadm.conf
  2. Pare o RAID: mdadm --stop /dev/md0
  3. Zere os metadados: mdadm --misc --zero-superblock /dev/sda2
    1. Isto para cada dispositivo que participava do RAID
  4. Recupere o espaço usado pelo superblock
    1. resize2fs /dev/sda2
Happy hacking!