Como ativar a virtualização aninhada para instâncias de VM

Neste documento, veja como ativar a compatibilidade com a virtualização aninhada em instâncias de VMs do Compute Engine. Além disso, ele inclui as etapas básicas da inicialização e configuração de uma VM aninhada.

A virtualização aninhada inclui compatibilidade com as instruções de virtualização do processador Intel VT-x para as VMs do Compute Engine. Com a virtualização aninhada, você inicia normalmente uma instância da VM no Compute Engine e, em seguida, instala um hipervisor compatível com o KVM na instância da VM para que você possa executar outra instância da VM nesse hipervisor. Atualmente, outros hipervisores, como Hyper-V, ESX e Xen, não são compatíveis. A virtualização aninhada pode ser usada em qualquer instância de VM Linux em execução em uma plataforma Haswell ou mais recente.

Essa virtualização é ideal para aplicativos baseados em VM e cargas de trabalho onde não é viável converter ou importar suas imagens de VM para o Compute Engine. Por exemplo, você pode usar a virtualização aninhada para criar uma solução de recuperação de desastres para uma carga de trabalho local em execução em VMs baseadas no KVM. Assim, ocorreria o failover contínuo para VMs em execução no Compute Engine sem o tempo extra ou a orquestração necessária para converter sua VM baseada em KVM em uma imagem nativa do Compute Engine. Outra carga de trabalho ideal para a virtualização aninhada é uma biblioteca de validação de software que precisa testar e validar novas versões de um pacote de software em várias versões de diferentes sistemas operacionais compatíveis com KVM. Executar VMs aninhadas remove a necessidade de converter e gerenciar uma grande biblioteca de imagens do Compute Engine.

Antes de começar

Como a virtualização aninhada funciona

As VMs do Compute Engine são executadas em um hardware físico (o servidor host), chamado de ambiente L0. No servidor host, um hipervisor pré-instalado permite que um único servidor hospede várias VMs do Compute Engine, chamadas de L1 ou VMs nativas no Compute Engine. Na virtualização aninhada, você instala outro hipervisor no SO convidado L1 e cria VMs aninhadas, chamadas de VMs L2, usando o hipervisor L1. As VMs L1 ou nativas do Compute Engine que estão executando um hipervisor convidado e VMs aninhadas também podem ser chamadas de VMs do host.

Diagrama de virtualização aninhada

Restrições

  • A virtualização aninhada só pode ser ativada para VMs L1 em execução nos processadores Haswell ou posteriores. Se o processador padrão para uma zona for Sandy Bridge ou Ivy Bridge, use a seleção mínima de CPU para escolher Haswell ou posterior para uma determinada instância. Consulte a página Regiões e Zonas para verificar quais zonas são compatíveis.
  • A virtualização aninhada é compatível apenas com hipervisores baseados em KVM em execução nas instâncias do Linux. Os hipervisores ESX e Xen não são compatíveis.
  • Atualmente, a virtualização aninhada não é compatível com instâncias do Windows.

Versões de KVM testadas

O Google executa testes básicos de inicialização e integração de virtualização aninhada usando as seguintes combinações de VMs hospedeiras e aninhadas:

  • Debian 9 com o kernel versão 4.9 hospedando as seguintes VMs aninhadas:
    • CentOS 6.5 com kernel versão 2.6
    • Debian 9 com kernel versão 4.9
    • RHEL 5.11 com kernel versão 2.6
    • SLES 12 SP3 com kernel versão 4.4
    • Ubuntu 16.04 LTS com kernel versão 4.15
    • Windows Server 2008 R2
    • Windows Server 2016 Datacenter Edition
  • SLES 12 SP3 com a versão 4.4 do kernel hospedando as seguintes VMs aninhadas:
    • SLES 12 SP3 com kernel versão 4.4
  • Ubuntu 16.04 LTS com a versão do kernel 4.15 hospedando as seguintes VMs aninhadas:
    • Ubuntu 16.04 LTS com kernel versão 4.15

