Conteinerização de aplicativos antigos

Executar aplicativos como contêineres é o novo padrão para soluções e softwares desenvolvidos de forma nativa em nuvem. Muitos livros, artigos e publicações de blog descrevem como aproveitar os benefícios usando uma plataforma com base em contêineres. Mas, e os aplicativos antigos? O que será feito deles? Eles podem ser beneficiados por uma abordagem de execução como contêineres?

Em muitas empresas, grande parte do orçamento de TI é usada para a manutenção e o gerenciamento da dívida técnica do portfólio de aplicativos herdados. A conteinerização pode, portanto, fazer parte do processo perene? Como apenas 20% das cargas de trabalho das empresas foram migradas para a nuvem, os 80% restantes não estão aproveitando ao máximo o potencial em escala de nuvem. A conteinerização pode ser um novo caminho econômico até a nuvem para os aplicativos antigos? Modernizar aplicativos e bancos de dados monolíticos é difícil na prática, em função do tamanho e da complexidade deles. A adoção gradual de arquiteturas nativas de nuvem pode ser uma abordagem para tornar nossos monólitos mais ágeis e prontos para o futuro?

Este artigo fala sobre como é possível obter benefícios ao migrar aplicativos antigos para contêineres e para a nuvem. Desenvolverei o conceito de que a conteinerização não é algo binário, como estar ou não estar em contêineres. É muito mais uma questão de escala, ou seja, até que ponto os conceitos de contêiner podem ser adotados e com qual granularidade.

Para cenários nativos de nuvem, o uso de contêineres é padrão e não vem com muitos custos fixos, já que os contêineres fazem parte da arquitetura desde o início. Por outro lado, a conteinerização de aplicativos antigos sempre requer algum tipo de transformação e investimentos correspondentes. Uma discussão sobre custo e benefício torna-se, portanto, necessária. Apresentarei um modelo de caso de negócios que ajudará você a tomar essas decisões de investimento após responder a esta pergunta: quando a conteinerização de aplicativos antigos faz sentido e até que ponto?

# A conteinerização no contexto da modernização de aplicativos antigos

Contêineres e ferramentas de orquestração de contêineres, como Kubernetes, são tendências emergentes que estão prestes a causar uma revolução no setor de TI e engenharia de software. A maneira como o conceito de contêineres fornece uma camada de abstração à infraestrutura é sem precedentes para desenvolvedores de software.

No entanto, antes que um aplicativo possa ser implementado em contêineres, é necessário começar a pensar sobre quando a conteinerização dele é adequada. Vamos, portanto, refletir primeiro sobre o termo conteinerização, pois ele pode ter diferentes implicações para diferentes cenários.

Para cenários nativos de nuvem, a conteinerização é o processo de empacotar código, bibliotecas e configuração de software compilados, bem definições de computação, rede e armazenamento, em um conjunto de contêineres e definições de gerenciamento de contêineres (Kubernetes). Tais contêineres são implementados em um mecanismo de tempo de execução, como o Docker Engine ou o CRI-O. A escalabilidade, a alta disponibilidade e o gerenciamento de cluster são organizados pela ferramenta de orquestração de contêineres.

Em um contexto de aplicativos antigos, o significado da palavra conteinerização precisa ser ampliado de modo a incluir tudo o que é necessário para preparar um aplicativo existente para adotar o conceito de execução como contêiner. Ou seja, de maneira que exista um bom equilíbrio entre a viabilidade técnica e os benefícios esperados para os negócios.

Examinando a conteinerização dessa forma, o próximo passo lógico é introduzir a escala em que um aplicativo antigo pode adotar o conceito de execução como contêiner. Essa escala vai desde uma conteinerização simples, que não altera nada em relação ao aplicativo antigo, até conteinerizações mais complexas em que os aplicativos são refatorados ou até mesmo recodificados. A conteinerização de aplicativos antigos é, por conseguinte, um espectro de técnicas simples, intermediárias e complexas que podem ser aplicadas nos casos adequados, nas perspectivas técnicas e de negócios.

Imagine, por exemplo, um espectro da esquerda para a direita que represente conteinerizações simples a complexas. Na extremidade esquerda desse espectro, é possível empacotar um aplicativo no estado em que se encontra em um ou mais contêineres, armazenar as imagens do contêiner em um registro de contêiner e executar o aplicativo como um contêiner (ou um conjunto deles) em uma plataforma, como Docker Engine ou CRI-O.

