Dia 12: LVM em Profundidade — Snapshots e Extensão Online

No Dia 11 vimos LVM básico — criar um volume group, um logical volume e formatar com ext4 ou xfs. Hoje aprofundamos: extensão e redução online, snapshots para backup consistente, thin provisioning, migração de dados entre discos com pvmove, mirror e cache LV. Estas são as funcionalidades que fazem do LVM a ferramenta de gestão de armazenamento mais usada em servidores Linux de produção.

O LVM (Logical Volume Manager) separa o espaço físico dos discos da apresentação lógica ao sistema operativo. Um LV pode crescer enquanto está montado e em uso, pode ser fotografado num instante para backup, e pode ser espelhado entre discos sem o sistema de ficheiros saber. Este artigo assume que já domina os conceitos do Dia 11 — partições, tipos de partição (8e para LVM), e o fluxo básico PV → VG → LV.

1. Revisão PV/VG/LV — A Arquitectura em Três Camadas

O LVM organiza o armazenamento em três camadas hierárquicas. Compreender esta hierarquia é essencial — todas as operações avançadas (snapshots, thin pools, mirrors) operam dentro dela.

Camada Significado Comando de Criação Unidade Base
PV (Physical Volume) Disco ou partição inicializada para LVM pvcreate PE (Physical Extent, tipicamente 4 MB)
VG (Volume Group) Conjunto de PVs — o pool de espaço vgcreate PE herdado dos PVs membros
LV (Logical Volume) Volume lógico extraído do VG lvcreate LE (Logical Extent, mapeia 1:1 para PE)

O Physical Extent (PE) é a unidade mínima de alocação no LVM. O tamanho padrão é 4 MB — cada PE do PV mapeia directamente para um LE (Logical Extent) no LV. Ao criar um LV de 10 GB, o LVM aloca 2 560 PEs (10 GB ÷ 4 MB). O tamanho do PE afecta a granularidade: PE maior (16 MB, 64 MB) reduz overhead mas desperdiça mais espaço em fragmentação; PE menor permite alocação mais precisa.

Comandos de Visualização

Três comandos mostram o estado das três camadas. Usar as versões compactas (pvs, vgs, lvs) para visão rápida, e as versões display para detalhe completo:

# Visão compacta das três camadas
sudo pvs          # Lista PVs: nome, VG, tamanho, espaço livre
sudo vgs          # Lista VGs: nome, PVs, espaço total/livre
sudo lvs          # Lista LVs: nome, VG, atributos, tamanho

# Detalhe completo de cada camada
sudo pvdisplay /dev/sdb1
sudo vgdisplay vg_dados
sudo lvdisplay /dev/vg_dados/lv_backup

# Ver o mapeamento físico (que PV alimenta que LV)
sudo pvdisplay -m /dev/sdb1

ℹ Nota: O atributo “a” em lvs significa “active” — o LV está activo e acessível. Um LV com atributo “s” é um snapshot. Consultar a man page do lvs para a lista completa de atributos.

2. pvcreate, vgcreate, lvcreate — Criar a Base

Antes de operações avançadas, revisitar o fluxo completo de criação. O cenário: dois discos novos (/dev/sdb e /dev/sdc) para um volume group de dados. Pode-se usar o disco inteiro ou uma partição — a partição com tipo 8e (Linux LVM) é a abordagem tradicional, mas o LVM aceita directamente o dispositivo de bloco.

# 1. Inicializar os discos como Physical Volumes
sudo pvcreate /dev/sdb /dev/sdc
  Physical volume "/dev/sdb" successfully created.
  Physical volume "/dev/sdc" successfully created.

# 2. Criar o Volume Group com PE de 16 MB (em vez do padrão 4 MB)
sudo vgcreate -s 16m vg_dados /dev/sdb /dev/sdc
  Volume group "vg_dados" successfully created

# 3. Criar um Logical Volume de 50 GB
sudo lvcreate -L 50G -n lv_app vg_dados
  Logical volume "lv_app" created.

# 4. Criar um LV que usa TODO o espaço livre do VG
sudo lvcreate -l 100%FREE -n lv_dados vg_dados

# 5. Formatar e montar
sudo mkfs.xfs /dev/vg_dados/lv_app
sudo mkdir /mnt/app
sudo mount /dev/vg_dados/lv_app /mnt/app

