Máquinas Virtuais e Containers

Prof. Filippo Valiante Filho


A virtualização permite, essencialmente, desacoplar, ou dissociar recursos lógicos dos recursos físicos subjacentes. Existem vários níveis de virtualização, ou desse tipo de abstração se assim preferir, nos sistemas computacionais. A própria definição de Sistema Operacional é a de oferecer uma máquina virtual padronizada aos usuários e aplicações. No funcionamento do computador utilizam-se memória virtual e volumes lógicos (LVM). Há VPNs e VLANs em redes. Realidade virtual e aumentada têm estado em moda mais recentemente. E poderíamos esticar bastante esta lista.

Mas o tipo de máquina virtual (VM — Virtual Machine) que nos interessa aqui, inicialmente, são os chamados hipervisores. Essa história se inicia na década de 60 e foi se desenvolvendo para solucionar alguns problemas, ou gerar determinadas comodidades, como permitir retrocompatilidade e isolar aplicações e usuários, garantindo maior segurança e melhor utilização dos recursos. A partir de 1999, a virtualização ganhou novo impulso com a chegada à arquitetura x86 por meio da VMware e, em especial, com o acréscimo de suporte à virtualização em hardware nessa arquitetura promovidos pela Intel e AMD ao longo da década de 2000. Mais recentemente os containers se juntaram ao leque de opções para virtualização. O projeto Linux Containers (LXC) foi criado em 2008 e o famoso Docker em 2013.

Além das aplicações mencionadas, exploraremos outras e também algumas implicações da virtualização e conteinerização, bem como alguns de seus principais conceitos a seguir. Se você ainda não se convenceu da importância do tema, pode começar conferindo a lista de aplicações no último tópico "contextualizando".

Máquinas Virtuais

As máquinas virtuais consistem em uma abstração do hardware físico, ou seja, uma máquina puramente lógica, que se comporta como um computador real. Do ponto de vista do usuário, a máquina virtual (VM) é um sistema computacional como outro qualquer. Um usuário não tem como saber se está interagindo com uma máquina virtual ou com uma máquina física (bare metal). Do ponto de vista do kernel que executa a máquina virtual, a máquina virtual é um sistema puramente lógico e se constitui de uma série de arquivos que armazenam a configuração da máquina virtual, seu estado de memória, os conteúdo dos discos (memória secundária) da máquina virtual, arquivo de log e eventuais "instantâneos" da máquina virtual, chamados snapshots.

Os snapshots são uma espécie de "backup a quente" do sistema, que armazenam o conteúdo da memória secundária e da memória principal, com todos os processos em execução, permitindo que se possa retornar àquele ponto específico posteriormente, clonar a VM, fazer com que a VM possa ser executada em outro host físico (migração), etc.



A "mágica" da virtualização é feita por um software chamado hipervisor (hypervisor) que é executado no sistema operacional da máquina física. Ele também é chamado de monitor de máquinas virtuais (Virtual Machine Monitor). Como a máquina virtual é do ponto de vista lógico um computador como outro qualquer, ela também precisa de um sistema operacional, chamado de "guest", ou convidado, que pode ser diferente do sistema operacional da máquina física ("host"). Aliás, é possível haver múltiplas máquinas virtuais em execução em uma máquina física, todas com sistemas operacionais distintos. O que se precisa respeitar é a arquitetura computacional (x86, ARM) e a capacidade do sistema físico.

Há dois tipos de hipervisores. Os hipervisores tipo 1, também chamados de bare metal, que se constituem basicamente de um kernel de SO com as funções de hipervisor. É o tipo mais usado em servidores e data centers. Nessas máquinas não usamos diretamente os recursos da máquina física, apenas das máquinas virtuais. A lista de exemplos inclui as soluções principais da VMware, Xen, versões do Microsoft Hyper-V, Linux KVM e o novo XCP-ng, baseado no Xen.
 


Os hipervisores tipo 2, ou hosted (hospedados), rodam como uma aplicação sobre um sistema operacional instalado em uma máquina física (host, ou hospedeira). Isso é feito porque normalmente também queremos executar aplicações no sistema operacional host. Por exemplo, colocamos um servidor web na máquina virtual e usamos o navegador da máquina física para acessá-lo. A lista de exemplos aqui inclui o VMware workstation, a versão específica do Microsoft Hyper-V, Gnome Boxes e o VirtualBox.



Por se tratar de um software open source, gratuito, multiplataforma, fácil de usar e muito bom. O VirtualBox acaba sendo a melhor recomendação para quem deseja se iniciar no mundo da virtualização e, mesmo para os mais avançados, ainda é uma das melhores opções. Ele está disponível em https://www.virtualbox.org/.


Dica! Além de criar máquinas virtuais através das imagens dos sistemas operacionais, a Bitnami oferece uma série de aplicações disponíveis como máquinas virtuais (e também pra nuvens) em seu catálogo de aplicação: https://bitnami.com/stacks.