Avançando para a direita no espectro de conteinerização, seria possível introduzir ferramentas de orquestração de contêineres para iniciar/parar/reiniciar contêineres com base em eventos externos.

Mais à direita no espectro, é possível implementar como contêineres separados partes do aplicativo antigo que sejam adequadas para execução independentemente do estado lógico do usuário ou dos negócios (stateless), por exemplo, o front-end de um aplicativo da web. Esses contêineres podem ser automaticamente controlados pelo Kubernetes para obedecer a restrições declaradas de disponibilidade ou escalabilidade.

Avançando mais ainda para a direita do espectro, seria possível refatorar parcialmente o aplicativo antigo ao identificar as partes adequadas para execução como macrosserviços independentes, mas, ainda, grosseiros como parte do cluster do aplicativo antigo.

Diagrama do exemplo do espectro de conteinerização

Ainda mais à direita no espectro, podem ser encontradas técnicas para refatorar o aplicativo de maneira que os módulos em nível de microsserviços possam ser implementados e executados independentemente. É possível usar os contêineres e o Kubernetes na totalidade, como se seu aplicativo tivesse sido desenvolvido para eles desde o princípio. Trata-se do ponto mais à direita e mais próximo do lado nativo de nuvem do espectro, por assim dizer.

Ao avançar da esquerda para a direita no espectro, quanto mais o aplicativo usa a plataforma conteinerizada, mais benefícios ele recebe. Consequentemente, você obtém mais custo-benefício e agilidade nos negócios. Ao mesmo tempo, os investimentos que precisa fazer para transformar o aplicativo antigo aumentam. Mais riscos são apresentados a esses tipos de projetos à medida que a complexidade técnica para refatorar ou recodificar o aplicativo aumenta.

Como em todas as abordagens de migração, escolher a técnica correta de conteinerização de aplicativos antigos dentro desse espectro é uma questão de encontrar o equilíbrio certo entre investimento, resultado para os negócios, ganho em custo-benefício, viabilidade técnica e apetite a riscos.

As tecnologias de contêiner emergentes abrem caminhos para a nuvem

É a pilha de tecnologia que determina se e até que ponto um aplicativo antigo pode ser conteinerizado. Em geral, tecnologias mais antigas, como antigas estruturas de desenvolvimento de software, dificultam a migração de um aplicativo para um contêiner. Estão sendo disponibilizadas tecnologias de contêiner que abrem mais possibilidades para migrar um aplicativo para um contêiner e, em seguida, para uma nuvem.

  • Versões de middleware em contêineres leves e específicos. Um importante princípio da arquitetura baseada em contêineres são componentes leves que possam ser reiniciados rapidamente. O objetivo é manter os contêineres o mais leves possível. Por exemplo, usando o menor volume em disco possível para os arquivos de instalação dentro do contêiner. Na maioria dos casos, os arquivos do sistema operacional não precisam fazer parte do contêiner, uma vez que os contêineres reutilizam tais arquivos da plataforma de hospedagem. Além disso, vejo uma tendência em que versões leves de middleware são disponibilizadas. Por exemplo, uma versão leve de um servidor de aplicativo da web que inclui apenas os componentes e arquivos necessários para facilitar as funções de que o aplicativo no contêiner necessita. O resultado é um software de middleware que contribui para um espaço ocupado menor e tempos de reinicialização mais curtos dos contêineres.

  • Suporte stateful do Kubernetes para as partes que gerenciam um banco de dados. Uma arquitetura baseada em contêiner funciona bem para aplicativos concebidos de forma stateless. Afinal, a resiliência e a escalabilidade são implementadas por reinicializações de contêineres com falha ou iniciam contêineres idênticos em paralelo para exercer as funções do aplicativo com uma carga mais elevada. Isso funciona melhor quando nenhum estado precisa ser gerenciado na lógica do aplicativo. Entretanto, a maioria dos aplicativos antigos requer gerenciamento de estado e persistência de dados. O Kubernetes consegue coordenar estados e a persistência de dados porque fornece um mecanismo para rastrear os volumes de armazenamento e manter os nomes de host após a reinicialização do contêiner, usando o recurso StatefulSet. Isso possibilita a conteinerização das partes do aplicativo antigo que gerencia estados, como bancos de dados.

  • Windows Server Containers. A vantagem do Windows Server Containers é que ele permite a conteinerização de aplicativos .NET, tornando muito maior o escopo da conteinerização. As versões mais antigas de aplicativos .NET recebem suporte. É possível eliminar conflitos entre diferentes versões de aplicativos Internet Information Services (IIS) ou .NET, pois também podem coexistir. Outro caso interessante de conteinerização é isolar uma versão mais antiga de um sistema operacional Windows em um contêiner Windows Server 2016 como uma rápida vitória perene.