O parâmetro -s 16m no vgcreate define o tamanho do PE em 16 MB — útil para VGs grandes (>1 TB) onde o padrão de 4 MB gera metadados excessivos. O -l 100%FREE aloca todo o espaço restante do VG no LV.

Instalar o LVM (se não estiver presente)

Em instalações mínimas, o pacote LVM pode não estar instalado. Os comandos diferem entre distribuições:

# Debian/Ubuntu
sudo apt update && sudo apt install lvm2

# RHEL/Rocky/Alma/Fedora
sudo dnf install lvm2

# Verificar a versão instalada
sudo lvm version
  LVM version:     2.03.16(2) (2022-05-18)
  Library version: 1.03.16(2) (2022-05-18)

3. lvextend e lvreduce — Redimensionar LVs Online

A extensão de um LV é a operação mais comum em produção — um volume enche e precisa de mais espaço sem downtime. O lvextend aumenta o LV; depois é preciso expandir o file system para o novo tamanho (ver secção 4).

Extensão — lvextend

# Adicionar 20 GB ao LV (extensão relativa)
sudo lvextend -L +20G /dev/vg_dados/lv_app

# Definir tamanho absoluto de 100 GB
sudo lvextend -L 100G /dev/vg_dados/lv_app

# Usar todo o espaço livre do VG
sudo lvextend -l +100%FREE /dev/vg_dados/lv_app

# Extender E redimensionar o file system num só comando (-r)
sudo lvextend -L +20G -r /dev/vg_dados/lv_app
  # O -r chama automaticamente xfs_growfs ou resize2fs conforme o FS

ℹ Dica: A flag -r (ou --resizefs) é o atalho que todo o sysadmin deve usar — combina lvextend + xfs_growfs/resize2fs num único comando. Detecta automaticamente o tipo de file system.

Redução — lvreduce (Cuidado!)

Reduzir um LV é perigoso — se o novo tamanho for menor que os dados existentes, há perda de dados. O procedimento correcto exige reduzir o file system antes do LV, e só funciona com ext4 (xfs não suporta redução).

# REDUÇÃO DE ext4 (passo-a-passo — NÃO usar -r aqui):
# 1. Desmontar o volume
sudo umount /dev/vg_dados/lv_app

# 2. Verificar o file system
sudo e2fsck -f /dev/vg_dados/lv_app

# 3. Reduzir o file system PRIMEIRO (para 40G)
sudo resize2fs /dev/vg_dados/lv_app 40G

# 4. Só agora reduzir o LV (mesmo tamanho!)
sudo lvreduce -L 40G /dev/vg_dados/lv_app

# 5. Remontar e verificar
sudo mount /dev/vg_dados/lv_app /mnt/app
df -h /mnt/app

⚠ Aviso crítico: XFS não pode ser reduzido — é uma limitação de design do XFS. Se precisar de reduzir um volume XFS, a única opção é fazer backup dos dados, destruir o LV, recriá-lo menor, reformatar e restaurar. Para volumes que possam precisar de redução futura, usar ext4 em vez de xfs.

4. xfs_growfs e resize2fs — Expandir o File System

Depois de lvextend, o LV tem mais espaço mas o file system ainda não o vê. É preciso expandir o FS para preencher o novo tamanho. O comando depende do tipo de file system:

File System Comando de Expansão Redução Suportada? Montado?
ext4 resize2fs /dev/vg/lv Sim (com e2fsck + desmontar) Sim (expansão online)
xfs xfs_growfs /mnt/ponto Não Sim (expansão online)
# Extender o LV primeiro
sudo lvextend -L +20G /dev/vg_dados/lv_app

# Para XFS — passar o PONTO DE MONTAGEM (não o dispositivo)
sudo xfs_growfs /mnt/app
  meta-data=/dev/vg_dados/lv_app  isize=512  agcount=4, agsize=327680 blks
  data blocks=1310720, rtextchars=0
  data blocks changed from 1310720 to 1835008

# Para ext4 — passar o DISPOSITIVO
sudo resize2fs /dev/vg_dados/lv_app
  The filesystem on /dev/vg_dados/lv_app is now 26214400 (4k) blocks long.

# Verificar o novo tamanho
df -h /mnt/app

