Caminho de modernização para aplicativos .NET no Google Cloud

Neste documento, analisamos as limitações comuns dos aplicativos monolíticos e descrevemos um processo gradual, mas estruturado, para modernizá-los.

Ele é destinado a arquitetos de nuvem, administradores de sistemas e CTOs que estejam familiarizados com o Windows e o ecossistema do .NET e queiram saber mais sobre o tema da modernização. Este documento se concentra em aplicativos de servidor personalizados, como ASP.NET ou Windows Services, mas é possível aplicar essas lições a outros casos de uso.

Aplicativos legados x modernos: por que modernizar?

A modernização de aplicativos legados é uma jornada. O início e o fim dessa jornada e os benefícios que você consegue dependem muito do estado dos seus aplicativos e do tempo e esforço que pode investir na modernização.

No contexto de aplicativos .NET, o que é legado e o que é moderno? Essa pergunta não é fácil de responder de forma completa ou definitiva. Cada aplicativo tem necessidades legadas e de modernização distintas. No entanto, os aplicativos legados compartilham algumas limitações comuns.

O diagrama a seguir resume as características dos aplicativos legados e dos modernos aplicativos baseados em nuvem.

Diferenças entre aplicativos monolíticos e baseados
em nuvem.

Um aplicativo .NET legado geralmente é um monolítico criado no .NET Framework, hospedado em um servidor local Microsoft Windows e conectado a um servidor local executando o Microsoft SQL Server. Os detalhes da arquitetura que você utiliza podem ser diferentes dessas características gerais, mas a maioria dos aplicativos monolíticos tem as seguintes limitações:

  • A necessidade de gerenciar servidores locais que executam o Windows e o SQL Server.
  • Os ambientes de implantação limitados e os custos de licenciamento associados à dependência no Windows.
  • A dificuldade de fazer upgrade de aplicativos legados baseados em uma arquitetura monolítica.
  • Pouca agilidade para planejar, orçar e escalonar usando recursos locais

Aplicativos criados para uma arquitetura baseada em nuvem oferecem vários benefícios:

  • Sobrecarga mínima de gerenciamento pela integrando com serviços gerenciados.
  • Total mobilidade com o .NET Core e contêineres e sem dependências do Windows ou custos de licenciamento.
  • Um caminho de upgrade de alta velocidade baseado em microsserviços implantáveis de maneira independente.
  • Agilidade total para escalonamento e orçamento com uma arquitetura sem servidor.

Em comparação com a abordagem convencional no local, uma arquitetura de nuvem oferece uma maneira mais econômica, eficiente e resiliente de executar seus aplicativos. Em uma abordagem baseada em nuvem, há mais flexibilidade para escolher onde e quando implantar seus aplicativos.

Caminho de modernização

Os benefícios de uma arquitetura baseada em nuvem estão claros, mas o caminho para a nuvem pode não ser. A modernização de uma arquitetura .NET legada para uma arquitetura baseada em nuvem não segue um padrão único. Como mostrado no diagrama a seguir, a modernização envolve uma série de etapas, em que cada uma remove uma limitação, aumenta os recursos do aplicativo e abre oportunidades para fases posteriores da modernização.

Processo, tecnologias e serviços envolvidos no processo de
modernização.

As etapas para a modernização são agrupadas em três fases:

  1. Re-hospedagem na nuvem (também conhecida como migração lift-and-shift)
  2. Mudança de plataforma
  3. Rearquitetura e recriação

Avaliação e aprendizado de pré-modernização

Antes de modernizar, você precisa se preparar. O primeiro passo é avaliar seus aplicativos e as respectivas dependências para determinar quais aplicativos são adequados para modernização e quais não podem ser alterados ou movidos (normalmente por assuntos de regulamentação ou legado). Para mais informações, consulte Migração para o Google Cloud: como avaliar e descobrir as cargas de trabalho.

Em paralelo com essa avaliação, sua equipe precisa conhecer os recursos da nuvem. O Google Cloud oferece certificações, guias técnicos e codelabs específicos para Windows e .NET que podem ajudar a acelerar o processo de aprendizado.