Breve discussão sobre como conteinerizar aplicativos antigos

A finalidade deste artigo é explicar o que é a conteinerização de aplicativos antigos e por que usá-la, para ajudar você a avaliar se a conteinerização é uma abordagem benéfica para sua situação. Em artigos futuros, descreverei como fazer a conteinerização de aplicativos antigos, o que é apenas uma parte limitada deste artigo, como descrito abaixo.

Diagrama dos cinco elementos de programas de conteinerização de sucesso

A meu ver, programas de conteinerização de sucesso necessitam de cinco componentes fundamentais:

  1. Avalie seu portfólio de aplicativos para selecionar os candidatos corretos à conteinerização. Uma avaliação da afinidade com nuvem dos aplicativos é necessária para identificar os candidatos certos, dentro do portfólio de aplicativos, que são adequados para uma forma inicial de conteinerização. Você receberá bons resultados quando os parâmetros relevantes do aplicativo forem analisados durante essa análise de afinidade de primeira passagem. Os parâmetros devem incluir a frequência de uso do aplicativo, a criticidade para os negócios, as linguagens de programação usadas, o sistema operacional, os requisitos de hardware, a tecnologia de banco de dados e o uso da infraestrutura, para citar alguns mais importantes. A IBM Cloud Advisory Tool é um exemplo de ferramenta que pode contribuir para sua avaliação inicial da afinidade com nuvem. Após uma filtragem de primeira passagem, é necessário realizar uma análise mais detalhada por aplicativo de modo a entender as dependências tecnológicas. Essa análise usa os arquivos de implementação ou código, por exemplo, archives da web (WARs) e archives de aplicativo empresarial (EARs), como entrada para determinar quais linguagens de programação e estruturas são usadas. A análise também deve ter o objetivo de identificar as partes que talvez possam ser executadas independentemente como contêiner, sejam elas macrosserviços ou até mesmo microsserviços. O Red Hat Application Migration Toolkit é um exemplo de ferramenta compatível com essa fase detalhada.

  2. Selecione a abordagem de migração correta. A maioria dos aplicativos antigos pode ser migrada para contêineres sem muita adaptação inicial. Seguindo um método de conteinerização no lado esquerdo menos complexo do espectro de conteinerização, é possível criar manualmente uma imagem de contêiner definindo um Dockerfile que inclua todas as instalações e configurações necessárias para a execução como contêiner nativamente em um servidor. Uma forma mais compatível é usar a ferramenta Image2Docker, que pega imagens em nível de máquina virtual (VM) como entrada para criar uma imagem de contêiner do Docker. Outras ferramentas entram em cena quando o aplicativo antigo precisa ser refatorado ou recodificado. A parte mais complexa da conteinerização é a migração do contêiner para um novo ambiente em nuvem, em que a integração com o sistema auxiliar precisa acontecer, como os sistemas de autenticação de segurança. Outro aspecto importante é a definição de como o aplicativo conteinerizado se encaixa no domínio de servidor do diretório. A reconexão do aplicativo conteinerizado com os bancos de dados necessários pode exigir design, dependendo da estratégia de migração para os bancos de dados, especialmente quando os bancos de dados permanecem no local. Para esses cenários, o design da rede precisa ser feito de modo a facilitar a troca entre o aplicativo conteinerizado na nuvem e o ambiente de banco de dados local. Esse último também é importante para os aplicativos conectados que permanecem no local.

  3. Defina e governe uma arquitetura de destino sob medida para hospedar os aplicativos conteinerizados. Muitas empresas estão se preparando para incorporar contêineres e o Kubernetes no ambiente de TI. Aqui, há três considerações importantes. Primeiramente, desenvolver uma plataforma de contêineres e Kubernetes por conta própria é algo complexo. Exige tomar muitas decisões arquiteturais interligadas, especialmente no que se refere à rede e à segurança. Como a maioria das empresas adota duas ou mais plataformas em nuvem de hyperscaler, a implementação de uma camada de contêineres e Kubernetes aumenta a complexidade a respeito dos diferentes tipos de serviços que os hyperscalers oferecem. Recomendo, portanto, uma abordagem de arquitetura aberta para criar um plano de controle geral em todas as nuvens. Essas arquiteturas abertas podem ser feitas com o Red Hat OpenShift, que está disponível em todos os principais hyperscalers. Em segundo lugar, os serviços de contêineres e Kubernetes em hyperscalers vêm com diferentes níveis de serviço. É preciso considerar qual nível de serviço (nenhum nível de serviço, objetivo de serviço ou acordos de nível de serviço) combina melhor com sua estratégia empresarial de TI. Em muitos casos, as empresas adotam um serviço totalmente gerenciado de contêineres e Kubernetes para liberar recursos a fim de priorizar aplicativos e processos de negócios. Em terceiro lugar, desenvolver uma plataforma de contêineres e Kubernetes é uma jornada. Usar um modelo grow-as-you-go para os serviços de que você precisa para executar as cargas de trabalho iniciais como contêineres é a melhor abordagem para equilibrar os investimentos e os resultados. É possível, por exemplo, começar com o Windows Server Containers apenas para hospedar as cargas de trabalho Windows e .NET.

  4. Reutilize e governe receitas, padrões e normas. Por meio do meu trabalho com clientes em diferentes setores, aprendi que capturar padrões e receitas de sucesso para o desenvolvimento de soluções e a modernização de aplicativos é fundamental para um sucesso reproduzível e para crescer dentro do domínio de trabalho e além. Padrões e receitas reproduzíveis devem ser capturados para avaliar, migrar e executar aplicativos como contêineres, fornecendo uma descrição detalhada daquilo que funciona e não funciona no contexto do ambiente de TI empresarial específico. Um manual de conteinerização bem administrado e mantido é uma boa maneira de capturar tais receitas e normas.

  5. Desenvolva um caso de negócios para fazer o programa de conteinerização progredir. Uma abordagem consistente de desenvolvimento de caso de negócios é importante para estimular seu programa de conteinerização. Falarei sobre os elementos do caso de negócios mais adiante neste artigo. O desenvolvimento contínuo do caso de negócios alinha o investimento e o resultado, mudando, com o tempo, quando mais tecnologia de contêiner se torna disponível e amadurece. Por exemplo, uma empresa pode se concentrar em vitórias rápidas primeiro para migrar aplicativos da web com base em Linux para contêineres, que são beneficiados pela maior utilização da infraestrutura e custos mais baixos de gerenciamento de aplicativos.