⚠ Erro frequente: xfs_growfs recebe o ponto de montagem (/mnt/app), não o dispositivo. resize2fs recebe o dispositivo (/dev/vg_dados/lv_app). Trocar os argumentos causa erro imediato.

5. LVM Snapshots — lvcreate –snapshot

Um snapshot LVM é uma fotografia pontual do estado de um LV num instante específico. Não é uma cópia completa — usa copy-on-write (COW): o snapshot começa vazio e só regista os blocos que mudam no LV original após o momento do snapshot. Isto torna a criação instantânea, independentemente do tamanho do volume.

Criar um Snapshot

# Criar snapshot de 5 GB do lv_app
# O tamanho (5G) é o espaço para guardar blocos alterados (COW)
sudo lvcreate -L 5G -s -n lv_app_snap /dev/vg_dados/lv_app
  Logical volume "lv_app_snap" created.

# Verificar — o snapshot aparece como LV normal com atributo "s"
sudo lvs
  LV         VG       Attr       LSize  Origin     Data%
  lv_app     vg_dados owi-aos---  70.00g
  lv_app_snap vg_dados swi-a-s---  5.00g lv_app    0.01

# Montar o snapshot para backup consistente
sudo mkdir /mnt/snap
sudo mount /dev/vg_dados/lv_app_snap /mnt/snap

# Fazer backup do snapshot (estado congelado no momento da criação)
sudo tar -czf /backup/app-$(date +%F).tar.gz -C /mnt/snap .

# Desmontar e remover o snapshot quando o backup terminar
sudo umount /mnt/snap
sudo lvremove -f /dev/vg_dados/lv_app_snap

O tamanho do snapshot (5 GB no exemplo) é o espaço reservado para o COW. Se o LV original mudar mais de 5 GB de blocos enquanto o snapshot existe, o snapshot fica inválido (overflow). Monitorizar com lvs — a coluna Data% mostra a percentagem de uso do espaço COW. Quando chega a 100%, o snapshot é automaticamente desactivado.

Merge e Restore de Snapshots

O lvconvert --merge reverte o LV original ao estado do snapshot — útil para rollback após uma actualização falhada. O merge ocorre na próxima activação do LV (se estiver desmontado, imediatamente; se estiver montado, no próximo reboot).

# Antes de uma actualização arriscada, criar snapshot
sudo lvcreate -L 2G -s -n lv_root_pre_update /dev/vg_os/lv_root

# Executar a actualização... (algo corre mal)

# Reverter para o estado anterior ao update
sudo lvconvert --merge /dev/vg_os/lv_root_pre_update
  Merging of snapshot lv_root_pre_update will start next activation.
  Logical volume lv_root_pre_update contains a merge in progress.
  Logical volume vg_os/lv_root contains a merge in progress.

# Se o LV estiver montado (root), o merge acontece no próximo reboot
sudo reboot

# Após reboot, o snapshot é removido automaticamente após o merge

ℹ Padrão de uso: Snapshot antes de update → testar → se OK, remover snapshot com lvremove; se falhar, lvconvert --merge e reboot. Consultar a man page do lvconvert para todas as opções de merge.

6. Thin Provisioning — Overcommit de Storage

No LVM tradicional (thick), um LV de 100 GB reserva imediatamente 100 GB no VG, mesmo que só use 5 GB. O thin provisioning elimina esta reserva — o espaço só é consumido quando efectivamente escrito. Isto permite overcommit: criar LVs cuja soma excede o tamanho do VG, confiando que nem todos usam o espaço alocado simultaneamente.

# 1. Criar um thin pool (o reservatório de espaço real)
#    O pool tem 100 GB de espaço físico real
sudo lvcreate -L 100G -T vg_dados/thin_pool

# 2. Criar LVs thin — podem somar mais de 100 GB!
sudo lvcreate -V 200G -T vg_dados/thin_pool -n lv_vm1
sudo lvcreate -V 200G -T vg_dados/thin_pool -n lv_vm2
sudo lvcreate -V 200G -T vg_dados/thin_pool -n lv_vm3
  # 3 LVs de 200 GB = 600 GB virtuais sobre 100 GB reais