Containers de Sistema - Linux Containers (LXC/LXD)

Na prática eles possuem um comportamento muito similar ao de uma máquina virtual, mas na verdade são como que novas instâncias do sistema, implementando todas as técnicas disponíveis para isso. Tratam-se de "full system" containers, ou containers de máquina. Os containers Linux compartilham o kernel da máquina real, de modo a oferecer um isolamento do sistema sem todo o overhead de uma VM tradicional, tanto que vem sendo chamados de "lightervisors". Uma limitação dos containers é que ao compartilhar o kernel da máquina física (ou virtual) onde são executados, tratam-se de containers Linux rodando em máquinas Linux em com o mesmo kernel do host. Você pode trocar todas as bibliotecas e frameworks do seu container, mas o kernel será sempre o mesmo do host. O site oficial do projeto é https://linuxcontainers.org/.



 

O kernel do sistema é compartilhado, mas é possível executar distribuições diferentes do sistema base no container. As imagens de sistema disponíveis oficialmente se encontram no link https://images.linuxcontainers.org e também é possível criar suas próprias imagens e publicá-las em um repositório público, ou mantê-las apenas para uso local.

 

Para isolar o container são usados recursos de segurança já existentes no mundo Unix/Linux, como namespaces, chroot, cgroups, etc. Embora em teoria esse isolamento seja inferior ao proporcionado por uma VM, na prática não há restrições para a maioria das aplicações.

 

É possível usar containers dentro de VMs e containers dentro de containers também. Também é possível fazer live migration de containers, tirar snapshots, gerar imagens de containers personalizadas, etc.

 

Ao se criar um container, ele compartilha exatamente os mesmos recursos da máquina real. Na verdade é uma aplicação rodando em bare metal mesmo! Mas é possível restringi-los da mesma forma que em um hipervisor tradicional. Por exemplo limitar a quantidade de CPUs vista pelo container, a memória, ou o espaço em disco.

 

Note que a ideia aqui é de um container de sistema completo, com "n" aplicações, diferentemente de containers de aplicação como Docker e Rocket (CoreOS), onde há um container para cada aplicação. Esse tipo de container também é chamado de container de processo. O conceito também é diferente de sistemas de distribuição de aplicação como o snap, que por vezes são referenciados como containers de pacotes, ou containers de pacotes de software, que encapsulam uma única aplicação em específico. Falaremos mais sobre esses outros tipos de containers na sequência.


Os containers Linux funcionam excelentemente bem para a maioria das aplicações de servidores, mas ainda possuem limitações para configurações avançadas de rede e para a utilização de periféricos da máquina física dentro dos containers.


Uma das grandes vantagens dos containers é viabilizar o mesmo ambiente para desenvolvimento e "produção". Como o grau de abstração do hardware chega ao nível da aplicação, o mesmo container testado pelo desenvolvedor será utilizado no servidor, do pequeno ao grande porte, do servidor local a um grande data center de um provedor de nuvem.


Acesse o Microtutorial de Containers LXC/LXD!



Containers de Aplicação


Conforme mencionado no item anterior, plataformas como Docker e Rkt são containers de aplicação. A ideia básica é que cada aplicação rode em um container, de forma a isolá-la do sistema operacional e das demais aplicações. E no caso estamos falando mais precisamente de cada processo. Um sistema comercial que possua um banco de dados e mais três módulos rodaria em 4 containers, um para cada módulo e outro para o banco.


O Docker baseou-se e era executado inicialmente sobre o LXC. Mas o projeto evoluiu e, por exemplo, firmou uma parceria com a Microsoft para suportar containers de aplicação Windows e Linux. De fato o Docker é hoje um produto multiplataforma, compatível com Linux, Windows e MacOS. Com certeza uma das razões para que ele tenha se popularizado tanto de forma a se tornar praticamente sinônimo de container. A plataforma Docker também cuida das máquinas virtuais necessárias para garantir que containers de diferentes sistemas operacionais (Windows e Linux, por exemplo) possam ser executados em um mesmo SO host. Os containers de aplicação podem ser executados em bare metal, em uma máquina virtual, ou em um container de sistema. Ferramentas como a Docker Compose permitem que aqueles diversos containers que compões um sistema possam ser integrados, ou devidamente interligados e coordenados, de forma a atuar como um único sistema. 


Outra importantíssima plataforma relacionada é a Kubernetes (K8s), que gerencia containers de aplicação, realizando sua orquestração. Isto é, ela cria e destrói containers conforme a necessidade (demanda), bem como automatiza as configurações necessárias para a execução de uma aplicação. Isso pode ser feito de modo transparente mesmo através de um grande data center. Kubernetes foi desenvolvido originalmente pela Google e se tornou o grande padrão de orquestração de containers.