Depois de identificar quais aplicativos serão modernizados, é possível começar a migrar seus aplicativos tradicionais para a nuvem como estão ou com alterações mínimas no código ou na configuração do aplicativo.

Fase 1: hospedar novamente na nuvem

O objetivo principal dessa primeira fase é transferir o fardo do gerenciamento de servidores dos recursos locais para a infraestrutura em nuvem. Nesta fase, você garante que sua infraestrutura está pronta para a nuvem. Assim, você pode otimizá-la para a nuvem em fases posteriores.

Migração manual versus migração baseada em ferramenta

A lift-and-shift dos aplicativos .NET baseados no Windows normalmente começa movendo as instâncias de Windows Server e do SQL Server locais para instâncias de máquinas virtuais (VM) do Compute Engine. É possível executar esse processo manualmente ou automatizá-lo com a ajuda de uma ferramenta de migração.

Em uma migração manual, é possível usar as imagens do Windows Server do Compute Engine para iniciar instâncias. O Google Cloud Marketplace também tem soluções prontas para implantar no Compute Engine, como a solução ASP.NET Framework com uma VM do Windows Server que inclui o IIS, o SQL Express e o ASP.NET.

Da mesma forma, é possível iniciar instâncias do SQL Server a partir de imagens do SQL Server ou acessar uma solução mais gerenciada: Cloud SQL para SQL Server.

O Google Cloud também oferece ferramentas de migração como o Migrate to Virtual Machines ou o VMware Engine para ajudar você a migrar VMs locais do VMware para um ambiente VMware no Google Cloud.

Depois de configurar as VMs, você normalmente cria imagens de VM personalizadas para recriar novas instâncias sob demanda. Esta etapa também é importante para modelos de instância, que serão discutidos mais adiante neste documento.

Se precisar de serviços de domínio na nuvem, implante um Ambiente do Microsoft Active Directory tolerante a falhas no Compute Engine com uma nuvem privada virtual (VPC) ou vá diretamente para o Serviço gerenciado para o Microsoft Active Directory.

Conectividade local e na nuvem

À medida que você migra VMs para a nuvem, não é incomum manter algumas cargas de trabalho no local, quando, por exemplo, existem aplicativos que exigem hardware ou software legado ou quando é preciso atender à conformidade e aos requisitos de regulamentações locais. Você precisa de uma VPN ou de uma solução de interconexão para se conectar com segurança a recursos locais e na nuvem. Para várias maneiras de criar e gerenciar essa conexão, além de outras implicações da execução de cargas de trabalho híbridas e locais, consulte Migração para o Google Cloud: como criar sua base.

Benefícios iniciais

No final da Fase 1, você tem uma infraestrutura básica em execução na nuvem, o que traz benefícios como:

  • Otimizações de custo. É possível criar um tipo de máquina personalizado (CPU, memória e armazenamento) e pagar pelo que usar. Inicie e interrompa VMs e ambientes de recuperação de desastres quando quiser e pague somente quando eles estiverem em execução. Receba recomendações de redimensionamento antes da migração.
  • Maior eficiência operacional. É possível anexar discos permanentes a VMs e criar snapshots para backup e restauração simplificados.
  • Maior confiabilidade. Não é mais necessário programar janelas de manutenção devido ao recurso de migração em tempo real.

Esses benefícios iniciais são úteis, mas outros benefícios são desbloqueados quando você começa a otimizar para a nuvem.

Fase 2: remodelar a plataforma

Ao remodelar a plataforma, você otimiza o aplicativo atualizando seus componentes (como banco de dados, camada de armazenamento em cache ou sistema de armazenamento), sem alterar a arquitetura do aplicativo e com alterações mínimas na base de código. O objetivo da Fase 2 é começar a usar os recursos de nuvem para melhor gerenciamento, resiliência, escalonabilidade e elasticidade do aplicativo, sem reestruturá-lo ou sair do ambiente da VM.

Aproveite o Compute Engine

