Homelab: Memory Overcommit – SSD Edition

Olá a todos,

Como todos os que tem o seu próprio homelab virtualizado, ou utilizam virtualização centralizada em pequena escala podem confirmar, existem três coisas fundamentais para ambientes virtuais: CPU (em termos de context switching), capacidade de memória (MB/s por VM) e IO.
Também praticamente todos afirmam que sofrem de problemas em dois dos três: capacidade de memória e IO wait alto.

Em ambientes virtuais, estes bottlenecks estão praticamente sempre associados entre si.
É um ciclo vicioso: Falta memória à maquina física, o administrador de sistemas dá menos memória à máquina virtual , logo em carga a máquina virtual faz mais swap, causando sobrecarrega de IO no virtualizador, levando a lentidão generalizada.

Com este problema bastante visível nos nossos homelab’s, eu e um colega estávamos a equacionar reforçar a memória RAM dos nossos virtualizadores, quando notamos que o preço da memória havia sofrido igualmente um pico.
A memória, na capacidade que necessitávamos estava a um preço proibitivo.

Sendo os pais de família responsáveis que somos, tínhamos que procurar uma solução que fosse amiga da nossa carteira e que nos suprimisse os bottlenecks que estávamos a sentir.

Eis que o colega se lembra de algo extremamente simples e engenhoso: Porque não utilizar SSD’s de baixa capacidade <=120GB para swap, utilizando toda a RAM como memória intermédia?
Melhor ainda, porque não colocar o SSD’s num bus PCIe para aproveitar os slots que temos vazios enquanto deixamos livres portas de disco SATA que pela necessidade estão consideradas a premium?

O setup que foi escolhido foi: Placa com controlador ASM1062, com disco mSATA1 da Kingston de 120GB (no meu caso comprei apenas 60GB por rotura de stock).
A Kingston anuncia para o SSD em questão uma velocidade de até 550MB/s para leitura e 520MB/s para escrita com  86,000 iops de leitura e 79,000 iops de escrita.

Assim que a placa foi montada, e o disco SSD  ficou visível ao sistema operativo, configurei um volume group em LVM, fazendo em seguida logical volumes para (exportados via VirtIO) como um disco novo para dentro das máquinas virtuais apenas para swap.
Foi em seguida desativada a swap existente em cada máquina virtual que estivesse residente num disco mecânico.

Igualmente toda a swap que tinha em discos mecânicos do próprio virtualizador foi substituída por um novo lvol no mesmo SSD.
Finalmente diminuir para 5 a swappiness no virtualizador, e a vfs_cache_pressure para 50.

Os resultados são bastante expressivos:

Em termos de IOwait:

index.php

Até dia 14, utilizava apenas single disk swap, depois de dia 14 passei a usar o equivalente de swap com stripe através de múltiplos discos mecânicos simultaneamente (publicarei em breve um howto de como fazer isto), depois de dia 19 apenas o SSD como swap.
É claramente visível a descida de IOwait no sistema, enquanto o consumo de memória swap aumenta:

index

Como decerto alguns de vós já devem estar a pensar, tanta carga num SSD irá diminuir o seu tempo de vida. Correto.
Mas a carga que lhe é dada não tão anormalmente alta como seria expectável.
Neste momento a após 34 horas de funcionamento, o SSD apenas efetuou 51GB de escrita e 337GB de leituras (o valor que nos interessa são os bytes escritos):

# smartctl  -a /dev/sdf
smartctl 6.3 2014-07-26 r3976 [x86_64-linux-3.16.6-2-default]
Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     SandForce Driven SSDs
Device Model:     KINGSTON SMS200S360G

Vendor Specific SMART Attributes with Thresholds:

241 Lifetime_Writes_GiB     0x0032   000   000   000    Old_age   Always       –       51
242 Lifetime_Reads_GiB      0x0032   000   000   000    Old_age   Always       –       337

Tendo em conta que este modelo de SSD tem uma MTBF de 1 milhão de horas, e em termos de erros que a Kingston anuncia 218TB escritos até que exista degradação de performance faz que este SSD possa ter esta utilização durante 16.5 anos.

Tendo em conta os preços na altura que este artigo está a ser escrito, tanto do SSD (€ 50) como de 16GB de RAM (€ 167,80) para os mesmos 2 anos de garantia, a escolha torna-se óbvia.