Lembre que uma máquina virtual compartilha os recursos físicos (hardware), enquanto containers compartilham o sistema operacional e os recursos físicos subjacentes, muito embora isolando as aplicações. E para provar que a tecnologia de containers é realmente imprescindível para a infraestrutura de TIC atual, há até mesmo containers como o Singularity, específicos para aplicações de computação de alto desempenho (HPC), que encapsulam aplicações e seus respectivos ambientes para execução em clusters.


Containers de sistema e containers de aplicação possuem um "overhead" muito menor do que uma máquina virtual tradicional, tanto em termos de uso de memória secundária (disco) como memória principal. Sua inicialização também é muito mais rápida, praticamente instantânea. Desta forma é muito comum tratá-los como efêmeros. Ou seja, eles são criados no momento da utilização, isto é, da execução da aplicação, e destruídos logo em seguida.


Há um outro tipo de container de aplicação em Linux que se consiste basicamente em encapsular uma aplicação com todas as suas dependências, de forma que ela possa ser instalada em qualquer distribuição e conviver com aplicações em um mesmo sistema mesmo que tenham dependências conflitantes. São os chamados containers para distribuição de aplicações. Há principalmente três dessas soluções hoje: Snapcraft, Flatpak e AppImage. O conceito dos "apps universais" no WIndows, ou mesmo dos apps dos sistemas móveis, é basicamente o mesmo.



Acesse o Microtutorial de Containers Docker!



Contextualizando


Hipervisores tipo 1 são muito usados em servidores e data centers para garantir maior segurança e disponibilidade, aproveitar melhor os recursos computacionais e financeiros, facilitar e centralizar o gerenciamento, etc. São essenciais para a infraestrutura moderna, da consolidação de servidores à viabilização da computação em nuvem. E isso se aplica a containers quando executados de modo similar à hipervisores tipo 1, em especial quando em conjunto com Kubernetes.


O uso de máquinas virtuais e, especialmente, de containers, também viabilizou que as equipes de desenvolvimento e de operações pudessem trabalhar com a mesma infraestrutura e agilizar grandemente o processo de teste e entrega do software, viabilizando o DevOps (Development + Operations). Um desenvolvedor pode trabalhar com o mesmo ambiente onde o software será executado, sem surpresas. Aliás, o desenvolvedor pode realmente definir o ambiente em que o software será executado.


Hipervisores tipo 2, que usamos em nossas máquinas no dia a dia, viabilizam uma série de aplicações que já bastariam para justificar conhecer e utilizar essa tecnologia. A saber:

  • Testar novos sistemas operacionais, ou novas versões de um sistema operacional;
  • Executar um servidor e deixar o sistema host atuar como cliente, o que pode ser muito útil para redes e desenvolvimento;
  • Desenvolver, ou testar, software para outro sistema operacional, ou outra versão do sistema operacional;
  • Testar software sem impactar o sistema em uso;
  • Realizar testes de segurança sem comprometer o sistema em uso;
  • Executar aplicações que necessitem de maior segurança ou que possam comprometer o desempenho do sistema em uso. Por exemplo, aqueles famigerados módulos de segurança para acesso a bancos;
  • Criar uma rede virtual;
  • Testar configurações impossíveis de se executar no hardware real como, por exemplo, um RAID 5 ou 6 quando se tem um único HD;
  • Etc!

A maioria dessas aplicações também se aplicam a containers sendo executados em um computador pessoal.


Outro detalhe relevante é que o desempenho de uma máquina virtual, ou container, é essencialmente o mesmo da máquina física. O assunto merece uma discussão mais aprofundada, mas é possível iniciá-la verificando os seguintes artigos de Iniciação Científica que este professor pôde orientar:

  • OLIVEIRA, E. J. A.; FARIAS, T. K.; COSTA, W. S. C.; OLIVEIRA, W. S.; VALIANTE FILHO, F. Análise de Desempenho de Máquinas Virtuais. In: Anais da 7ª Escola Regional de Alto Desempenho de São Paulo. Sociedade Brasileira de Computação. p.45 - 48. 2016. [Artigo apresentado]
  • OLIVEIRA, E. J. A.; FARIAS, T. K.; COSTA, W. S. C.; VALIANTE FILHO, F. Análise de Desempenho de Máquinas Virtuais Executadas Simultaneamente em um Mesmo Sistema Hospedeiro. In: Seminário em Tecnologia da Informação Inteligente (SETII), 2016, São Paulo. Anais do SeTII 2016. São Paulo: Universidade Nove de Julho, 2016. v. 01. p. 103-110.



Referências


  • EMC Corporation. Information Storage and Management (ISM) v3. 2015.
  • TANENBAUM. Andrew. Sistemas Operacionais Modernos – 4ª ed. São Paulo: Pearson, 2016.


Versão revisada em 09/2020.