# 3. Monitorizar o uso real do pool
sudo lvs -o name,data_percent,origin,snap_percent vg_dados
  LV        Data%  Origin  Snap%
  thin_pool  45.20
  lv_vm1     12.50
  lv_vm2     30.80
  lv_vm3     02.10

# 4. Quando o pool encher, extender o thin pool (não os LVs)
sudo lvextend -L +50G /dev/vg_dados/thin_pool

⚠ Risco do overcommit: Se os LVs thin collectively escreverem mais do que o pool físico tem, o VG fica sem espaço e todos os LVs thin param com erro de I/O. Monitorizar Data% do pool e extender antes de chegar a 100%. Configurar alertas a 80%.

7. vgextend, pvmove e vgreduce — Gerir Discos no VG

Adicionar e remover discos de um volume group sem parar o sistema é uma das funcionalidades mais poderosas do LVM. O fluxo completo: adicionar um novo disco ao VG, migrar os dados do disco antigo e remover o disco antigo do VG — tudo online.

Adicionar Disco — vgextend

# Novo disco /dev/sdd — inicializar e adicionar ao VG existente
sudo pvcreate /dev/sdd
sudo vgextend vg_dados /dev/sdd
  Volume group "vg_dados" successfully extended

# Verificar o novo espaço livre
sudo vgs vg_dados
  VG       #PV #LV #SN Attr   VSize   VFree
  vg_dados  3   2   0 wz--n- 299.99g 99.99g

Migrar Dados — pvmove

O pvmove migra todos os PEs de um PV para outros PVs no mesmo VG — online, enquanto o LV está montado e em uso. É a forma de esvaziar um disco antes de o remover.

# Migrar todos os dados de /dev/sdb para outros PVs do VG
sudo pvmove /dev/sdb
  /dev/sdb: Moved: 0.0%
  /dev/sdb: Moved: 45.2%
  /dev/sdb: Moved: 100.0%

# Migrar apenas um LV específico de um PV
sudo pvmove -n lv_app /dev/sdb /dev/sdd

# Verificar que o PV está vazio (PUsed deve ser 0%)
sudo pvs /dev/sdb
  PV         VG       Fmt  Attr PSize  PFree
  /dev/sdb   vg_dados lvm2 a--  100.00g 100.00g

Remover Disco — vgreduce

# Depois de pvmove esvaziar o PV, removê-lo do VG
sudo vgreduce vg_dados /dev/sdb
  Removed "/dev/sdb" from volume group "vg_dados"

# Remover o PV do disco (deixa de ser LVM)
sudo pvremove /dev/sdb

# Agora /dev/sdb pode ser removido fisicamente do servidor

ℹ Cenário típico: Substituir um disco de 1 TB por um de 4 TB sem downtime: (1) pvcreate no novo disco, (2) vgextend para o adicionar, (3) pvmove para migrar os dados, (4) vgreduce + pvremove para remover o antigo. Tudo online. Ver Arch Wiki: LVM para exemplos detalhados.

8. Mirror LV e Cache LV — Funcionalidades Avançadas

Mirror LV — RAID 1 no LVM

O LVM pode espelhar um LV entre dois ou mais PVs — equivalente a RAID 1 mas gerido pelo LVM. Se um disco falha, o LV continua acessível a partir do mirror. Requer pelo menos 2 PVs no VG (tipicamente em discos físicos diferentes).

# Criar LV mirror de 50 GB (2 cópias em 2 PVs diferentes)
sudo lvcreate -L 50G -m 1 -n lv_critical vg_dados
  # -m 1 = 1 mirror (2 cópias total: original + 1 mirror)

# Criar LV com RAID 1 via lvconvert (alternativa moderna)
sudo lvcreate -L 50G -n lv_critical vg_dados
sudo lvconvert -m 1 /dev/vg_dados/lv_critical

# Verificar o estado do mirror
sudo lvs -a -o name,region_size,data_percent,attr vg_dados
  lv_critical       2.00m  100.00 Rwi-aor---

# Se um disco falhar, reparar substituindo o PV:
sudo pvcreate /dev/sde
sudo vgextend vg_dados /dev/sde
sudo vgreduce --removemissing vg_dados  # remove o PV falhado
sudo lvconvert -m 1 /dev/vg_dados/lv_critical  # recriar mirror

Cache LV — Acelerar com SSD

