KVM, Xen ou LXC: qual virtualização seu VPS usa
Veja se seu VPS tem kernel próprio, swap real e virtualização aninhada. Compare KVM, Xen e LXC e descubra se o steal time mede seu servidor ou o host.
O que o seu plano VPS está realmente a vender
KVM, Xen e LXC são as três famílias de virtualização em que um plano VPS pode ser baseado, e essa escolha não é um detalhe do rack do provedor. Ela determina se você recebe o seu próprio kernel. Tudo o que interessa ao comprador resulta desse único facto: carregar módulos, controlar o swap, executar virtualização aninhada, saber se /proc descreve o seu servidor ou o servidor de outra pessoa e se o steal time pode ser medido.
A virtualização completa (KVM e Xen HVM) fornece a cada tenant um kernel e uma máquina virtual. O Xen paravirtualizado também fornece um kernel, mas um kernel que sabe que é um guest e pede ao hypervisor para executar trabalho privilegiado em seu nome. Um plano baseado em contentores (LXC ou a linha OpenVZ e Virtuozzo) fornece um sistema de ficheiros e um conjunto de namespaces no kernel do provedor. Os três modelos são vendidos com as mesmas três letras.
KVM vs Xen vs LXC: um kernel por instância ou um kernel partilhado
No KVM e no Xen, uname -r identifica o seu kernel. Pode instalar outro, carregar um módulo nele e reiniciar para o utilizar. Nada do que fizer nesse kernel afeta outro tenant. Num plano de contentores, uname -r identifica o kernel do fornecedor, executado no host e partilhado com todos os outros contentores dessa máquina. Não pode alterá-lo, e apt install linux-image-generic vai extrair ficheiros que nunca arrancam.
Esta única diferença é mais importante do que qualquer ficha técnica. Leia o resto deste guia como consequências dela.
Virtualização completa: KVM e Xen HVM
KVM (kernel-based virtual machine) é um módulo do kernel Linux que transforma um host Linux comum num hypervisor, utilizando as instruções Intel VT-x ou AMD-V incorporadas no CPU. O QEMU fornece o hardware virtual à sua volta: disco, placa de rede e consola série. O Xen tem um desenho diferente. O Xen é o seu próprio hypervisor e arranca antes do Linux. Um domínio de controlo privilegiado, chamado dom0, executa a stack de gestão, e cada tenant é um domU. O Xen HVM (hardware virtual machine) utiliza as mesmas extensões do CPU que o KVM, normalmente com drivers paravirtualizados para disco e rede, porque o hardware emulado é lento. Essa combinação chama-se PVHVM.
Para um tenant, os dois comportam-se quase da mesma forma. Tem um kernel, um bootloader, um dispositivo de bloco real, um modprobe funcional, um /proc válido, a sua própria swap e um reboot que efetivamente arranca. Se o fornecedor permitir anexar uma ISO, pode instalar uma distribuição que nunca foi disponibilizada por ele.
O custo está na densidade. Os seus 4 GB ficam reservados para a sua máquina e não podem ser emprestados a um vizinho enquanto estão inativos, e cada guest inclui um processo QEMU, as suas próprias tabelas de páginas e a sua própria cache de páginas. Esse custo explica por que motivo um plano KVM tem um preço superior ao de um plano de contentores com os mesmos valores.
Xen paravirtualizado e como reconhecê-lo
O Xen PV surgiu antes de as CPUs terem instruções de virtualização. Em vez de intercetar instruções privilegiadas, o kernel convidado é modificado para chamar diretamente o hypervisor. Funciona sem VT-x, que era precisamente o objetivo em 2005. O kernel é carregado a partir da sua própria imagem de disco pelo pygrub ou pelo pvgrub. Portanto, é o seu kernel, mas tem de ser compilado com suporte para convidados PV.
Os sinais de que está num destes sistemas são: lscpu indica o tipo de virtualização como para em vez de full, /sys/hypervisor/type existe e identifica o Xen, e os discos são xvda em vez de vda ou sda. As ferramentas que leem as tabelas SMBIOS ou DMI não encontram dados, porque um convidado PV não tem firmware para as publicar.
A consequência permanente é não poder usar virtualização aninhada. Um convidado PV nunca recebe as extensões de virtualização da CPU. Portanto, nenhum hypervisor pode ser executado dentro dele. O Xen em si não está obsoleto. O Xen PV é que perdeu relevância, e a direção do próprio projeto passou para PVH e HVM. Se um plano disser "Xen", confirme qual dos tipos está incluído. HVM é um VPS moderno normal. PV é um plano que deve ter um preço mais baixo.
VPS em contentores: LXC e a linha OpenVZ
Um VPS em contentor é um conjunto de namespaces Linux (vistas separadas de IDs de processos, montagens, interfaces de rede, hostname e utilizadores) mais cgroups (grupos de controlo, os limites de recursos do kernel) executados no kernel do fornecedor. O seu init é um processo no host. O seu ls executa diretamente no kernel do host, sem emulação nem um segundo escalonador pelo meio. É por isso que os contentores são rápidos e permitem elevada densidade.
Os nomes apresentados numa página de encomenda são LXC, contentores Proxmox VE (que são LXC), OpenVZ e Virtuozzo. OpenVZ 7 e Virtuozzo são os descendentes comerciais da mesma ideia.
Quatro aspetos mudam para si:
- Módulos.
modprobenão vai inserir nada. Se o WireGuard, o ZFS ou um módulo netfilter específico não estiver já no kernel do fornecedor, não poderá utilizá-lo. sysctl. A maior parte de/proc/sysé apenas de leitura. A rede é um namespace real, por issonet.ipv4.ip_forwarde os elementos vizinhos são normalmente graváveis. Parâmetros globais do sistema, comovm.swappinessoufs.file-max, pertencem ao host.- Contentores aninhados. O Docker dentro de um contentor LXC só funciona quando o fornecedor ativa o nesting e o controlador de armazenamento é compatível. Teste-o antes de comprar, em vez de assumir que funciona.
- A versão do kernel. Ficará sujeito ao calendário de atualizações do fornecedor, incluindo os reboots.
Como saber qual dos dois comprou
Execute estes comandos no servidor e analise as respostas em conjunto. Nenhum comando isolado é conclusivo.
systemd-detect-virt
systemd-detect-virt -c
lscpu | grep -iE 'hypervisor|virtualization'
uname -r
ls /lib/modules/$(uname -r) 2>/dev/null | head -n 3
cat /sys/hypervisor/type 2>/dev/nullsystemd-detect-virt imprime um identificador curto de um vocabulário fixo. No lado da máquina, inclui kvm, qemu, xen, amazon e vmware. No lado do contentor, inclui lxc, lxc-libvirt, openvz, docker e systemd-nspawn. Quando não deteta nada, imprime none e termina com um código diferente de zero. A forma -c só responde para tecnologias de contentores. Por isso, qualquer resposta diferente de none esclarece a questão, independentemente do que dizia a página de vendas.
lscpu identifica o fornecedor do hypervisor e indica se o tipo de virtualização é full ou para. É assim que se distingue Xen HVM de Xen PV. /sys/hypervisor/type existe apenas no Xen.
A verificação /lib/modules é a que muitas pessoas ignoram e é a mais direta. Se o diretório correspondente à versão do kernel em execução estiver ausente ou vazio, embora o sistema esteja claramente a executar esse kernel, o kernel não veio do seu sistema de ficheiros. Veio do host, e a respetiva árvore de módulos nunca foi instalada na sua imagem. Isso indica um contentor.
Para obter uma segunda opinião independente, sudo apt install -y virt-what && sudo virt-what executa os testes de deteção como uma ferramenta dedicada. Precisa de root e não imprime nada em bare metal.
Por que /proc descreve a máquina errada num contentor
Numa guest KVM ou Xen, /proc/meminfo é o registo contabilístico do seu próprio kernel relativamente à memória que o hypervisor lhe atribuiu. Essa informação é verdadeira para a sua máquina e não diz nada sobre o host. Esse é o objetivo de uma máquina virtual.
Num contentor não existe um segundo kernel a fazer essa contabilização, por isso /proc corresponde ao /proc do host. O LXCFS é um pequeno sistema de ficheiros que reescreve alguns desses ficheiros para corresponderem aos limites do seu cgroup. Abrange /proc/cpuinfo, /proc/meminfo, /proc/stat, /proc/uptime, /proc/swaps, /proc/diskstats e /sys/devices/system/cpu/online. O Proxmox monta-o por predefinição. Muitos providers mais pequenos não o fazem. Nesse caso, free -m indica a memória total do host, nproc pode indicar todos os cores da máquina e uptime indica há quanto tempo o host está em execução.
Isto não é apenas uma questão estética, porque o software dimensiona os próprios recursos com base nesses ficheiros. nginx com worker_processes auto conta os cores que consegue ver. make -j$(nproc) num host com 64 cores e uma quota de 2 cores inicia 64 compiladores. Uma JVM ou uma base de dados que escolha o tamanho da cache a partir de MemTotal pode escolher um valor que o seu cgroup irá recusar, e o kernel termina o processo quando este atinge o limite. Essa terminação fica registada no log do kernel do host, que não pode ler.
Os valores autoritativos estão no cgroup, não em /proc:
cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.current
cat /sys/fs/cgroup/cpu.maxEstes são caminhos de cgroup v2, utilizados pelas distribuições atuais. memory.max ao ler max significa que não está definido qualquer limite nesse nível. cpu.max mostra uma quota e um período em microssegundos, por isso 200000 100000 corresponde a dois cores de tempo de CPU por período. Num host mais antigo com cgroup v1, os mesmos valores encontram-se em /sys/fs/cgroup/memory/memory.limit_in_bytes e /sys/fs/cgroup/cpu/cpu.cfs_quota_us.
Swap e quem realmente o controla
No KVM e no Xen, o swap é seu. É um ficheiro ou uma partição no seu disco, e o seu kernel gere a paginação.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
swapon --showswapon --show deverá agora listar o ficheiro com o respetivo tamanho e prioridade. Se swapon recusar o ficheiro, crie-o com dd if=/dev/zero of=/swapfile bs=1M count=2048, porque um ficheiro pré-alocado com extents não escritos é rejeitado em alguns sistemas de ficheiros. Adicione /swapfile none swap sw 0 0 a /etc/fstab, ou o swap desaparecerá depois do próximo reboot.
Num contentor, nada disso é seu. swapon requer uma capability que um contentor sem privilégios não possui, por isso a criação do seu próprio ficheiro de swap falha por falta de permissões e nunca chega ao disco. O que o plano chama de swap é uma definição de cgroup no host, memory.swap.max no cgroup v2, suportada pelos próprios dispositivos de swap do host. Os planos OpenVZ mais antigos vendiam uma atribuição de "vswap" que se comportava mais como um crédito temporário do que como espaço em disco. Pode consultar o limite. Não controla o dispositivo que está por baixo dele.
Virtualização aninhada e o sinalizador de CPU que engana
A virtualização aninhada consiste em executar um hypervisor dentro do seu VPS: um guest QEMU, uma box Vagrant ou um laboratório de virtualização aninhada com as suas próprias VMs. É necessário que duas condições sejam cumpridas. O fornecedor tem de ativar a virtualização aninhada no host, e o seu guest tem de receber as extensões de virtualização da CPU.
lscpu | grep -i virtualization
ls -l /dev/kvm
sudo apt install -y cpu-checker && sudo kvm-okNum guest KVM com virtualização aninhada ativada, /dev/kvm existe e kvm-ok indica claramente se a aceleração pode ser utilizada. Em Xen HVM, isso é tecnicamente possível, mas raramente é disponibilizado. Em Xen PV, não pode acontecer.
Num container, a verificação falha de uma forma esclarecedora. /proc/cpuinfo é o ficheiro do host, por isso o sinalizador vmx ou svm está presente e é genuinamente verdadeiro: a CPU física que está por baixo tem realmente essas instruções. Ainda assim, elas não lhe pertencem. Não existe /dev/kvm no seu namespace, não pode carregar o módulo kvm_intel e o sinalizador que acabou de consultar descreve a máquina em que é um guest, não uma máquina que controla. Este é o caso mais claro da regra geral. Num container, /proc descreve o namespace e o hardware que o rodeia, não um servidor que lhe pertença.
AES-NI e os recursos de CPU expostos pelo seu plano
AES-NI (advanced encryption standard new instructions) é um conjunto de instruções de CPU que torna a encriptação AES várias vezes mais rápida do que os mesmos cálculos implementados em software. A terminação TLS, a encriptação de discos, o SSH e os processos de backup dependem destas instruções.
No KVM, os recursos que o guest vê são determinados pelo modelo de CPU que o fornecedor configurou para o QEMU. Com host passthrough, o guest vê as flags reais. Com um modelo genérico como qemu64, ou com uma baseline deliberadamente antiga escolhida para permitir a migração de guests entre hosts incompatíveis, a flag aes pode estar ausente, e o OpenSSL recorre silenciosamente ao processamento em software.
lscpu | grep -ow aes | head -n 1
openssl speed -evp aes-128-gcm
env OPENSSL_ia32cap='~0x200000000000000:~0x20000000000:~0x0:~0x0:~0x0' openssl speed -evp aes-128-gcmO terceiro comando é o exemplo do manual do OpenSSL para desativar essas instruções dentro da biblioteca: limpa o bit AES-NI e o bit VAES, mantendo os restantes. Compare os dois valores de throughput. Se forem próximos, o caminho rápido não estava a ser usado desde o início. Nesse caso, vale a pena verificar corretamente o AES-NI numa VPS durante os cinco minutos anteriores à contratação do plano.
Um contentor não tem um modelo de CPU próprio, por isso as flags em /proc/cpuinfo são as flags reais do host e aplicam-se a si. Esta é uma vantagem real dos planos baseados em contentores. É também o único ponto deste guia em que o kernel partilhado funciona a seu favor.
De onde vem o steal time e por que um contentor não o tem
Steal time é o tempo em que a sua CPU virtual estava pronta para executar, mas não executou porque o hypervisor estava a executar outra carga. Este valor aparece como st em top e vmstat, e como o oitavo campo da linha cpu em /proc/stat.
Um guest não consegue medir isto sozinho, porque não está a executar enquanto o tempo é retirado. O hypervisor tem de informar o guest. O KVM escreve um total acumulado numa página que o guest regista através da sua interface de relógio paravirtualizado, e o Xen mantém uma área de estado de execução por vCPU para a mesma finalidade. O valor lido é a própria declaração do hypervisor, o que explica por que existe e por que é razoável confiar nele.
Um steal elevado significa que o host está sobrealocado e que os vizinhos estão ocupados nesse momento. Este valor mostra diretamente a relação entre as vCPUs vendidas e os cores físicos, e ler o steal time para detetar um vizinho ruidoso é a única medição que indica se um plano tem realmente o tamanho anunciado.
vmstat 1 5
cat /sys/fs/cgroup/cpu.statNum contentor, essa coluna não se altera porque não existe um hypervisor entre si e o scheduler. Os seus processos entram na fila juntamente com os processos de todos os outros tenants, como tarefas comuns no próprio scheduler de CPU do host. A contenção manifesta-se simplesmente quando o trabalho demora mais tempo, sem um contador que identifique a causa. O equivalente mais próximo é o throttling da quota: quando o provider define cpu.max, /sys/fs/cgroup/cpu.stat conta os períodos de nr_throttled e throttled_usec microssegundos passados à espera da próxima janela de quota. Isto abrange apenas a sua própria quota, nunca a concorrência dos vizinhos. Atenção: se o host de contentores do provider for uma máquina virtual, pode aparecer um valor de steal em /proc/stat, mas esse valor pertence ao host, não a si.
Excesso de alocação e por que o plano de containers é mais barato
A resposta honesta é curta. Um plano de containers custa menos porque o provedor partilha mais recursos da mesma máquina entre mais pessoas.
A memória é onde a diferença é maior. A RAM de um guest KVM fica comprometida com ele, portanto um host com 256 GB vende aproximadamente 256 GB de guests, descontando a sobrecarga. O limite de memória de um container é um teto, não uma reserva, e a memória que um container não está a usar fica imediatamente disponível para os outros. Por isso, o provedor pode vender limites cuja soma corresponde a várias vezes a RAM física e estar correto quase sempre. Nada é falsificado. Funciona até haver tenants suficientes ocupados ao mesmo tempo. Depois, deixa de funcionar para todos.
A CPU sofre excesso de alocação em todos os tipos de plano, incluindo KVM, porque são vendidos mais vCPUs do que o número de cores. O disco usa thin provisioning em quase todos os ambientes. Os containers aumentam ainda mais a densidade: um kernel, uma page cache e nenhum processo QEMU por guest. Assim, um host suporta várias vezes mais tenants.
O que se perde é isolamento, e essa é uma troca de engenharia real, não uma história para assustar. Todos partilham um kernel, portanto um bug no kernel torna-se um problema partilhado, e uma fuga de um container chega diretamente ao host. Sair de uma máquina virtual exige um bug no hypervisor, que é um alvo muito menor e mais difícil de explorar. Também fica sujeito ao calendário de atualizações do kernel e de reinícios do provedor. Se algum destes pontos for importante para si, leia como é realmente a segurança do alojamento VPS antes de escolher apenas pelo preço.
Qual escolher
Escolha KVM quando precisar do seu próprio kernel: módulos WireGuard ou ZFS, uma versão específica do kernel, virtualização aninhada, controlo real sobre a swap ou um limite de isolamento que consiga explicar a um auditor. Escolha um plano de containers quando estiver a executar serviços comuns com um orçamento limitado, o kernel do fornecedor estiver atualizado e tiver confirmado que as funcionalidades de que depende já estão compiladas nele. Para a maioria dos casos, trate Xen HVM como equivalente a KVM e faça esta pergunta antes de comprar qualquer serviço que ainda seja vendido como Xen PV.
Existem dois modelos fora desta divisão. As microVMs Firecracker fornecem a cada tenant um kernel real, com custos de arranque próximos dos de um container. É este o modelo usado pelas plataformas serverless. Os containers de sistema Incus permitem executar o modelo de containers no hardware que controla. Esta é uma situação diferente de comprar um serviço baseado nesse modelo. Se a terminologia for o principal obstáculo, o que é realmente um VPS e a diferença entre um VPS, uma VM e uma VPC explicam os termos que este guia pressupõe que já conhece.
FAQ
Como sei se o meu VPS usa KVM ou é um contentor?
Execute systemd-detect-virt -c. Qualquer resposta diferente de none significa que está dentro de um contentor, independentemente do nome do produto associado ao plano. Confirme de mais duas formas, porque a deteção pode ser enganada. lscpu identifica um fornecedor de hypervisor e indica se o tipo de virtualização é completa ou para. ls /lib/modules/$(uname -r) está ausente ou vazio num contentor, porque o kernel em execução veio do host e a respetiva árvore de módulos nunca foi instalada no seu sistema de ficheiros. sudo virt-what fornece uma resposta independente através de uma ferramenta criada especificamente para esta questão.
Porque é que free -m mostra muito mais memória do que a incluída no meu plano?
Está num plano de contentor sem o LXCFS montado. Por isso, /proc/meminfo é o ficheiro do host e free reporta corretamente a memória do host. O seu limite real é definido pelo cgroup. Consulte /sys/fs/cgroup/memory.max para ver o limite e /sys/fs/cgroup/memory.current para ver a utilização atual, ou /sys/fs/cgroup/memory/memory.limit_in_bytes num host cgroup v1 mais antigo. Configure qualquer serviço que dimensione uma cache ou um conjunto de workers a partir desse valor, e não de free.
Posso executar Docker ou WireGuard num VPS LXC?
Por vezes, mas nunca devido a algo que instale. Ambos dependem do kernel do fornecedor, porque não pode carregar um módulo nesse kernel. O WireGuard funciona quando o módulo já está presente no host e é exposto ao seu ambiente. Caso contrário, a implementação em userspace wireguard-go é a alternativa. O Docker precisa que o fornecedor permita o nesting e de um controlador de armazenamento que funcione dentro de um contentor. Pergunte antes de comprar ou teste durante um período que possa cancelar.
Porque é que o meu VPS de contentor nunca reporta tempo de steal?
O tempo de steal existe apenas quando um hypervisor agenda uma CPU virtual. É reportado porque esse hypervisor escreve o valor numa página que o seu kernel lê. Um contentor não tem um hypervisor por baixo. Os seus processos são tarefas normais no scheduler do host. Por isso, a contenção manifesta-se como uma maior duração de todas as operações, sem um contador que a identifique. Consulte /sys/fs/cgroup/cpu.stat: nr_throttled e throttled_usec contam o tempo que o seu cgroup passou à espera da próxima janela de quota de CPU. Esse é o equivalente mais próximo de steal num contentor.