VM vs. Containers

Resolvemos escrever sobre este assunto após lermos um artigo que tratava sobre um caso específico de migração de VM para Containers. Aqui a intenção é tentar ser o mais abrangente possível para que você possa ter uma visão dos benefícios (e os desafios) da “containerização” (?) e como este caminho inevitável faz você reduzir muito seus custos ao mesmo tempo que melhora seus ganhos através de mais disponibilidade e mais agilidade na entrega de suas aplicações. Vamos lá:

Conforme aumenta o crescimento da demanda de soluções DevOps, também aumenta a adoção de barreiras pelos “donos” das aplicações legadas em VMs e dos servidores de “lata”.

A complexidade de decompor e migrar estas aplicações normalmente é alta então é comum que os donos destas aplicações tenham que redesenhar a arquitetura para se beneficiar das soluções atuais de PaaS e CaaS.

Um bom começo é analisar os desafios específicos de uma das aplicações legadas que rodam em VMs e serão colocadas em plataformas baseadas em containers. Escolha a sua primeira aplicação e vamos lá:

Motivações

A virtualização foi um grande passo comparado com a era dos "metais". Ganhamos a habilidade de isolar múltiplas aplicações uma das outras e usar o hardware de forma mais eficiente. Apesar disso, cada VM ainda precisaria de seu próprio OS, TCP e sistema de arquivos, que usam memória e processamento consideráveis.

Cada VM tem um número fixo de memória e somente alguns casos permitem memória “dinâmica”. Mesmo assim isso não é uma tarefa trivial. Normalmente o resultado é que deixamos reservados recursos em cada VM para que futuramente possamos escalar nossas aplicações (falar sobre isso agora dá a sensação de que estamos no ano de 1817, mas vamos lá…)

Estes recursos obviamente não são totalmente utilizados, mas não podem ser compartilhados com outras aplicações devido a falta de isolamento de instâncias em uma VM (ok, tem gente trabalhando nisso…). De qualquer forma é possível ver abaixo a quantidade de espaço disponível para aplicações utilizando containers e com isso você gasta muito menos máquinas para rodar as mesmas aplicações de forma mais estável e com mais performance.

Os containers trabalham a performance e utilização de recursos em outro nível compartilhando OS, TCP, file system e outros recursos do sistema usando menos memória e processamento.

Existem dois tipos de containers (de aplicação e de sistema). É comum um container de aplicação rodar quase como um processo individual. E um container de sistema se comporta como um OS completo e pode rodar todas as funcionalidades “init” como systemmd, SysVinit, e openrc, que permitem recuperar outros processos como openssh, crond e syslogd em um único container.

Ambos os tipos são úteis em diferentes casos e não desperdiçam memória em um processo de gerenciamento redundante, ou seja, consumindo menos RAM do que uma VM. Entretanto, dependendo da aplicação são necessárias modificações somente nos containers de sistema para que tudo funcione. Isto pode ser feito sem um redesenho completo da arquitetura. :)

Ao contrario de VMs, os limites de recurso em containers podem ser alterados facilmente rodando novas instâncias sem um restart. Além disso, os recursos que não são consumidos, são compartilhados com outros containers rodando no mesmo node! A diferença na inteligência da utilização de recursos pode ser facilmente observável nas imagens abaixo.

Os recursos que não são utilizados no hardware podem ser usados nos containers existentes em um scaling ou mesmo em um novo workload de aplicação. Considerando o isolamento avançado do container, diferentes tipos de aplicação podem rodar no mesmo node de hardware sem influenciar aos demais. Isto permite que a utilização de recursos da infraestrutura existente aumente, em media, de 3 a 10 vezes!

Como cereja do bolo, os containers são muito usados por desenvolvedores que querem criar, empacotar e testar aplicações com agilidade para acelerar o processo de desenvolvimento de aplicações e melhorar a escalabilidade de aplicações.

O que é Decomposição?

Decomposição é uma parte essencial do processo de migração. É aquela fase onde dividimos uma grande aplicação monolítica em pequenos pedaços lógicos e que trabalharão de forma independente.

Uma representação simples do processo de decomposição para a migração de uma VM para containers está na imagem a seguir:

Rodando aplicações legadas em uma VM

Existe um ditado no desenvolvimento de aplicações: “Está tudo bem possuir sistemas legados. São apenas software antigo que ainda funciona”. Ok, vamos analisar de forma mais precisa como isto funciona em um Servidor WebLogic da Oracle e tangibilizar isto tudo em algo prático.

Estrutura de um Servidor WebLogic Oracle

O WebLogic Server é composto por três principais tipos de instâncias necessárias para rodar em uma VM:

  • Servidor de Administração (Administration Server).
  • Gerenciador de Nodes (Node Manager).
  • Servidor gerenciado (Managed Server).

Bom, o Administration Server é o ponto central que iremos configurar e gerenciar todos os recursos no cluster. Isto está conectado aos Node Managers, que são responsáveis por adicionar e remover instâncias de Managed Servers (onde ficam hospedados as aplicações WEB, EJBS, web services e outros recursos). Vejamos abaixo:

Normalmente cada VM hospeda um Node Manager e muitos Managed Servers. Da mesma forma que um Administration Server é usado para gerenciar todas as instâncias entre VMs. Quem quiser mais informações: http://docs.oracle.com/middleware/12211/wls/DOMCF/understand_domains.htm