O cache LV usa um dispositivo rápido (SSD/NVMe) como cache para um LV lento (HDD). O LVM cria automaticamente o cache pool e liga-o ao LV de dados. Ideal para bases de dados em discos mecânicos acelerados por SSD.

# Cenário: LV de dados em HDD (lv_db), SSD para cache (/dev/nvme0n1)

# 1. Criar PV no SSD e adicionar ao VG
sudo pvcreate /dev/nvme0n1
sudo vgextend vg_dados /dev/nvme0n1

# 2. Criar cache pool no SSD (10 GB, modo writeback)
sudo lvcreate -L 10G --type cache-pool -n cache_pool vg_dados /dev/nvme0n1

# 3. Ligar o cache pool ao LV de dados (transforma lv_db em cached)
sudo lvconvert --type cache --cachepool vg_dados/cache_pool vg_dados/lv_db

# 4. Verificar — o LV agora tem atributo "C" (cache)
sudo lvs -o name,attr,cache_mode vg_dados
  LV    Attr       Cache
  lv_db Cwi-a-C--- writeback
Modo de Cache Comportamento Risco
writeback Escritas confirmadas no cache, assíncronas para o HDD Perda de dados se SSD falhar antes do flush
writethrough Escritas confirmadas só após escrever no HDD Seguro — sem perda se SSD falhar

9. Erros Comuns

Problema Causa Solução
"Volume group not found" PV não inicializado ou VG não activado sudo vgscan && sudo vgchange -ay
Snapshot fica inválido sem aviso Espaço COW do snapshot insuficiente (Data% chegou a 100%) Criar snapshot maior: lvextend -L +5G /dev/vg/snap ou monitorar com alerta a 80%
xfs_growfs: cannot grow data section LV não foi extendido antes de tentar crescer o FS Executar lvextend primeiro, depois xfs_growfs
resize2fs: Filesystem not clean FS não verificado ou montado em modo só-leitura Desmontar, e2fsck -f, depois resize2fs
Thin pool sem espaço — I/O errors Overcommit excedeu o espaço físico do pool lvextend -L +50G /dev/vg/thin_pool imediatamente; configurar alertas a 80%
pvmove: Cannot allocate extents Não há espaço livre noutros PVs para receber os dados Adicionar disco novo com vgextend antes de pvmove
LV não activa após reboot VG não marcado como auto-active sudo vgchange -ay; verificar /etc/lvm/lvm.conf e auto_activation_volume_list

10. Checklist de LVM

  1. Verificar estado das três camadas com pvs, vgs, lvs antes de qualquer operação
  2. Extender LV online com lvextend -L +NG -r /dev/vg/lv — a flag -r redimensiona o FS automaticamente
  3. Para reduzir ext4: desmontar → e2fsck -fresize2fslvreduce → remontar
  4. XFS nunca reduz — se precisar de reduzir, backup + destruir + recriar
  5. Snapshots para backup: lvcreate -L 5G -s -n snap /dev/vg/lv → montar → backup → lvremove
  6. Monitorizar Data% do snapshot — remover antes de chegar a 100% ou o snapshot é invalidado
  7. Thin provisioning: criar pool com lvcreate -L NG -T vg/pool, LVs com -V, alertar a 80% de Data% do pool
  8. Substituir disco sem downtime: pvcreate novo → vgextendpvmove antigo → vgreduce + pvremove
  9. Mirror LV com -m 1 para dados críticos — verifica periodicamente com lvs -a -o name,attr
  10. Cache LV com SSD em modo writethrough para segurança de dados; writeback só para performance com risco aceitável
  11. Adicionar entradas em /etc/fstab usando /dev/vg_dados/lv_app ou UUID — nunca o caminho /dev/mapper/ ambíguo
  12. Validar fstab com sudo mount -a e testar reboot antes de produção

✓ Boa prática: Usar LVM em todos os servidores de produção, mesmo com um único disco. O overhead é mínimo e ganha-se: extensão online, snapshots para backup consistente, e a capacidade de adicionar discos sem parar o sistema. Consultar a Arch Wiki: LVM e a Debian Wiki: LVM para referência contínua.

No Dia 13 do curso Linux 30 Dias, vamos abordar cron e agendamento — crontab, at e a comparação entre cron e systemd timers para automação de tarefas.

Artigos Relacionados