O Compute Engine fornece alguns recursos padrão úteis para serem explorados. Por exemplo, é possível usar modelos de instância no Compute Engine para criar modelos a partir de configurações de VM existentes. Os grupos de instâncias são uma frota de VMs idênticas que permite escalonar de maneira eficiente o desempenho e a redundância do aplicativo. Além do simples balanceamento de carga e redundância, os grupos de instâncias gerenciadas têm recursos de escalonabilidade (como escalonamento automático), recursos de alta disponibilidade (como recuperação automática e implantações regionais) e recursos de segurança (como atualização automática).

Com esses recursos, você pode permanecer no mundo da VM, mas aumentar a resiliência, a redundância e a disponibilidade dos aplicativos sem precisar reestruturá-los completamente.

Procure substituições no local

Ao mover seu aplicativo para a nuvem, você precisa buscar oportunidades para substituir a infraestrutura hospedada por opções de nuvem gerenciadas pelo Google e por parceiros terceirizados no Cloud Marketplace, incluindo o seguinte:

  • Cloud SQL, em vez do SQL Server, MySQL ou Postgres auto-hospedado. O Cloud SQL permite que você se concentre no gerenciamento do banco de dados, em vez de gerenciar a infraestrutura, como correções de VMs de banco de dados por segurança ou gerenciar backups. E ainda há a vantagem adicional de remover o requisito da licença do Windows.
  • Serviço gerenciado para o Microsoft Active Directory, em vez do Active Directory auto-hospedado.
  • Memorystore, no lugar de instâncias Redis hospedadas.

Essas substituições não devem exigir alterações de código, apenas mudanças mínimas na configuração, além de vantagens de gerenciamento mínimo, segurança aprimorada e escalonabilidade.

Primeiros passos com contêineres do Windows

Depois de otimizar as funções básicas da nuvem, inicie a migração de VMs para contêineres.

Um contêiner é um pacote leve que abriga um aplicativo e todas as respectivas dependências. Comparada à execução do aplicativo diretamente em uma VM, os contêineres permitem executar aplicativos em vários ambientes e de maneira mais consistente, previsível e eficiente, principalmente quando executa vários contêineres no mesmo host. O ecossistema em torno dos contêineres (como Kubernetes, Istio e Knative) também fornece vários recursos de gerenciamento, resiliência e monitoramento que podem acelerar ainda mais a transformação do aplicativo de um simples monolítico em um conjunto de microsserviços focados.

Por algum tempo, a conteinerização foi um recurso somente para Linux. Os aplicativos do Windows não podiam se beneficiar dos contêineres. Isso mudou com os contêineres do Windows, seguidos pelo suporte no Kubernetes e pelo Google Kubernetes Engine (GKE).

Os contêineres do Windows são uma opção se você não quer migrar aplicativos do .NET Framework para o .NET Core, mas ainda precisa dos benefícios dos contêineres (como aceleração, portabilidade e controle). Você precisa escolher o SO de destino correto, dependendo da versão do .NET Framework, e precisa lembrar que nem toda a pilha do Windows é compatível com contêineres do Windows. Para ver as limitações dessa abordagem e as alternativas, consulte Contêineres do.NET Core e Linux, mais adiante neste documento.

Depois de conteinerizar seu aplicativo .NET Framework em um contêiner do Windows, recomendamos que você o execute em um cluster do Kubernetes. O Kubernetes fornece recursos padrão, como detectar quando um pod de contêiner está inativo e recriá-lo, pods de escalonamento automático, lançamentos ou reversões automatizadas e verificações de integridade. O GKE adiciona recursos como escalonamento automático de clusters, clusters regionais, planos de controle altamente disponíveis e suporte híbrido e de várias nuvens com o Anthos. Se decidir usar o GKE ou o Anthos, use o Migrate to Containers para simplificar e acelerar a migração de VMs do Windows para contêineres. O Migrate to Containers automatiza a extração de aplicativos das VMs em contêineres sem a necessidade de reescrever ou fazer a rearquitetura de aplicativos.