Se tiver problemas para executar VMs aninhadas em distribuições e versões de kernel/KVM não listadas aqui, reproduza o problema usando um dos ambientes acima como o sistema operacional convidado na instância do Compute Engine do host antes de relatar o problema.

Desempenho

Mesmo com a virtualização aninhada assistida por hardware, haverá um impacto no desempenho nas próprias VMs aninhadas e quaisquer aplicativos ou cargas de trabalho que funcionem nelas. Embora não seja possível prever a degradação exata do desempenho para um determinado aplicativo ou carga de trabalho, estima-se que haja um impacto de 10% para as cargas de trabalho vinculadas à CPU e que, para as cargas de trabalho vinculadas à E/S, ele seja muito maior.

Como ativar a virtualização aninhada em uma instância

É possível ativar a virtualização aninhada usando a API ou o componente gcloud. Para isso, crie uma imagem personalizada com uma chave de licença especial que ativa VMX na instância da VM L1 ou host e, em seguida, use essa imagem em uma instância que atenda às restrições para virtualização aninhada. A chave de licença não gera cobrança adicional.

  1. Crie um disco de inicialização a partir de uma imagem pública ou de uma imagem personalizada usando o sistema operacional. É possível pular essa etapa aplicando uma licença em um disco existente de uma de suas instâncias de VM.

    gcloud

    Use a ferramenta de linha de comando gcloud para criar um disco a partir de um disco de inicialização de imagem. Neste exemplo, crie um disco chamado disk1 a partir da família de imagens debian-9:

    gcloud compute disks create disk1 --image-project debian-cloud --image-family debian-9

    API

    Crie um disco disk1 a partir da família de imagens debian-9:

    POST https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/zones/us-central1-b/disks
    
    {
     "name": "disk1",
     "sourceImage": "/projects/debian-cloud/global/images/family/debian-9"
    }

    em que [PROJECT_ID] é o código do projeto.

  2. Com o disco de inicialização criado, ou um disco de inicialização de uma instância existente, crie uma imagem personalizada com a chave de licença especial necessária para a virtualização.

    gcloud

    Se você está criando uma imagem com a ferramenta de linha de comando "gcloud", forneça o seguinte URL de licença usando a sinalização "--licenses":

    https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx

    Por exemplo, o comando a seguir cria uma imagem chamada "nested-vm-image" em um disco de exemplo chamado "disk1":

    gcloud compute images create nested-vm-image \
      --source-disk disk1 --source-disk-zone us-central1-b \
      --licenses "https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx"

    API

    Na API, inclua a propriedade de licenças na sua solicitação de API:

    POST https://www.googleapis.com/compute/v1/projects/[PROJECT_ID]/global/images
    
    {
       "licenses": ["projects/vm-options/global/licenses/enable-vmx"],
       "name": "nested-vm-image",
       "sourceDisk": "zones/us-central1-b/disks/disk1"
    }

    em que [PROJECT_ID] é o código do projeto.

  3. Depois de criar a imagem com a licença exigida, é possível excluir o disco de origem se ele não for mais necessário.
  4. Crie uma instância de VM usando a nova imagem personalizada com a licença. Para isso, é preciso criar a instância em uma zona compatível com a plataforma de CPU Haswell ou mais recente. Por exemplo:
    gcloud compute instances create example-nested-vm --zone us-central1-b \
                  --image nested-vm-image
  5. Confirme se a virtualização aninhada está ativada na VM.
    1. Conecte-se à instância de VM. Por exemplo:
      gcloud compute ssh example-nested-vm
    2. Execute o comando a seguir para verificar se a virtualização aninhada está ativada. Uma resposta diferente de zero confirma que ela está ativada.
      grep -cw vmx /proc/cpuinfo

Como iniciar uma VM aninhada