Os benefícios técnicos da conteinerização de aplicativos antigos

Existe uma diferença fundamental entre os resultados após a conteinerização de um aplicativo antigo e os resultados após a virtualização. A virtualização se concentra em como a infraestrutura pode ser definida e compartilhada para hospedar aplicativos. A virtualização gerencia as dependências com os recursos de infraestrutura que oferecem uma camada para a execução de aplicativos. Por outro lado, os contêineres se concentram nos requisitos do aplicativo que precisam ser cumpridos pela infraestrutura. Os contêineres e o Kubernetes são compatíveis com uma abordagem declarativa de gerenciamento dos requisitos não funcionais. Imagine uma pilha de tecnologia tradicional com hardware, um sistema operacional e um aplicativo hospedado. A virtualização olha para baixo do aplicativo até a infraestrutura, enquanto os contêineres e o Kubernetes olham para cima até o aplicativo.

Nas próximas seções, falo sobre algumas vantagens técnicas específicas que os contêineres e o Kubernetes criam para aplicativos antigos. As vantagens se dividem em três grupos: operações de serviços aprimoradas, adoção de nuvem híbrida e aceleração da modernização dos aplicativos.

Operações de serviços aprimoradas

  • Manuseio mais rápido de contêineres graças a um menor espaço ocupado. Como mencionei anteriormente, o volume em disco total de que um contêiner precisa para executar um aplicativo é menor que o das VMs. Os contêineres têm uma operação consequentemente mais leve. Por exemplo, o tempo de inicialização para os contêineres pode ser de segundos, o que permite uma recuperação de serviço em alta velocidade apenas ao reiniciar um novo contêiner.

  • Prontidão para a orquestração de contêineres do Kubernetes. Depois que um aplicativo antigo é conteinerizado, ele pode usar recursos de orquestração de contêineres, como os do verdadeiro líder, o Kubernetes. É possível conseguir resiliência e escalabilidade superiores para seu aplicativo apenas ao definir os requisitos e as restrições que ele deve seguir. O Kubernetes cuida do gerenciamento de contêineres para garantir que seu aplicativo seja executado de acordo com tais requisitos. Isso ajuda a programar como e sob quais restrições o aplicativo deve ser executado. Também muda o funcionamento das operações de serviço, que passam de realizar as tarefas e processos para executar o aplicativo a uma abordagem em que você apenas define o resultado do serviço (declarativo).

  • Melhor automação do serviço. A orquestração de contêineres do Kubernetes é implementada por arquivos de configuração YAML que definem o resultado do serviço do aplicativo em termos de onde ele deve ser implementado, onde deve ser replicado em casos de carga maior ou fail-over ou como gerenciar a persistência. Dessa maneira, a implementação, a escalabilidade, a resiliência e o monitoramento são totalmente automatizados pela plataforma Kubernetes. A maior escala da automação contribui para a diminuição de custo do gerenciamento do serviço.

  • Fluxo mais fácil de alterações para produção e entrega contínua. A abordagem declarativa de implementação que mencionei anteriormente reconhece um processo de código para implementação automático. Isso possibilita um fluxo mais fácil de alterações para produção e contribui para a entrega contínua de recursos do aplicativo aos seus negócios.

  • O aumento da resiliência produz sistemas com self-healing. O fail-over automático da reinicialização de novas instâncias de contêiner quando ocorre um problema pode aumentar a resiliência geral do ambiente de aplicativos. Também gera uma abordagem de sistema com self-healing, com menos interações manuais. O resultado é um maior tempo de atividade dos aplicativos com menos esforço.

  • Detecção mais rápida de problemas por meio de coleta e rastreio de logs. Embora o Kubernetes assuma muitas das responsabilidades do gerenciamento de serviços, ainda é importante analisar as falhas que ocorrem no ambiente de contêineres. Por causa da abordagem de cluster do Kubernetes que possui um plano de controle que supervisiona os nós trabalhadores, é possível identificar problemas com a coleta e a análise de logs em nível refinado. Recursos open-source, como a pilha ELK, passaram a ser o verdadeiro padrão para a criação de um pipeline de processamento de dados de log em um mecanismo de análise que alimenta painéis gráficos.