Embora se possa aproveitar muitos benefícios usando os recursos certos do Compute Engine, migrar para contêineres e para o GKE ajuda você a usar totalmente as VMs, graças ao empacotamento de vários pods nas mesmas VMs. Essa estratégia pode resultar em menos VMs e reduzir os custos de licenciamento do Windows.

O gerenciamento de contêineres do Windows e do Linux de maneira declarativa com o Kubernetes e o GKE também pode simplificar o gerenciamento de infraestrutura. Com a conteinerização funcionando, sua equipe está preparada para a próxima fase da modernização.

Fase 3: remodelar a arquitetura e recriar

A reformulação é apenas o começo para conseguir todos os benefícios da nuvem. A transformação da arquitetura em uma plataforma baseada em nuvem oferece várias vantagens, como:

A mudança para os serviços gerenciados

Assim que o processo de reescrever partes do seu aplicativo se inicia, recomendamos que você comece a migrar de serviços hospedados para serviços gerenciados. Por exemplo, você verá o seguinte:

Ainda que seja necessário um código adicional para integrar seu aplicativo a esses serviços, este é um investimento valioso, porque você está transferindo para o Google Cloud o fardo do gerenciamento de plataformas. Bibliotecas de cliente do Google Cloud .NET, Ferramentas para Visual Studio e Cloud Code para Visual Studio Code podem ajudá-lo a se manter no ecossistema e nas ferramentas .NET, enquanto você se integra a esses serviços.

Os serviços gerenciados também podem oferecer suporte a operações do seu aplicativo. É possível armazenar os registros do aplicativo no Cloud Logging e enviar suas métricas para o Cloud Monitoring, onde você pode criar painéis com métricas do servidor e do aplicativo. O Google Cloud oferece bibliotecas de cliente .NET para Cloud Logging, Cloud Monitoring e Cloud Trace.

Contêineres do .NET Core e do Linux

Se estivermos falando de um aplicativo legado .NET Framework executado apenas no Windows, talvez você queira mantê-lo em execução em um servidor Windows no Compute Engine ou em um contêiner do Windows Server no GKE. Essa abordagem pode funcionar a curto prazo, mas pode gerar sérias limitações no longo prazo. O Windows tem taxas de licenciamento e uma pegada de recursos maior do que o Linux. Esses fatores podem resultar em um custo de propriedade mais alto a longo prazo.

O .NET Core é a versão moderna e modular do .NET Framework. A orientação da Microsoft afirma que o .NET Core é o futuro do .NET. Ainda que a Microsoft planeje oferecer suporte ao .NET Framework, todos os novos recursos serão adicionados apenas ao .NET Core (e, futuramente, ao .NET 5). Mesmo que ainda queira executar no Windows, qualquer novo desenvolvimento ocorrerá no .NET Core.

Um dos aspectos mais importantes do .NET Core é que ele é compatível com várias plataformas. É possível colocar um aplicativo .NET Core em um contêiner do Linux. Os contêineres do Linux são mais leves que os do Windows e são executados em um número maior de plataformas com mais eficiência. Esse fator cria opções de implantação para aplicativos .NET e permite que você se liberte da dependência do Windows e dos custos de licenciamento associados.

Portabilidade de aplicativos .NET Framework para o .NET Core

Uma boa maneira de começar a migrar para o .NET Core é ler a Visão geral da portabilidade do .NET Framework para o .NET Core. Ferramentas como .NET Portability Analyzer e API.NET Analyzer podem ajudar a determinar se conjuntos e APIs são portáteis. Outras ferramentas de portabilidade, como o dotnet try-convert, podem ser úteis.

Ferramentas externas podem ajudar a identificar problemas de compatibilidade e decidir quais componentes migrar primeiro. Futuramente, será necessário criar projetos .NET Core, migrar gradualmente o código .NET Framework para o novo projeto e corrigir incompatibilidades ao longo do processo. Antes de fazer a portabilidade do código, é crucial colocar os testes em prática e testar a funcionalidade depois do processo concluído. Recomendamos usar o teste A/B para testar códigos novos e antigos. Com o teste A/B, é possível manter seu aplicativo legado em execução enquanto direciona alguns dos seus usuários para o novo aplicativo. Essa abordagem permite testar as saídas, escalonabilidade e resiliência do novo aplicativo. Para ajudar no teste A/B, o Google Cloud oferece soluções de balanceamento de carga, como o Traffic Director.