É possível iniciar uma VM aninhada de várias maneiras. Nesta seção, mostramos um exemplo de como iniciar uma VM aninhada usando qemu-system-x86_64 em uma VM L1 que executa o Debian. Se você estiver com problemas para executar VMs aninhadas usando métodos diferentes deste processo documentado, reproduza seu problema usando este processo antes de relatar o problema como um bug.

  1. Conecte-se à instância de VM. Por exemplo:

    gcloud compute ssh example-nested-vm
    
  2. Atualize a instância de VM e instale alguns pacotes necessários:

    sudo apt-get update && sudo apt-get install qemu-kvm -y
    
  3. Faça o download de uma imagem do SO:

    wget https://people.debian.org/~aurel32/qemu/amd64/debian_squeeze_amd64_standard.qcow2
    
  4. Execute screen:

    screen
    
  5. Aperte "Enter" no prompt de boas-vindas da screen.

  6. Inicie a VM aninhada. Quando solicitado, faça login com user: root e password: root.

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -curses
    
  7. Verifique se a VM tem acesso externo:

    user@nested-vm:~$ wget google.com && cat index.html
  8. Quando terminar, pressione os botões Ctrl + a ou Ctrl + d para sair da VM.

Como iniciar uma ponte particular entre o host e VMs aninhadas

Para ativar as conexões entre o host e a VM aninhada, crie uma ponte particular. O seguinte exemplo é referente a uma VM L1 executando o Debian.

  1. Conecte-se à instância de VM. Por exemplo:

    gcloud compute ssh example-nested-vm
    
  2. Atualize a instância de VM e instale alguns pacotes necessários:

    sudo apt-get update && sudo apt-get install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
    
  3. Inicie a rede padrão que vem com o pacote libvirt:

    sudo virsh net-start default
    
  4. Verifique se você tem a ponte virbr0:

    sudo ifconfig -a
    
     eth0      Link encap:Ethernet  HWaddr 42:01:0a:80:00:02
               inet addr:10.128.0.2  Bcast:10.128.0.2  Mask:255.255.255.255
               UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
               RX packets:14799 errors:0 dropped:0 overruns:0 frame:0
               TX packets:9294 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:1000
               RX bytes:97352041 (92.8 MiB)  TX bytes:1483175 (1.4 MiB)
    
     lo        Link encap:Local Loopback
               inet addr:127.0.0.1  Mask:255.0.0.0
               inet6 addr: ::1/128 Scope:Host
               UP LOOPBACK RUNNING  MTU:65536  Metric:1
               RX packets:0 errors:0 dropped:0 overruns:0 frame:0
               TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:0
               RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
    
     virbr0    Link encap:Ethernet  HWaddr 5a:fa:7e:d2:8b:0d
               inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
               UP BROADCAST MULTICAST  MTU:1500  Metric:1
               RX packets:0 errors:0 dropped:0 overruns:0 frame:0
               TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:0
               RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  5. Crie uma interface fictícia:

    sudo modprobe dummy
    
  6. Adicione a interface fictícia à ponte:

    sudo brctl addif virbr0 dummy0
    
  7. Verifique se a interface foi adicionada:

    sudo brctl show
    
    bridge name    bridge id          STP enabled    interfaces
    virbr0         8000.6a20fa136bb6  yes            dummy0
  8. Crie uma interface tun para ir da VM de host para a VM aninhada:

    sudo tunctl -t tap0
    sudo ifconfig tap0 up
    
  9. Vincule a interface tun à VM da ponte:

    sudo brctl addif virbr0 tap0
    
  10. Verifique se a rede da ponte está configurada corretamente:

    sudo brctl show
    
    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.5254005085fe       yes              dummy0
                                                             tap0
  11. Faça o download de uma imagem do SO:

    wget https://people.debian.org/~aurel32/qemu/amd64/debian_squeeze_amd64_standard.qcow2
    
  12. Execute screen:

    screen
    
  13. Aperte "Enter" no prompt de boas-vindas da screen.

  14. Inicie a VM aninhada. Quando solicitado, faça o login com user: root e password: root.

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    
  15. Na VM aninhada, execute ifconfig para confirmar que a VM tem um endereço no espaço virbr0, como 192.168.122.89:

    user@nested-vm:~$ ifconfig
  16. Comece um servidor da Web fictício na porta 8000:

    user@nested-vm:~$ python -m SimpleHTTPServer
  17. Pressione os botões Ctrl + a ou Ctrl + a para sair da VM aninhada.

  18. Verifique se a VM pode dar um ping na VM aninhada:

    curl 192.168.122.89:8000
    

    A VM aninhada precisa retornar algo semelhante a:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    <title>Directory listing for /</title>
    <body>
    <h2>Directory listing for /</h2>
    <hr>
    <ol>
    <li><a href=".aptitude/">.aptitude/</a>
    <li><a href=".bashrc">.bashrc</a>
    <li><a href=".profile">.profile</a>
    </ol>
    <hr>
    </body>
    </html>
    