Adoção de nuvem híbrida

  • Implementação definida por software. O Kubernetes e os contêineres permitem uma implementação densa do aplicativo, com um acoplamento relativamente frouxo à infraestrutura. É possível manter os domínios do aplicativo e do usuário separados por namespaces enquanto você controla a alocação de recursos de computação, a rede, o armazenamento e o controle de acesso. O conceito de “definir uma vez, executar em todo lugar” facilita a implementação de aplicativos em escala global e de maneira controlada e consistente.

  • Maior portabilidade dos aplicativos. A camada básica padronizada dos mecanismos de contêiner e do Kubernetes permite implementar aplicativos em diferentes ambientes, até mesmo em nuvens distintas, no local e na borda. Isso acomoda o frouxo acoplamento com provedores de tecnologia de nuvem e aumenta o poder de negociação para a contratação de recursos.

  • Menor espaço ocupado por recursos de infraestrutura. O pequeno espaço ocupado pelo contêiner e o mecanismo de implementação rápida possibilitam uma implementação mais inteligente na infraestrutura, resultando em menor uso de recursos. Além do uso reduzido de armazenamento dos arquivos de instalação de aplicativos, é possível compartilhar recursos de computação entre um conjunto de aplicativos ou em ambientes de produção e não produção.

Aceleração da modernização de aplicativos

  • Isolamento de tecnologias antigas. A modernização do ambiente de aplicativos consolida o número de tecnologias que precisam ser gerenciadas. Entretanto, é difícil criar um ambiente perene por causa das dependências entre o código do aplicativo, as bibliotecas de tecnologia e as estruturas. Os contêineres oferecem uma maneira de isolar tecnologias mais antigas que são pré-requisitos para o código do aplicativo sem interferir com outras pilhas de aplicativos.

  • Ausência de recodificação. É possível ter rápidas vitórias iniciais apenas aplicando a técnica de conteinerização mais simples possível, sem recodificar ou refatorar o aplicativo antigo. Essa abordagem de baixo investimento é um novo caminho para a nuvem e abre a possibilidade de migrar mais cargas de trabalho para ela. Especialmente em casos em que o lift-and-shift da VM é complexo por causa de dependências em relação à infraestrutura subjacente.