Transformação cultural

A transformação de servidores .NET Framework e Windows para contêineres .NET Core e Linux não é apenas técnica. Ela exige uma transformação cultural na organização. Equipes acostumadas a usar apenas o Windows precisam se adaptar a ambientes de várias plataformas. Essa transformação cultural requer tempo e orçamento para realizar treinamentos no .NET Core, no Linux e nas ferramentas de contêiner, como Docker e Kubernetes. No entanto, transformar uma organização que usa apenas o Windows para a multi-plataforma permite que ela acesse um conjunto maior de ferramentas e habilidades.

Decomposição monolítica

A mudança do .NET Framework para o .NET Core pode gerar várias perguntas, como estas:

  • Você regrava todo o aplicativo no .NET Core?
  • Você divide seu aplicativo em serviços menores e os grava em .NET Core?
  • Você grava apenas novos serviços no .NET Core?

A resposta a essas questões deve considerar os benefícios, o tempo e o custo associados a cada abordagem. É bom adotar uma abordagem equilibrada que não obrigue a regravar tudo de uma só vez. Em vez disso, é possível gravar novos serviços no .NET Core e dividir o monolítico existente em serviços menores, à medida que a oportunidade surgir. Os seguintes whitepapers podem ajudar enquanto você planeja:

Opções de implantação para contêineres do .NET Core

O documento Como implantar aplicativos .NET no Google Cloud, afirma que existem diferentes opções para implantar contêineres .NET Core no Google Cloud. Ao reformular seu aplicativo monolítico para microsserviços, é possível usar mais de uma solução de hospedagem, dependendo da arquitetura e do design de seus microsserviços.

Responder às perguntas a seguir pode ajudar você a decidir a melhor estratégia de hospedagem:

  • Qual o gatilho do seu aplicativo? Todas as soluções de hospedagem são adequadas para HTTP(S) padrão, mas se o protocolo for TCP/UDP ou um proprietário, o GKE poderá ser sua única opção.
  • Seu aplicativo requer hardware específico? O Cloud Run oferece uma quantidade razoável de RAM e CPU para cada solicitação. O Cloud Run para Anthos oferece opções adicionais de personalização, como GPU, mais memória e espaço em disco.
  • Quais são suas expectativas de escalonamento? Se o aplicativo tem períodos de inatividade, soluções sem servidor como o Cloud Run podem oferecer a opção de reduzir a zero.
  • Qual a importância da latência e qual a tolerância do seu aplicativo para inicializações a frio? Se a tolerância a inicializações a frio for baixa, use um número mínimo de instâncias no Cloud Run ou no GKE com escalonamento automático.

Recomendamos a leitura da documentação de cada ambiente de hospedagem para se familiarizar com os recursos, pontos fortes e fracos e o modelo de preços.

Como regra geral, se quiser criar microsserviços que atendam a solicitações HTTP, precisará implantar no Cloud Run, sempre que possível, e voltar ao GKE, se quiser permanecer no ecossistema do Kubernetes ou precisar de mais opções de personalização. O GKE também é a escolha padrão se você tem um processo de longa duração, como detecção em filas ou um aplicativo que usa protocolos diferentes de HTTP(S).

O Cloud Functions também é uma boa opção de implantação sem servidor, mas não é discutido aqui porque o Cloud Run fornece a maioria dos recursos fornecidos pelo Cloud Functions e ele não é compatível com as versões mais recentes do .NET Core.

Kubernetes e GKE

Se quiser executar em um ambiente otimizado para contêiner, essa abordagem provavelmente envolve o Kubernetes e sua versão gerenciada, o GKE. O Kubernetes e o GKE são especialmente apropriados, se você planeja implantar muitos contêineres com requisitos diferentes e quer um controle refinado sobre como cada um é implantado e gerenciado.