Como configurar uma VM aninhada para ser acessada externamente à VM de host

É possível configurar uma instância com várias interfaces de rede ou configurar uma instância usando um IP do alias para que as VMs externas à VM de host possam dar um ping na VM aninhada.

O exemplo a seguir configura sua VM de host e a VM aninhada para que a VM aninhada seja acessível em outras VMs na mesma rede usando IPs do alias. Esse procedimento é referente a uma VM L1 executando o Debian.

  1. Crie uma VM com virtualização aninhada ativa e inclua um intervalo de IP do alias e compatibilidade com o tráfego HTTP/HTTPS. Por exemplo:

    gcloud compute instances create example-nested-vm --image nested-vm-image \
        --tags http-server,https-server --can-ip-forward \
        --network-interface subnet=subnet1,aliases=/30
    
  2. Conecte-se à instância de VM. Por exemplo:

    gcloud compute ssh example-nested-vm
    
  3. Atualize a instância de VM e instale alguns pacotes necessários:

    sudo apt-get update && sudo apt-get install uml-utilities qemu-kvm bridge-utils virtinst libvirt-daemon-system libvirt-clients -y
    
  4. Inicie a rede padrão que vem com o pacote libvirt:

    sudo virsh net-start default
    
  5. Verifique se você tem a ponte virbr0:

    sudo ifconfig -a
     
     eth0      Link encap:Ethernet  HWaddr 42:01:0a:80:00:02
               inet addr:10.128.0.2  Bcast:10.128.0.2  Mask:255.255.255.255
               UP BROADCAST RUNNING MULTICAST  MTU:1460  Metric:1
               RX packets:14799 errors:0 dropped:0 overruns:0 frame:0
               TX packets:9294 errors:0 dropped:0 overruns:0 carrier:0
               collisions:0 txqueuelen:1000
               RX bytes:97352041 (92.8 MiB)  TX bytes:1483175 (1.4 MiB)

    lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

    virbr0 Link encap:Ethernet HWaddr 5a:fa:7e:d2:8b:0d inet addr:192.168.122.1 Bcast:192.168.122.255 Mask:255.255.255.0 UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

  6. Crie uma interface fictícia:

    sudo modprobe dummy
    
  7. Adicione a interface fictícia à ponte:

    sudo brctl addif virbr0 dummy0
    
  8. Verifique se a interface foi adicionada:

    sudo brctl show
    bridge name    bridge id          STP enabled    interfaces
    virbr0         8000.6a20fa136bb6  yes            dummy0
  9. Crie uma interface tun para ir da VM de host para a VM aninhada:

    sudo tunctl -t tap0
    sudo ifconfig tap0 up
    
  10. Vincule a interface tun à VM da ponte:

    sudo brctl addif virbr0 tap0
    
  11. Verifique se a rede da ponte está configurada corretamente:

    sudo brctl show
    
    bridge name     bridge id               STP enabled     interfaces
    virbr0          8000.5254005085fe       yes              dummy0
                                                             tap0
  12. Faça o download de uma imagem do SO:

    wget https://people.debian.org/~aurel32/qemu/amd64/debian_squeeze_amd64_standard.qcow2
    
  13. Execute screen:

    screen
    
  14. Aperte "Enter" no prompt de boas-vindas da screen.

  15. Inicie a VM aninhada. Quando solicitado, faça o login com user: root e password: root.

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    
  16. Na VM aninhada, execute ifconfig para confirmar que a VM tem um endereço no espaço virbr0, como 192.168.122.89:

    user@nested-vm:~$ ifconfig
  17. Comece um servidor da Web fictício na porta 8000:

    user@nested-vm:~$ python -m SimpleHTTPServer
  18. Pressione os botões Ctrl + a ou Ctrl + a para sair da VM aninhada.

  19. Verifique se a VM pode dar um ping na VM aninhada:

    curl 192.168.122.89:8000
    

    A VM aninhada precisa retornar algo semelhante a:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    <title>Directory listing for /</title>
    <body>
    <h2>Directory listing for /</h2>
    <hr>
    <ol>
    <li><a href=".aptitude/">.aptitude/</a>
    <li><a href=".bashrc">.bashrc</a>
    <li><a href=".profile">.profile</a>
    </ol>
    <hr>
    </body>
    </html>
    
  20. Na VM de host, configure o iptables para permitir o encaminhamento dela para a VM aninhada. Por exemplo, se você quer usar um IP do alias de 10.128.0.13 para encaminhar tráfego para a VM hospedada em 192.168.122.89:

    echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
    sudo iptables -t nat -A PREROUTING -d 10.128.0.13 -j DNAT --to-destination 192.168.122.89
    sudo iptables -t nat -A POSTROUTING -d 192.168.122.89 -j MASQUERADE
    sudo iptables -A INPUT -p udp -j ACCEPT
    sudo iptables -A FORWARD -p tcp -j ACCEPT
    sudo iptables -A OUTPUT -p tcp -j ACCEPT
    sudo iptables -A OUTPUT -p udp -j ACCEPT
    
  21. Em seguida, faça login em outra VM que esteja na mesma rede que a VM hospedada e faça uma solicitação curl para o IP do alias. Por exemplo:

    user@another-vm:~$ curl 10.128.0.13:8000

    A VM aninhada precisa retornar algo semelhante a:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
    <title>Directory listing for /</title>
    <body>
    <h2>Directory listing for /</h2>
    <hr>
    <ol>
    <li><a href=".aptitude/">.aptitude/</a>
    <li><a href=".bashrc">.bashrc</a>
    <li><a href=".profile">.profile</a>
    </ol>
    <hr>
    </body>
    </html>
    