Desenvolvimento de caso de negócios para a transformação de aplicativos antigos com a conteinerização

Muitas organizações enfrentam o desafio de migrar seus aplicativos antigos para a nuvem. Com apenas 20% das cargas de trabalho empresariais migradas para a nuvem, as empresas não estão aproveitando ao máximo os recursos e a elasticidade em escala de nuvem, a segurança em escala de nuvem e o potencial de automação. As vantagens técnicas oferecidas pelos métodos de conteinerização criam um novo caminho rumo à nuvem para mais cargas de trabalho. Há recompensas em duas áreas: eficiência de custo e agilidade nos negócios.

Eficiência de custo

  • Diminuição do custo da infraestrutura. Uma implementação definida por software de aplicativos na infraestrutura e uma adoção de arquitetura aberta com maior portabilidade das cargas de trabalho ajudam a selecionar a infraestrutura mais econômica. É possível implementar aplicativos em vários provedores de tecnologia de nuvem ou em servidores locais caso você precise obedecer a requisitos e restrições de dados globais ou locais, por exemplo. Além disso, o compartilhamento de infraestrutura (ou fazer mais com a mesma capacidade) é um cenário viável com aplicativos conteinerizados.

  • Diminuição do custo do gerenciamento de serviços. A implementação de aplicativos como contêineres pode ser altamente automatizada e reduzir o custo do gerenciamento de serviços. Além disso, os mecanismos de self-healing dos clusters Kubernetes também contribuem para um menor risco nas operações e maior resiliência no ambiente de aplicativos.

Agilidade nos negócios

  • Aceleração do valor de negócios. Muitas organizações ainda enfrentam um longo tempo de espera para colocar novas ideias em produção. A abordagem de contêineres e Kubernetes diminui esse caminho. Primeiramente, o desenvolvimento de uma implementação altamente componentizada com contêineres permite alterar o escopo limitado do aplicativo e implementá-lo em um escopo limitado do ambiente de produção. Em outras palavras, o impacto de uma mudança é menor em termos de custo, esforço e risco. Em segundo lugar, a implementação automatizada e a entrega contínua permitem promover mudanças menores para a produção de maneira controlada e com uma frequência muito maior, às vezes semanalmente ou diariamente, se necessário.

  • Padronização e melhoria na segurança. As definições e imagens de contêineres são altamente reutilizáveis. Desse modo, é possível padronizar a pilha e aumentar o controle de quais tecnologias são permitidas e quais não são. O maior controle das tecnologias aplicadas e dos padrões arquiteturais e de segurança contribui para uma integridade superior da pilha total usada para hospedar aplicativos.

Resumo e próximas etapas

A conteinerização é uma técnica de modernização emergente para migrar aplicativos antigos para a nuvem. Um espectro de abordagens de conteinerização permite selecionar a técnica certa que equilibra seus investimentos e os benefícios de negócios. Programas de sucesso de conteinerização de aplicativos antigos incluem avaliação de aplicativos candidatos, uma abordagem de fábrica para a migração, uma arquitetura de destino sob medida, gerenciamento de melhores práticas e desenvolvimento contínuo de caso de negócios.

Um próximo passo lógico para você é executar um piloto de conteinerização para alguns dos seus aplicativos antigos a fim de entender o potencial de diminuição de custo e os benefícios para os negócios. Ele também fornecerá insights sobre como a arquitetura de destino deve se parecer para hospedar uma primeira onda de aplicativos em contêineres.