Finalmente e como surpresa acrescida, existiu um decréscimo no consumo elétrico do servidor.
Como a swap passou a estar toda no SSD, tanto para o virtualizador como para as máquinas virtualizadas, existe menos carga mecânica nos discos que se traduz num decréscimo do consumo elétrico (<2%) nas 34 horas em que está em utilização:

ups

Irei agora comprar o mesmo conjunto (placa pci-e+disco mSata) para o meu outro servidor tendo em conta o nível de sucesso que esta alteração trouxe.

Concluindo, pelos resultados obtidos até agora é das ideias mais engenhosas que o meu colega Nuno teve e certamente é um conceito que pode auxiliar na diminuição imediata de custos.
O procedimento em si não vos dará mais memória RAM mas irá vos permitir estenderem o consumo da vossa memória RAM atual, sobrecarregando a swap que o vosso sistema possua.
Como esta swap é muito rápida que a swap num disco mecânico tradicional praticamente não notarão a diferença nas vossas VM’s o que se traduzirá em mais VM’s (ou VM’s maiores) sem mais RAM.

Como sempre se tiverem duvidas, sugestões ou ideias o meu email está sempre disponível.

Update:

Descobri que os discos mecânicos tem firmware muito mais trabalhada e madura que os SSD’s.

Nos meus logs começaram a aparecer os seguintes erros:
2015-02-19T06:45:41.696808+00:00 npar1 kernel: [295159.296431] ata7: SError: { Handshk }
2015-02-19T06:45:41.696810+00:00 npar1 kernel: [295159.296434] ata7.00: failed command: WRITE FPDMA QUEUED
2015-02-19T06:45:41.696811+00:00 npar1 kernel: [295159.296443] ata7.00: status: { DRDY }
2015-02-19T06:45:41.696812+00:00 npar1 kernel: [295159.296445] ata7.00: failed command: WRITE FPDMA QUEUED
2015-02-19T06:45:41.696813+00:00 npar1 kernel: [295159.296449] ata7.00: cmd 61/00:08:d8:1c:34/04:00:01:00:00/40 tag 1 ncq 524288 out
2015-02-19T06:45:42.088438+00:00 npar1 kernel: [295159.296449]          res 40/00:d8:a0:13:34/00:00:01:00:00/40 Emask 0x10 (ATA bus error)
2015-02-19T06:45:42.088457+00:00 npar1 kernel: [295159.296452] ata7.00: status: { DRDY }
2015-02-19T06:45:42.088458+00:00 npar1 kernel: [295159.296454] ata7.00: failed command: WRITE FPDMA QUEUED
2015-02-19T06:45:42.088460+00:00 npar1 kernel: [295159.296458] ata7.00: cmd 61/00:10:d8:20:34/04:00:01:00:00/40 tag 2 ncq 524288 out
2015-02-19T06:45:42.088461+00:00 npar1 kernel: [295159.296458]          res 40/00:d8:a0:13:34/00:00:01:00:00/40 Emask 0x10 (ATA bus error)
2015-02-19T06:45:42.088462+00:00 npar1 kernel: [295159.296460] ata7.00: status: { DRDY }
2015-02-19T06:45:42.088463+00:00 npar1 kernel: [295159.296462] ata7.00: failed command: WRITE FPDMA QUEUED
2015-02-19T06:45:42.088860+00:00 npar1 kernel: [295159.296466] ata7.00: cmd 61/38:18:d8:24:34/01:00:01:00:00/40 tag 3 ncq 159744 out
2015-02-19T06:45:42.088862+00:00 npar1 kernel: [295159.296466]          res 40/00:d8:a0:13:34/00:00:01:00:00/40 Emask 0x10 (ATA bus error)

Cheguei a conclusão que o meu SSD kingston tem alguns problemas relacionados com o firmware do mesmo em que ao fim de uma torrente de erros o ssd ficava simplesmente offline levando a um crash do servidor.

Embora a Kingston esteja a investigar a situação e esteja a preparar um update, as falhas que estava a sentir estavam a impactar negativamente o meu laboratório e os serviços que uso desde ele.
Implementei portanto um workaground que até agora levou á estabilização do conjunto, sem erros ou crashes:

echo deadline > /sys/block/$device_ssd/queue/scheduler
echo 1 > /sys/block/$device_ssd/queue/iosched/fifo_batch
echo 3600 > /sys/block/$device_ssd/device/timeout

O $device_ssd é o scsi device atribuído pelo kernel ao vosso ssd. Recomendo colocarem estes valores no vosso initscript, rc.boot, init.local wtv.

Abraço,
Higgs