Como solucionar problemas

O Google executa testes básicos de inicialização e integração de virtualização aninhada usando distribuições do Linux e versões de kernel/KVM específicas na instância do Compute Engine: Além disso, esses testes usam um processo específico. Antes de relatar os problemas como um bug, reproduza-os usando os seguintes itens:

A execução de grep -c vmx /proc/cpuinfo retorna 0 e informa que minha VM não está ativada para aninhamento.

  1. Inicie a VM com uma plataforma de CPU da Haswell ou posterior.
  2. Use a licença correta com a imagem da VM.

Não consigo sair da minha VM aninhada.

Se você não executou a screen antes de cada sessão da VM aninhada, encerre a VM aninhada ou elimine o processo de outro terminal. Para encerrar a VM aninhada, execute o comando poweroff nela. Como alternativa, efetue login na VM do host em outro terminal e elimine o processo. Em seguida, execute a screen na VM do host antes de iniciar uma nova VM aninhada.

Minhas regras do iptables não estão encaminhando tráfego para minha VM aninhada.

  • O iptables soluciona regras de cima para baixo. Verifique se as suas regras têm maior prioridade que as outras.
  • Verifique se não há regras conflitantes que interceptem seus pacotes.
  • Limpe seu iptables:

    1. Primeiro, defina as políticas padrão:

      sudo iptables -P INPUT ACCEPT
      sudo iptables -P FORWARD ACCEPT
      sudo iptables -P OUTPUT ACCEPT
      
    2. Em seguida, elimine todas as tabelas e cadeias e exclua cadeias não padrão:

      sudo iptables -t nat -F
      sudo iptables -t mangle -F
      sudo iptables -F
      sudo iptables -X
      
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Compute Engine