Existe uma crença fantasiosa de que você pode pegar um monólito, colocá-lo em um recipiente e pronto! Benefícios arquitetônicos modernos de escala e velocidade.
De fato, uma pesquisa da KubeKon de 2018 sugeriu que é exatamente isso que está acontecendo com cerca de 55% dos entrevistados que indicaram que utilizam contêineres "como substituição de VM para aplicativos existentes". Outras pesquisas mostram uma quantidade significativa de aplicativos Java de nível empresarial sendo executados em contêineres. Uma pesquisa da Diamanti de 2018 mostrou que, enquanto a maioria (54%) usava contêineres para aplicativos nativos da nuvem, quase um terço (31%) os usava para modernizar aplicativos legados.
Os motivos citados são geralmente operacionais; os contêineres são vistos como mais simples de gerenciar, apesar da explosão de peças móveis que devem ser gerenciadas. Taxas de desempenho e licenciamento também costumam ser fatores na decisão de prosseguir com os contêineres.
Mas essa mudança não é tão simples quanto finalizar um aplicativo antigo e colocá-lo em um contêiner.
A realidade é que os monólitos — aplicativos cliente-servidor e web tradicionais — têm certas características que dificultam sua transferência para um contêiner e a obtenção dos benefícios operacionais. Contêineres e microsserviços não são mutuamente inclusivos, mas ambos tendem aos princípios de "construído para falhar", nos quais a disponibilidade de aplicativos modernos se baseia. Esse princípio, caso você não esteja familiarizado, é que se um contêiner falhar, você simplesmente inicia outro para tomar o lugar dele. Todos os contêineres são de gado e um é tão bom quanto o outro.
Em arquiteturas de aplicativos deliberadamente modernas e sem estado, isso é verdade. Em arquiteturas de aplicativos tradicionais com estado, nem tanto.
Veja, o cliente-servidor e seu sucessor, o aplicativo web de três camadas, geralmente são com estado. Eles mantêm certas informações sobre a interação entre um cliente e o aplicativo em uma sessão. Essa sessão pode ser mantida na memória do aplicativo ou servidor web, ou em um banco de dados separado. Independentemente de onde esses dados são armazenados, é isso que torna o aplicativo com estado. Esses dados são relevantes e importantes para a operação do aplicativo. Eles contêm seu carrinho de compras, a última página que você visitou e outras informações específicas do aplicativo.
Você pode imaginar que se o servidor web/aplicativo onde essas informações são armazenadas desaparecer de repente, isso interromperá negativamente a experiência do cliente. Meu carrinho sumiu. Tenho que voltar para onde estava. Basicamente, tenho que recomeçar.
Esse comportamento é diametralmente oposto aos princípios arquitetônicos modernos que eliminam a operação com estado de um aplicativo. É a natureza sem estado dos aplicativos e serviços modernos que torna possível substituir facilmente uma instância por outra quando algo dá errado. É a base sobre a qual o "feito para falhar" funciona. Se você introduzir o estado novamente nessa equação, de repente tudo desmorona.
Embora o aplicativo ainda funcione, o usuário fica no limbo. Seu fluxo é interrompido, suas transações são transportadas para o nether, para nunca mais serem vistas.
Essa questão deu origem à necessidade de os serviços de aplicação respeitarem o estado. Depois que um cliente se conectava a um aplicativo/servidor web específico, ele tinha que se conectar ao mesmo aplicativo/servidor web durante toda a sessão. A persistência de cookies e outros mecanismos foram desenvolvidos para garantir que as solicitações fossem roteadas para o mesmo servidor todas as vezes. Para preservar o estado.
A realidade é que, a menos que você seja uma startup novata, você tem aplicativos tradicionais e modernos em execução agora mesmo. Embora as pesquisas variem sobre o tópico, a divisão de "63% aplicativos antigos / 37% novos" permanece amplamente consistente ao longo do tempo. O que significa que você precisa oferecer suporte a arquiteturas legadas e modernas ao mesmo tempo.
Simplesmente mover o monólito para um contêiner não ajudará se você não tiver resolvido a divisão entre com estado e sem estado.
A melhor - ou pelo menos a mais fácil - maneira de gerenciar a migração de monólitos para um ambiente em contêineres é garantir que você ainda possa respeitar o estado, mesmo na anarquia sem estado de um cluster de contêineres. Isso requer alguma inteligência na borda do cluster, na entrada onde N-S encontra E-O.
Uma abordagem em duas camadas oferece suporte a abordagens operacionais tradicionais e modernas, bem como à migração de aplicativos tradicionais com estado para um ambiente em contêiner. Ao aproveitar o F5 Container Ingress Services (CIS), o NetOps pode continuar a dar suporte às necessidades de aplicativos com estado que migram para ambientes em contêineres. A conectividade garante que os métodos tradicionais de balanceamento de carga que empregam persistência possam continuar operando e direcionar solicitações para o contêiner certo ou diretamente para um ambiente tradicional.
Enquanto isso, o BIG-IP pode direcionar simultaneamente solicitações de aplicativos e APIs modernos para um controlador de entrada dentro do cluster de contêineres para distribuição em quantos contêineres sem estado forem necessários.
A realidade é que a maioria das organizações oferece suporte a até cinco arquiteturas de aplicativos distintas — de monólitos a dispositivos móveis e microsserviços. Oferecer suporte simultâneo a um número igual, mas distinto, de modelos de rede e operacionais certamente sobrecarregará as operações e anulará os benefícios da migração para arquiteturas e ambientes modernos. Uma abordagem estratégica em dois níveis permite que as organizações aproveitem os benefícios operacionais e comerciais de ambos os modelos durante a transição para um ambiente majoritariamente em contêineres.
Uma das coisas que você pode fazer para facilitar essa transição é refatorar aplicativos legados para aproveitar as sessões compartilhadas. Essas sessões são realizadas em um local separado do servidor web/aplicativo - geralmente algum tipo de banco de dados - e podem ser acessadas por qualquer servidor web/aplicativo com o ID de sessão apropriado. Você ainda precisará controlar o ID da sessão, mas isso geralmente pode ser feito por meio de um cookie que persiste independentemente do estado do servidor web/aplicativo. Se os aplicativos legados ainda não usam um modelo de sessão compartilhada, a refatoração para fazer isso é um processo bastante tranquilo, comparado à reformulação do aplicativo inteiro.
Como essas transições levam tempo (afinal, ainda estamos quase todos operando em um modelo de multinuvem hoje em dia), é importante encontrar e aproveitar opções arquitetônicas que maximizem os benefícios sem comprometer as principais necessidades do cliente, como disponibilidade e segurança. Usar uma abordagem arquitetônica de duas camadas fornece ambos sem restringir os esforços de conteinerização.