O Kubernetes foi projetado para executar contêineres em escala e fornece elementos básicos, como pods, serviços, implantações e conjuntos de réplicas. Entender e usar adequadamente essas ferramentas pode ser desafiador, mas elas permitem transferir a maior parte do trabalho duro de gerenciamento de contêineres para o Kubernetes. Elas também são adequadas para a arquitetura de microsserviços, na qual um microsserviço é uma implantação que usa um conjunto de pods com balanceamento de carga por trás de um serviço.

Além do Kubernetes, o GKE oferece recursos automáticos como escalonamento, reparo e upgrade, para simplificar o gerenciamento do Kubernetes, além de recursos de segurança, como isolamento de contêineres e registros particulares. Embora você seja cobrado por cada nó no cluster do GKE, ele é compatível com VMs preemptivas para reduzir custos.

O GKE pode gerenciar contêineres do Windows e do Linux. Esse recurso é útil se você quiser manter um único ambiente híbrido para aplicativos baseados em Windows e os mais modernos, baseados em Linux.

Knative e Cloud Run

Para seus contêineres .NET Core sem estado, o Knative e sua versão gerenciada, o Cloud Run, fornecem um ambiente de contêiner sem servidor. Os contêineres sem servidor oferecem benefícios como provisionamento, escalonamento automático e balanceamento de carga, sem a sobrecarga de gerenciamento de infraestrutura.

Para implantar contêineres em um cluster do Kubernetes, o Knative fornece uma superfície de API de nível superior e menor que o Kubernetes. Assim, o Knative pode ajudar você a evitar as complexidades do Kubernetes, facilitando a implantação do contêiner.

O Cloud Run segue a API Knative, mas é executado na infraestrutura do Google, eliminando a necessidade de clusters do Kubernetes. O Cloud Run oferece uma opção sem servidor para contêineres. Por padrão, os contêineres no Cloud Run são escalonados automaticamente e cobrados de acordo com a duração da solicitação. O tempo de implantação é de segundos. O Cloud Run também fornece recursos úteis, como revisões e divisão de tráfego.

O Cloud Run for Anthos é a versão mais flexível do Cloud Run, que oferece a simplicidade do Knative e do Cloud Run com a flexibilidade operacional do Kubernetes. Por exemplo, o Cloud Run no Anthos permite adicionar GPUs a instâncias subjacentes que executam seus contêineres ou escalonar verticalmente o aplicativo para muitos contêineres.

O Cloud Run se integra a outros serviços, como Pub/Sub, Cloud Scheduler, Cloud Tasks e back-ends, como o Cloud SQL. Ele pode ser usado para front-ends da Web com escalonamento automático ou para microsserviços internos acionados por eventos.

Modernização das operações

A modernização não se resume apenas ao código do aplicativo. Ela se aplica a todo o ciclo de vida do aplicativo, como ele é criado, testado, implantado e monitorado. Portanto, quando você pensa em modernização, precisa considerar as operações.

O Cloud Build pode ajudar você a modernizar e automatizar o ciclo de criação/teste/implantação do aplicativo. O Cloud Build não só oferece builders para .NET Core, como também se integra ao Verificador de vulnerabilidades do Container Registry e à Autorização binária para impedir que imagens criadas a partir de código-fonte desconhecido ou repositórios não seguros sejam executadas no seu ambiente de implantação.

O pacote de operações do Google Cloud (antigo Stackdriver) oferece vários serviços que permitem modernizar a observabilidade do aplicativo:

Você pode usar a biblioteca Google.Cloud.Diagnostics.AspNetCore para uma integração simples do pacote de operações do Google Cloud aos seus aplicativos ASP.NET Core. Se quiser exportar métricas do OpenTelemetry para o pacote de operações, use a biblioteca do Pacote de operações do Google Cloud OpenTelemetry.Exporter..

Para mais informações sobre como a modernização se aplica aos processos e à cultura da equipe, consulte Soluções do Google Cloud para DevOps.

A seguir