Escalando WebLogic entre VMs

Agora vamos imaginar que temos um pico de trafego e temos que escalar o cluster. Para lidar com este aumento, novos Managed Servers serão adicionados a VM até que atinjamos os limites de recursos (ex: RAM).

Imaginemos que o tráfego continua crescendo e o número atual de instâncias de Managed Servers não é suficiente para lidar com esta carga, então precisamos adicionar uma nova VM e assim escalarmos a aplicação.

O fluxo clássico da escalabilidade do WebLogic Server através de muitas VMs possui três passos:

  1. Provisionar uma nova VM com um template WebLogic pré configurado.
  2. Adicionar um Node Manager dentro desta nova VM recém adicionada e conectá-lo ao Administration Server.
  3. Adicionar um Managed Server para lidar com uma parte do incremento de carga.

Feito isso, o processo de escalabilidade se repete e inserimos mais Managed Servers nesta VM até ela atingir também seu limite de recursos.

Desvantagens de rodar WebLogic em VMs

Rodar Oracle WebLogic em VMs é uma abordagem muito ineficiente do ponto de vista de recursos e muitos pontos de atenção podem ser levantados para demonstrar recursos não usados ou desperdiçados.

  • Cada VM demanda seu próprio OS, TCP, e sistema de arquivos, que usam processamento e memória consideráveis na máquina Host.
  • A alocação de recursos não é altamente granular então, mesmo que necessitemos ajustar apenas um Managed Server, o provisionamento de uma VM completa pode ser necessário.
  • Se ficarmos sem recursos em uma máquina virtual, teremos que reiniciar a máquina virtual inteira para adicionar mais CPU ou RAM.
  • Um Node Manager, especificamente requerido pela VM para adicionar ou remover Managed Servers, consume recursos adicionais e cria uma complexidade grande nas configurações.
  • Rodar instâncias da mesma VM pode influenciar as demais devido a falta de isolamento e impacta na performance das aplicações como um todo. Pela mesma razão, não podemos misturar e usar diferentes aplicações em uma VM.
  • A portabilidade das VMs é limitada a um vendor, então podemos ter diversos desafios caso queiramos migrar para outra cloud.
  • Os templates de pacotes e a implementação do fluxo de CI/CD com VMs são muito lentas e geram um processo complexo.

Migração de VM para containers

Atualmente podemos encontrar bons servidores de aplicação e frameworks que foram construídos para rodar como micro serviços em containers, como Spring Boot, WildFly Swarm, Payara Micro e outros. Entretanto existe uma lista de servidores especificamente desenhados para rodar em VMs, como o próprio Oracle WebLogic Server usado como exemplo. Sendo assim a tarefa de migração para containers em muitas instâncias é mais complexa. É por isto que temos que prestar atenção em cada exemplo deste artigo.

Decomposição do WebLogic Server

Primeiro de tudo necessitamos preparar a imagem de container com um Servidor WebLogic. É uma tarefa bem simples com a ajuda dos containers Docker (official Oracle repo).

Quando o template docker estiver pronto, vamos provisionar cada instância em um container isolado. Um Administration Server e o número necessário de Managed Servers.

A esta altura o Node Manager fica sem função e está dispensado, uma vez que foi construído como um agente da VM para adicionar e remover instâncias de Managed Server (aqui temos a primeira diminuição de complexidade).

Após a migração para containers, as instâncias Managed Servers podem ser adicionadas/removidas automaticamente bem como diretamente anexadas ao Administration Server usando uma plataforma de orquestração de containers e alguns Scripst WSLT.

Como resultado, obtemos uma topologia muito mais simples para o cluster.

Dessa forma o processo de escalabilidade horizontal fica granular e mais simples de lidar já que um container pode ser facilmente provisionado do zero ou clonado.

E mais, cada container pode ser escalado verticalmente em tempo de execução com disponibilidade total, sem downtime. É muito mais leve do que uma VM então a operação leva muito menos tempo do que escalar uma VM. São poucos MBs contra (preencha aqui a quantidade de TBs da sua VM).

Vantagens de rodar WebLogic em containers

A migração para containers pode ser sim um desafio, mas se você souber como gerenciar o processo da mudança (que acontecerá mais cedo ou mais tarde), você irá ganhar uma série de benefícios:

  • Reduzir a utilização de recursos (processamento e memória) eliminando a necessidade de existir um OS, TCP sistema de arquivos para cada container. Ou seja, o custo da infraestrutura é reduzido já no momento da implantação!
  • A escalabilidade horizontal é simplificada já que as instâncias de Node Manager são removidas da topologia de clusters.
  • A escalabilidade vertical automática é habilitada já que os recursos não usados são compartilhados para este fim. E sem necessidade de restart!
  • A utilização de infraestrutura aumenta já que é possível hospedar diferentes aplicações em um mesmo servidor já que as instâncias estão isoladas dentro dos containers.
  • A migração através das diferentes clouds sem lock-in é habilitada graças à portabilidade dos containers.
  • A velocidade de integração continua e processos de entrega usando uma das diversas ferramentas de DevOps especialmente desenhadas para containers.

Agora é “só” lidarmos com os dados após esta decomposição da aplicação. Falemos disso em um próximo artigo.