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 executar outra instância da VM nesse hipervisor. A virtualização aninhada pode ser usada em qualquer instância de VM Linux em execução em uma plataforma Haswell ou mais recente. Para outras restrições, consulte esta subseção.

Essa virtualização é ideal para aplicativos baseados em VM e cargas de trabalho em que 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 hypervisores Hyper-V, ESX e Xen não são compatíveis.
  • As VMs do Windows não são compatíveis com virtualização aninhada; isto é, as máquinas virtuais host precisam executar um sistema operacional Linux. No entanto, as VMs aninhadas podem executar determinados sistemas operacionais Windows (descritos abaixo).

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 --zone us-central1-b

    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 \
                  --min-cpu-platform "Intel Haswell" \
                  --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, você vê 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. Pressione "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, separe-se da sessão de tela com os comandos Ctrl + a e Ctrl + d.

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 tun para ir da VM de host para a VM aninhada:

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

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

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

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

    screen
    
  10. Pressione "Enter" no prompt de boas-vindas da screen.

  11. Inicie a VM aninhada:

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    
  12. Quando solicitado, faça login com user: root, password: root.

  13. 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
  14. Inicie um servidor da Web fictício na porta 8000:

    user@nested-vm:~$ python -m SimpleHTTPServer
  15. Separe-se da sessão de tela com os comandos Ctrl + a e Ctrl + d.

  16. Verifique se a VM pode enviar ping para a 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.

No exemplo a seguir, você 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 usa uma sub-rede imaginária denominada subnet1 que foi criada anteriormente. É possível substituir subnet1 pelo nome de sua própria sub-rede ou criar uma nova sub-rede chamada subnet1.

Finalmente, observe que este procedimento é destinado a uma VM L1 com 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 \
        --min-cpu-platform "Intel Haswell" \
        --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 tun para ir da VM de host para a VM aninhada:

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

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

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

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

    screen
    
  11. Pressione "Enter" no prompt de boas-vindas da screen.

  12. Inicie a VM aninhada:

    sudo qemu-system-x86_64 -enable-kvm -hda debian_squeeze_amd64_standard.qcow2 -m 512 -net nic -net tap,ifname=tap0,script=no -curses
    
  13. Quando solicitado, faça login com user: root, password: root.

  14. 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
  15. Inicie um servidor da Web fictício na porta 8000:

    user@nested-vm:~$ python -m SimpleHTTPServer
  16. Separe-se da sessão de tela com os comandos Ctrl + a e Ctrl + d.

  17. Verifique se a VM pode enviar ping para a VM aninhada:

    curl 192.168.122.89:8000
    

    A VM aninhada 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>
    
  18. Na VM do host, configure iptables para permitir o encaminhamento da VM do host para a VM aninhada. Para a imagem da máquina virtual L2 usada nestas instruções (debian_squeeze_amd64_standard.qcow2), é necessário primeiro limpar as tabelas do IP:

    sudo iptables -F
    

    Em seguida, determine o IP do alias da VM:

    ip route show table local
    

    A VM retornará algo semelhante ao resultado abaixo. Neste exemplo, há dois endereços IP associados ao dispositivo Ethernet da VM, eth0. O primeiro, 10.128.0.2, é o endereço IP principal da VM, retornado por sudo ifconfig -a. O segundo, 10.128.0.13, é o endereço IP do alias da VM.

    local 10.128.0.2 dev eth0 proto kernel scope host src 10.128.0.2
    broadcast 10.128.0.2 dev eth0 proto kernel scope link src 10.128.0.2
    local 10.128.0.13/30 dev eth0 proto 66 scope host
    broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
    local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
    local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
    broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
    broadcast 192.168.122.0 dev virbr0 proto kernel scope link src
    192.168.122.1 linkdown
    local 192.168.122.1 dev virbr0 proto kernel scope host src 192.168.122.1
    broadcast 192.168.122.255 dev virbr0 proto kernel scope link src
    192.168.122.1 linkdown
    

    Para encaminhar o tráfego do IP de alias (10.128.0.13) para a VM aninhada (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 -s 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
    
  19. Em seguida, faça login em outra VM que esteja na mesma rede que a VM hospedada e faça uma solicitação curl ao 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, limpe 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