Como implantar aplicativos .NET no Google Cloud

Last reviewed 2022-01-19 UTC

Neste artigo, apresentamos uma visão geral de como implantar apps .NET no Google Cloud e oferecemos orientações sobre como escolher a abordagem de implantação correta para seu aplicativo.

Introdução

O Microsoft .NET Framework oferece um conjunto avançado de ferramentas e bibliotecas para desenvolvimento de aplicativos. Com o suporte para Docker no Windows e a capacidade de executar aplicativos .NET Core no Linux, os aplicativos .NET agora também podem oferecer suporte a vários destinos de implantação.

Para que o desenvolvimento e os testes sejam eficientes, você precisa automatizar a implantação de aplicativos e torná-lá parte de um canal de integração/entrega contínuas (CI/CD, na sigla em inglês). Mas, para escolher as ferramentas certas e criar um canal de CI/CD, é necessário primeiro identificar como será executado o aplicativo em produção e qual abordagem de implantação será usada.

Não há uma única maneira que seja a melhor para implantar um aplicativo .NET no Google Cloud. As melhores opções de implantação dependem do app e das suas necessidades. Por exemplo, caso seu aplicativo exija o .NET Framework completo ou precisar ser executado no IIS, sua implantação será baseada no Windows. Por outro lado, se o aplicativo puder ser executado com a funcionalidade compatível com o .NET Core, você terá a opção de implantar no Linux.

Neste artigo, analisamos as diversas maneiras de executar apps .NET e implantá-los no Google Cloud, incluindo as condições em que cada opção se adequa melhor. No final, as opções de implantação são resumidas em uma árvore de decisão para ajudar você a definir quais componentes e abordagens do Google Cloud são mais apropriadas para seu app .NET.

Modelos de implantação

Há duas maneiras básicas de realizar a implantação automatizada de um app. O pacote de implantação pode ser enviado (push) para os servidores de apps ou os servidores podem extrair (pull) o pacote do aplicativo de um local conhecido. As próximas seções tratam das diferenças entre esses dois modelos.

Implantações baseadas em push

Em uma implantação baseada em push, o artefato de implantação, um arquivo zip, um pacote NuGet ou outro artefato, está disponível inicialmente apenas para um servidor de implantação. O servidor de implantação pode ser uma máquina dedicada ou uma função que o sistema de CI presume.

Para executar uma implantação, um processo no servidor de implantação se conecta a um servidor de aplicativos, copia o artefato e inicia a instalação. Se houver mais de um servidor de aplicativos, esse processo será repetido em paralelo ou, da maneira mais comum, em sequência, para que os artefatos sejam implantados em todos os servidores de aplicativos.

Veja esse fluxo no diagrama a seguir.

Implantações baseadas em push

Há várias ferramentas de gerenciamento de configuração disponíveis que permitem automatizar implantações dessa maneira. Algumas dessas ferramentas seguem uma abordagem imperativa, em que a sequência de etapas de implantação é definida de maneira semelhante a um script. Essa abordagem é intuitiva, mas está propensa a desvios de configuração, ou seja, após um determinado período os estados de várias máquinas podem não ser idênticos nem refletir totalmente o estado pretendido. Por isso, muitas ferramentas permitem definir o estado que você quer. Dessa maneira, elas podem descobrir as etapas necessárias para alcançar esse estado.

No Windows, as ferramentas mais usadas para esse modelo de implantação incluem:

Algumas ferramentas conhecidas de código aberto são Ansible, Chef Infra e Puppet. Essas ferramentas têm como alvo principal o Linux, mas elas também são capazes de implantar em destinos do Windows.

Segurança

Um canal de apoio precisa estar disponível para que uma implantação seja enviada por push de um servidor de implantação para um de aplicativos. Por exemplo, a Implantação da Web e o Octopus Deploy usam porta e protocolo personalizados para essa tarefa, enquanto o Ansible usa SSH.

Independentemente do protocolo usado pela ferramenta, é essencial que a comunicação seja segura. Isso ajuda a impedir que invasores usem o canal de apoio para implantar aplicativos mal-intencionados. Mais importante ainda, a comunicação segura exige que o servidor de implantação possa se autenticar com o servidor de aplicativos.

O SSH pode usar autenticação de chave pública. Se você usar a configuração apropriada do IAM, poderá permitir que o Google Cloud distribua automaticamente a chave pública usada para SSH aos servidores de aplicativos. No entanto, se você não estiver usando o IAM, o Google Cloud não poderá gerenciar a chave, e você mesmo precisará gerenciar essa tarefa.

Uma opção é usar o Active Directory. Se o servidor de implantação e o de aplicativos executarem o Windows e forem membros de um domínio do Active Directory, a autenticação poderá ser feita usando o Kerberos. No entanto, a execução de um ambiente tolerante a falhas do Active Directory exige pelo menos duas instâncias de VM adicionais para executar os controladores de domínio. Caso sua configuração use escalonamento automático, todos os servidores também precisarão ser associados dinamicamente ao domínio, o que atrasa o processo de criação de um servidor. O escalonamento automático também pode levar à acumulação de objetos de computador desatualizados no diretório, exigindo lógica adicional de limpeza. Se você usa o Active Directory em um ambiente baseado em nuvem, será preciso considerar esses fatores extras.

Na ausência do Active Directory, a autenticação precisa ser feita usando o NTLM (em inglês) ou por outros meios, como a autenticação básica HTTP. Ambas as abordagens exigem que as credenciais estejam sincronizadas entre o servidor de implantação e os de aplicativos e que sejam armazenadas com segurança. Ambas as tarefas podem ser desafiadoras.

Seja no Linux ou no Windows, a proteção da comunicação entre os servidores de implantação e de aplicativos exige mecanismos separados do IAM. No entanto, usar vários mecanismos para controlar o acesso aos sistemas aumenta a complexidade geral e, assim, o risco de um erro de configuração acidental.

Atualizações do sistema operacional

É importante implantar com eficiência novas versões de pacotes de aplicativos em servidores de aplicativos, mas também é essencial atender ao sistema operacional subjacente nesses servidores. Isso significa que é preciso instalar patches de segurança. Para frotas de servidores maiores, é preciso automatizar esse processo de uma maneira que minimize o risco e o número de servidores indisponíveis durante a atualização.

Também é possível usar push para atualizações do sistema operacional, em que o servidor de implantação aciona uma atualização do sistema operacional nos servidores de aplicativos. No Linux, é comum usar o SSH para executar remotamente esses comandos de atualização. No Windows, o PowerShell Remoting, que se baseia no WinRM, é uma escolha comum. Para ambos os mecanismos, é preciso autenticar e armazenar as credenciais com segurança.

Escalonamento automático

Em um ambiente estático em que o número de servidores de aplicativos não é alterado, o servidor de implantação conhece todos os destinos de implantação antecipadamente. Em um ambiente de nuvem, costuma ser vantajoso escalonar automaticamente o número de servidores de aplicativos para cima e para baixo. Isso cria dois desafios com implantações baseadas em push:

  • Quando um novo servidor de aplicativos for adicionado, ele precisará ser registrado no servidor de implantação para garantir que seja incluído em futuras implantações.
  • O novo servidor precisará receber sua implantação inicial.

O servidor de implantação não inicia eventos de escalonamento automático. Em vez disso, eles são iniciados pelo grupo de instâncias gerenciadas subjacente, que funciona em um nível abaixo do servidor de implantação.

A nova instância do servidor de aplicativos precisa se registrar no servidor de implantação e acionar uma antes que o novo servidor de aplicativos possa veicular solicitações. O diagrama a seguir é uma ilustração desse processo:

Escalonamento automático com implantações baseadas em push

Para que essa abordagem funcione, não é suficiente que o servidor de implantação entre em contato e autentique com os servidores de aplicativos. Os servidores de aplicativos também precisam entrar em contato com o servidor de implantação e se autenticar com ele.

Por fim, o novo servidor precisa ter os mais recentes patches de segurança do sistema operacional. Se iniciar uma atualização durante o processo de escalonamento automático, haverá um atraso significativo. Por isso, a imagem de onde a VM do servidor de aplicativos é criada precisa ter as atualizações já instaladas. É possível fazer isso de duas maneiras:

  • Usar as imagens públicas fornecidas pelo Google Cloud, que são atualizadas pelo Google. Como essas imagens contêm apenas o SO, você precisa lidar com qualquer personalização, como código do app, utilitários e configurações do sistema operacional, usando scripts de inicialização ou como parte da implantação do aplicativo.
  • Ter uma imagem personalizada do SO e mantê-la atualizada. Isso permite que você personalize a imagem, mas aumenta a complexidade geral do gerenciamento das implantações.

A execução de implantações baseadas em push é intuitiva, mas pode resultar em complexidade substancial ao considerar segurança, atualizações do sistema operacional e escalonamento automático. A próxima seção aborda implantações baseadas em pull, que são a maneira mais nativa da nuvem para abordar implantações.

Implantações baseadas em pull

As implantações baseadas em pull são realizadas de maneira indireta. Depois que o sistema de CI tiver produzido uma nova versão de um artefato de implantação, ele publicará o artefato em um repositório. O diagrama a seguir ilustra esse fluxo.

Implantações baseadas em pull

Quando uma implantação for executada (o que pode ocorrer imediatamente após a publicação do artefato ou em um estágio posterior), o servidor acionará a implantação real. Novamente, o servidor de implantação pode ser um sistema separado ou papel que o sistema de CI presume. O acionamento da implantação envolve a conexão com o servidor de aplicativos para que ele receba e instale o artefato de implantação do repositório central.

Inicialmente, as diferenças entre um modelo baseado em push e em pull podem parecer insignificantes, mas a execução da implantação baseada em pull tem algumas implicações importantes:

  • O acionamento de um servidor de aplicativos para fazer pull do artefato de implantação não precisa acontecer no nível do aplicativo ou do sistema operacional. Em vez disso, o servidor de implantação pode acionar a operação de pull fazendo com que o Compute Engine reinicie ou substitua a VM. Isso pode evitar os desafios de segurança associados às implantações baseadas em push.
  • Em vez de simplesmente conter arquivos de aplicativos, o artefato de implantação pode ser uma imagem do Docker ou uma imagem da VM, que pode unificar o processo de fazer atualizações no aplicativo e no sistema operacional.

Segurança

O servidor de implantação não precisa interagir com o de aplicativos para determinados tipos de implantações. Por exemplo, nenhuma interação será necessária se o artefato de implantação for um destes:

  • Uma imagem da VM
  • Uma imagem do Docker a ser implantada no Kubernetes Engine
  • Um pacote a ser implantado no App Engine

Em vez disso, o servidor de implantação só precisa interagir com as APIs do Google Cloud para iniciar a implantação. Isso, por sua vez, significa que o processo de implantação pode depender de mecanismos de autenticação fornecidos pelo IAM, o que elimina a necessidade de gerenciar chaves ou credenciais.

Quando você usa artefatos de implantação, como pacotes zip ou NuGet, que contêm apenas os arquivos e binários do aplicativo, é possível acionar a implantação destas maneiras:

  • Se o servidor estiver configurado para extrair e instalar o artefato de implantação mais recente quando o sistema operacional for iniciado, a atualização poderá ser acionada com a reinicialização da VM pelo Google Cloud. Embora a reinicialização leve algum tempo, isso evita a necessidade de autenticar o servidor de implantação com o de aplicativos.
  • Assim como nas implantações baseadas em push, o servidor de implantação pode acionar remotamente a atualização por meio de um canal de apoio. No entanto, essa abordagem está sujeita às mesmas implicações e desafios de segurança do gerenciamento de credenciais aplicadas a implantações baseadas em push.
  • O servidor de implantação pode executar um agente que observa o repositório para novos artefatos de implantação. Quando um novo artefato for detectado, o servidor poderá aplicá-lo automaticamente. Uma possibilidade problemática é a instalação de várias atualizações simultâneas nos diversos servidores de aplicativos, o que poderá torná-los indisponíveis. Para evitar isso, o agente pode rastrear o estado do servidor no repositório e usar essas informações para implantar atualizações de maneira controlada.

Em cada um desses casos, controle o acesso de gravação ao repositório para impedir que os servidores recebam e instalem pacotes mal-intencionados.

Atualizações do sistema operacional

Quando imagens do Docker ou da VM são usadas como artefatos de implantação, esses artefatos combinam arquivos e dependências de aplicativos. Isso permite usar o mesmo mecanismo de implantação para atualizar o sistema operacional e o app. Nesse caso, verifique se é possível criar e publicar um artefato de implantação para cada um dos dois casos. Um para quando uma nova versão do aplicativo estiver disponível. O outro quando novas atualizações de segurança para o sistema operacional ou outras dependências forem liberadas.

Em outros casos, em que o artefato de implantação contém apenas os arquivos do aplicativo, a atualização do sistema operacional ocorrerá como uma tarefa separada. Sendo assim, aplicam-se as mesmas questões discutidas no contexto de implantações baseadas em push.

Escalonamento automático

Os servidores de aplicativos que fazem pull dos artefatos de implantação alinham-se bem com a ideia de escalonamento automático. Isso evita grande parte da complexidade resultante da combinação do escalonamento automático com implantações baseadas em push. Sempre que um novo servidor de aplicativos for iniciado devido a um escalonamento automático, o servidor entrará em contato com o repositório, fará o pull e instalará o pacote de implantação mais recente.

Se você estiver usando imagens da VM ou do Docker, os mecanismos para extraí-las serão fornecidos pelo Google Cloud. Se você estiver usando outros pacotes, como arquivos ZIP ou NuGet, precisará configurar servidores de aplicativos para iniciar uma implantação após a inicialização. É possível fazer isso personalizando a imagem da VM ou usando scripts de inicialização.

Destinos de implantação

Historicamente, os aplicativos .NET eram executados apenas no Windows, e ele não era compatível com contêineres. Isso limitou as opções de ambiente onde executar seu aplicativo.

Com o advento do .NET Core, é possível decidir entre executar um aplicativo no Windows ou no Linux. E como os dois sistemas operacionais aceitam contêineres, agora você tem várias opções de ambientes.

Sistema operacional

Há muitos anos o Mono oferece uma maneira de implantar aplicativos .NET em plataformas diferentes do Windows, mas foi apenas no lançamento do .NET Core que o Linux tornou-se uma plataforma totalmente compatível para a pilha de desenvolvimento da Microsoft.

O .NET Core oferece apenas um subconjunto dos recursos do .NET Framework. Sendo assim, a segmentação do .NET Core impõe algumas restrições aos aplicativos. Mais importante para os aplicativos existentes, a portabilidade do .NET Framework para o .NET Core nem sempre poderá ser fácil e econômica. Em alguns casos, talvez ela nem seja possível.

Portanto, uma questão fundamental ao escolher um modelo e um destino de implantação é usar o Linux (que requer o .NET Core) ou o Windows (que é compatível com .NET Core ou .NET Framework).

Os possíveis benefícios da execução de aplicativos .NET no Linux incluem:

  • uso do ambiente flexível do App Engine, um ambiente totalmente gerenciado;
  • usar o GKE, um ambiente gerenciado compatível com a orquestração de contêineres;
  • possibilidade de evitar o custo extra das imagens premium do Compute Engine associadas ao licenciamento do Windows.

Analise esses benefícios em relação às possíveis desvantagens do uso do .NET Core no Linux:

  • O esforço necessário para portar um aplicativo .NET para o .NET Core não compensa a possível redução de custos. Ou, conforme observado, talvez nem seja possível portar um aplicativo .NET para o .NET Core.
  • O Linux não é compatível com IIS. O Kestrel, servidor da Web .NET Core, tem um ótimo desempenho, mas não oferece o mesmo conjunto de recursos do IIS. Portanto, talvez seja necessário usar o Kestrel com um servidor da Web como o Nginx.
  • Não há equivalente direto de um serviço do Windows no Linux. Em geral, é possível converter serviços do Windows em aplicativos de console do Linux que podem ser executados como um daemon, mas essa conversão nem sempre é fácil.
  • A solução de problemas e a depuração de aplicativos .NET Core no Linux exigem diferentes ferramentas e habilidades daquelas usadas com o .NET no Windows. Isso poderá ser desafiador se sua equipe tiver pouca experiência com Linux.

Contêineres

Os contêineres adaptam-se particularmente bem a aplicativos executados em um único processo. Alguns exemplos:

  • serviços do Windows
  • aplicativos de console do Linux que atuam como daemons
  • serviços WCF auto-hospedados
  • Aplicativos ASP.NET MVC ou da API da Web hospedados pelo Kestrel

Muitos aplicativos .NET têm como alvo IIS. Ele é comumente usado para gerenciar vários aplicativos (em diretórios virtuais e pools de aplicativos separados) e, portanto, pode não corresponder ao padrão de processo único.

Quando você move uma configuração baseada em IIS para um contêiner, é possível usar diferentes abordagens:

  • Coloque o IIS, com todos os diretórios virtuais e pools em uma única imagem do Docker baseada no Windows usando a imagem microsoft/iis como base. A menos que os aplicativos estejam bem acoplados, geralmente não é recomendável usar essa abordagem, porque ela não permite que os aplicativos sejam atualizados e implantados separadamente.
  • Use imagens do Docker baseadas no Windows separadas para cada app, cada uma executando o IIS. Isso garante a possibilidade de gerenciar aplicativos de forma independente. No entanto, o IIS resulta em uma sobrecarga insignificante que pode se tornar importante se for necessário operar muitos contêineres.
  • Migre alguns ou todos os aplicativos do IIS para o Kestrel. Como ele pode ser implantado em um contêiner baseado no Windows ou em um contêiner do Docker baseado em Linux, essa abordagem permite gerenciar contêineres individualmente.

Com o IIS, vários aplicativos da Web podem ser executados em um único site, compartilhando o mesmo nome de domínio. Ao empacotar aplicativos em contêineres separados, é possível conseguir a mesma funcionalidade usando o balanceamento de carga baseado em conteúdo. Na mesma linha, um balanceador de carga do Google HTTP torna desnecessária a implantação de um proxy reverso personalizado antes dos servidores Kestrel.

Dificilmente há algum aplicativo que não possa ser implantado em contêineres, porque a maioria é compatível com eles. No entanto, alguns desses cenários apresentam desafios:

  • Para aplicativos gerenciados pelo IIS, é comum que a implantação já seja automatizada. As etapas para configurar o IIS (criação de pools de aplicativos, associações, entre outros) são executadas manualmente. Quando você muda para contêineres, também é necessário automatizar todas essas etapas iniciais.
  • Aplicativos que dependem de arquivos de configuração ou de dados localizados no disco podem exigir alterações. Por exemplo, é possível conseguir informações de configuração a partir de variáveis de ambiente, e arquivos e pastas relevantes podem ser ativados como um volume. Isso mantém a imagem sem estado e livre de configurações específicas do ambiente.

Por fim, se você usa contêineres do Docker baseados no Windows, observe que atualmente o Google Cloud não é compatível com o Hyper-V e não permite a execução desse tipo de contêiner. Portanto, os contêineres do Windows Server só podem ser usados no Google Cloud. Os contêineres do Windows Server são mais leves que os do Hyper-V e oferecem um nível diferente de isolamento.

Restrições de implantação

Alguns fatores relativos à criação do aplicativo podem impor restrições à abordagem de implantação usada, conforme discutido nesta seção.

Arquitetura de apps

Um fator principal a ser considerado na escolha do modelo e do destino de implantação é a arquitetura do app. Por um lado, um app pode seguir um padrão de arquitetura monolítico, em que toda a lógica do aplicativo é implementada em uma única base de código e executada em um único processo ou pool de apps do IIS. No outro extremo, o aplicativo pode seguir um padrão de microsserviços. Nessa abordagem, o aplicativo consiste em vários serviços executados independentemente em processos separados, em pools de aplicativos do IIS ou como serviços do Windows separados.

Por fim, é possível ter vários aplicativos independentes que são implantados usando uma estratégia uniforme, em que cada aplicativo pode ser monolítico. Para esta discussão, tal abordagem pode ser considerada equivalente ao cenário de microsserviços.

Em uma arquitetura de microsserviços, o aplicativo precisa de uma execução econômica, com os serviços isolados e gerenciáveis de modo independente. É possível alocar VMs dedicadas para cada serviço, o que garante que eles possam ser gerenciados e implantados individualmente. Mas essa abordagem pode resultar em um grande número de VMs subutilizadas, gerando custos desnecessários. Para aplicativos como esses, os modelos de implantação que permitem um empacotamento mais restrito, em especial, os modelos baseados em contêineres, provavelmente terão uma melhor relação de custo-benefício.

Com e sem estado

Ao projetar aplicativos para a nuvem, tente mantê-los sem estado e gerenciá-los externamente usando um serviço de armazenamento baseado no Google Cloud. Os aplicativos sem estado oferecem estas e outras vantagens:

  • Eles podem ser implantados de maneira redundante para aumentar a disponibilidade e a capacidade.
  • As solicitações podem ser distribuídas livremente entre instâncias.
  • Eles adaptam-se bem ao escalonamento automático.
  • Em caso de falha, seja contêiner ou VM, o ambiente pode ser recriado sem o risco de perda de dados.

Nem sempre é fácil criar aplicativos no modo sem estado. Além disso, muitos aplicativos antigos não seguem essa prática. Ainda assim, vale a pena analisar se algum aplicativo pode ficar sem estado.

Estado da sessão

No geral, os aplicativos ASP.NET e ASP.NET MVC usam sessões para rastrear o estado do usuário. Isso faz o aplicativo ficar com estado. No entanto, há várias opções para limitar o impacto das sessões:

  • Se a quantidade de dados da sessão for pequena, é possível armazenar o estado em um cookie criptografado ou assinado.
  • Em vez de usar o provedor de estado da sessão InProc padrão, é possível usar o provedor SQLServer. No entanto, isso requer uma instância do SQL Server, o que acarreta custos extras e pode afetar a latência e a disponibilidade do aplicativo.
  • Aproveite a afinidade da sessão no Cloud Load Balancing. Esse recurso garante que todas as solicitações de um único cliente sejam roteadas para a mesma instância do app. Entretanto, o uso de afinidade de sessão pode ter um impacto negativo na imparcialidade do balanceamento de carga. Isso significa que certas instâncias de aplicativos podem acabar recebendo mais solicitações do que outras. Além disso, se uma instância do aplicativo for encerrada por qualquer motivo, todas as sessões tratadas pela instância serão perdidas, podendo afetar o usuário final. Por isso, confiar na afinidade da sessão não é uma solução ideal, mas muitas vezes pode ser um meio-termo viável entre robustez e custo.

Caches na memória

Os aplicativos geralmente usam caches na memória para evitar pesquisas no banco de dados ou cálculos redundantes. Isso se tornará um problema caso várias instâncias do aplicativo sejam executadas simultaneamente, porque os caches podem se tornar incoerentes.

Para evitar incoerências, use um cache distribuído, seja diretamente ou por meio da interface IDistributedCache. Servidores de armazenamento em cache, como Redis ou Memcache, geralmente têm demandas de recursos relativamente baixas, mas tornam a configuração geral mais complexa.

Armazenamento

Os dados na forma de imagens, anexos ou arquivos de mídia geralmente são armazenados no disco. O uso de discos permanentes em uma VM para essa finalidade geralmente não é uma opção, já que impede o compartilhamento de dados entre várias máquinas e arrisca a perda de dados se uma instância da VM for recriada. Em vez disso, você pode usar uma das seguintes abordagens:

  • Mova os dados para um servidor de compartilhamento de arquivos. Isso reduz o impacto no app. No entanto, operar um servidor SMB ou NFS altamente disponível gera mais custos e mais manutenção.
  • Mova os dados para o Cloud Storage. Embora isso exija alterações no aplicativo, o Cloud Storage é altamente disponível, muito mais econômico do que executar um servidor de arquivos e não requer nenhum trabalho de manutenção adicional.
  • Mova os dados para os servidores de arquivos do Filestore. Essa abordagem pode exigir algumas alterações no aplicativo. No entanto, depois de provisionadas, é possível escalonar a capacidade das instâncias de acordo com a necessidade, sem inatividade. O Filestore também é compatível com várias instâncias simultâneas de aplicativos que acessam o mesmo sistema de arquivos simultaneamente.
  • Transfira os dados para o Cloud Volumes Service. O Cloud Volumes Service permite mover seus aplicativos baseados em arquivos para o Google Cloud, com suporte para volumes NFS e SMB. Você não precisa reestruturar a arquitetura dos aplicativos e tem armazenamento permanente para eles sem complexidade.

Estratégias de implantação

Ao implantar uma nova versão de algum aplicativo, você precisa minimizar o risco e o impacto no usuário final. As três estratégias mais comuns para conseguir isso são recriação, azul/verde e implantação contínua.

Estratégia de recriação

A ideia da estratégia de recriação é interromper o app em execução em todos os servidores, implantar uma nova versão e iniciar o app. Essa estratégia tem a desvantagem óbvia de causar uma interrupção do serviço, mas evita possíveis problemas que podem surgir quando duas versões diferentes de um aplicativo coexistem e acessam dados comuns temporariamente.

Estratégia azul/verde

A ideia da estratégia azul/verde, também conhecida como vermelha/preta, é implantar uma nova versão do aplicativo em um novo conjunto de servidores. Quando a implantação for concluída, você alternará todo o tráfego do antigo para o novo conjunto de servidores. Essa abordagem requer até o dobro do número de servidores necessários para a produção por um período, mas evita a interrupção do serviço.

Um pré-requisito para essa estratégia é que duas versões de um aplicativo possam coexistir temporariamente e não interferir uma na outra. Para aplicativos que acessam bancos de dados, isso requer que cada iteração de mudanças nos esquemas do banco de dados seja compatível com versões anteriores, no mínimo com a última versão.

Estratégia de implantações contínuas

A ideia de uma implantação contínua é atualizar um servidor após o outro. Assim como na estratégia azul/verde, isso significa que, por um certo tempo, duas versões diferentes de um aplicativo coexistem. Ao contrário da implantação azul/verde, você transfere gradualmente o tráfego da versão antiga para a nova. À medida que mais servidores são atualizados, mais usuários são roteados para a nova versão até que o último servidor seja atualizado e todos os usuários acessem a nova versão. O principal benefício dessa abordagem é que os possíveis problemas podem ser detectados antecipadamente, antes que todos os usuários sejam afetados, o que ajuda a reduzir o risco geral.

Como as implantações contínuas exigem a coexistência de duas versões do aplicativo, essa estratégia geralmente também requer uma configuração do balanceador de carga que evite a rejeição de usuários entre as versões.

Opções de implantação

Até agora, este artigo abordou os modelos de implantação, os alvos e as estratégias. Nas seções a seguir, analisamos opções específicas para implantar apps .NET no Google Cloud.

GKE (Windows ou Linux)

O GKE fornece um ambiente completamente gerenciado do Kubernetes. Os recursos de orquestração do Kubernetes tornam o GKE especialmente adequado para executar aplicativos complexos de microsserviços formados por muitos contêineres. No entanto, mesmo para apps que não seguem o padrão de microsserviços, o GKE permite executar diversos contêineres na infraestrutura compartilhada de maneira eficiente em termos de recursos e de fácil manutenção.

O GKE requer que todas as partes do aplicativo sejam empacotadas como contêineres do Docker. Os contêineres baseados em Linux exigem o uso do .NET Core e um ambiente baseado no Linux. A criação de contêineres no Linux pode ser desafiadora, caso o sistema de CI seja baseado no Windows. No entanto, o Azure Pipelines/Team Foundation Server e o Cloud Build oferecem suporte interno para a criação de apps .NET Core e para a criação e publicação de imagens de contêineres baseadas no Linux.

O GKE oferece a maior flexibilidade para aplicativos sem estado. Também é possível executar certos tipos de aplicativos com estado no GKE usando conjuntos com estado e volumes permanentes.

Um cluster do GKE inclui várias instâncias de VM, chamadas de nós, em que os contêineres são programados. Em um cluster regional ou de várias zonas, o GKE pode distribuir nós e cargas de trabalho em várias zonas para garantir alta disponibilidade.

O preço é baseado na quantidade de nós em execução. Por isso, o GKE é mais econômico quando os nós são bem utilizados. É possível executar cargas de trabalho maiores no mesmo cluster ou escalonando automaticamente o número de nós, conforme necessário.

Implantação baseada em pull usando comandos kubectl

A implantação de um aplicativo no GKE envolve duas etapas:

  1. Publicação de imagens do Docker no Artifact Registry ou em um registro externo do Docker usando docker push ou outros meios. Essa etapa é geralmente processada pelo sistema de CI.
  2. Acionamento da implantação usando kubectl. Essa etapa pode ser gerenciada pelo sistema de CI ou separadamente. Como a implantação é iniciada remotamente, não importa se kubectl é executado no Linux ou no Windows.

O GKE tem suporte integrado para as estratégias de implantação de recriação e contínua. A base para controlar implantações é flexível o suficiente para permitir outras estratégias de implantação, mas o uso de uma estratégia diferente requer ferramentas ou scripts adicionais.

Implantação baseada em pull usando o Spinnaker

Se os recursos integrados do GKE para orquestrar implantações forem insuficientes para seus objetivos, combine o GKE com o Spinnaker. O Spinnaker tem suporte integrado ao Kubernetes e permite que você insira estratégias de implantação mais avançadas, incluindo implantações Azul/Verde.

Como o Spinnaker não é um serviço gerenciado, é preciso fazer sua implantação e manutenção separadamente. É possível implantar o Spinnaker em instâncias de VM separadas do Linux ou em um cluster do GKE.

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.

Compute Engine (Windows ou Linux)

O Compute Engine permite criar e gerenciar instâncias de VM. Ele é compatível com uma variedade de versões do Windows Server e distribuições Linux, além de opções de dimensionamento e configuração. Devido a essa flexibilidade, é possível usar instâncias de VM do Compute Engine para uma grande variedade de cargas de trabalho.

Para garantir que os aplicativos possam ser implantados e mantidos individualmente, implante apenas um único aplicativo ou serviço para cada instância da VM. Para garantir alta disponibilidade, execute pelo menos duas instâncias de VM por aplicativo, cada uma localizada em uma zona diferente. Portanto, é possível presumir que você precisará do dobro do número de instâncias de VMs que o número de aplicativos ou serviços que você quer implantar, independente da carga esperada.

O Compute Engine oferece uma maneira simples de implementar o escalonamento automático por meio de grupos de instâncias gerenciadas. Os grupos de instâncias gerenciadas também oferecem uma maneira de fazer implantações contínuas, conforme discutido posteriormente neste artigo.

O Compute Engine é precificado pela instância da VM. Por isso, é possível supor que a execução de aplicativos nesse produto é mais econômica quando os aplicativos recebem uma carga considerável, o que se converte em alta utilização das instâncias da VM. Por outro lado, se a quantidade de serviços e aplicativos for grande, mas a utilização média for baixa, outras opções de implantação, como o Kubernetes Engine, serão mais econômicas, porque permitem que vários aplicativos usem a infraestrutura comum sem sacrificar o isolamento da carga de trabalho.

A execução de instâncias de VM do Windows requer o uso de imagens premium. Essas imagens contêm cópias licenciadas do Windows e, portanto, estão sujeitas a taxas adicionais. Como resultado, as VMs do Windows geralmente são menos econômicas do que as que usam distribuições do Linux, como CentOS ou Debian, que não têm taxas de licença.

É possível usar o SSH ou o RDP para configurar manualmente uma instância de VM, seja para implantar um aplicativo manualmente ou para resolver qualquer configuração inicial necessária para preparar uma máquina para a primeira implantação. No entanto, isso pode fazer com que as máquinas tenham configurações exclusivas, diferindo de outras instâncias de VM. A longo prazo, a configuração manual de uma instância de VM pode se tornar complicada e trabalhosa. Sendo assim, é aconselhável automatizar o processo para torná-lo repetível.

A automação de implantações de aplicativos no Compute Engine inclui estas tarefas:

  1. Provisionamento e preparação de instâncias de VM para uma primeira implantação de aplicativo
  2. Implantação de aplicativos
  3. Manutenção do sistema operacional (instalação de atualizações de segurança)

As próximas duas seções descrevem como lidar com todas as três etapas de maneira unificada usando uma abordagem de implantação baseada em pull. Os mecanismos e as ferramentas são diferentes para as abordagens descritas nestas seções, mas a ideia geral é semelhante à de como um aplicativo baseado em contêiner é implantado usando o GKE.

Implantação baseada em pull usando um grupo de instâncias gerenciadas

Os grupos de instâncias gerenciadas são mais comumente usados para implementar o escalonamento automático, mas também oferecem uma maneira de lidar com implantações contínuas. Depois de criar um modelo de instância que faça referência à nova versão do aplicativo, é possível usar a funcionalidade de substituição contínua para substituir as instâncias de VM que usam o modelo antigo por instâncias que usam o modelo novo.

Um pré-requisito para essa abordagem é a disponibilização da nova versão do aplicativo como um modelo de instância. É possível fazer isso de duas maneiras:

  • Defina um modelo de instância que use uma das imagens públicas do sistema operacional. Use um script de inicialização para configurar o sistema e instalar o aplicativo a partir de um bucket do Cloud Storage, repositório NuGet, registro do Docker ou de outra origem. O diagrama a seguir ilustra essa abordagem.

    Implantações baseadas em pull usando um grupo de instâncias gerenciadas e uma imagem pública

  • Crie uma imagem de VM personalizada como parte do processo de CI/CD, um processo que geralmente é chamado de preparação da imagem. Nessa abordagem, uma das imagens públicas do SO é usada para gerar uma nova instância de VM, instalar o app mais recente nela, criar uma imagem de VM da instância e disponibilizar a imagem no projeto do Google Cloud. Todo o processo pode ser totalmente automatizado usando uma ferramenta como o Packer (em inglês). A imagem resultante pode então ser referenciada em um modelo de instância. O diagrama a seguir ilustra essa abordagem.

    Implantações baseadas em pull usando um grupo de instâncias gerenciadas e uma imagem personalizada

Uma desvantagem da criação de imagens personalizadas (a segunda opção) é que a preparação da imagem é um processo relativamente lento, em muitos casos ela dura vários minutos. A abordagem, portanto, torna o processo de CI/CD mais complexo e mais lento. Pelo lado positivo, o lançamento de novas VMs com uso de imagens personalizadas é um processo simples e rápido, o que é benéfico quando é usado o escalonamento automático.

O uso de scripts de inicialização para implantar o aplicativo (a primeira opção) tem vantagens e desvantagens. Isso não gera sobrecarga na preparação de imagens no processo de CI/CD, mas atrasa a criação de instâncias de VM. Além disso, se o script de inicialização não for totalmente confiável ou se os sistemas de onde os binários do aplicativo são baixados não estiverem altamente disponíveis, essa abordagem poderá resultar em menor disponibilidade.

A abordagem mais adequada ao aplicativo depende dele mesmo e da complexidade da configuração. Em algumas situações, pode até ser melhor combinar as duas abordagens:

  • Uma imagem personalizada contém todas as configurações e dependências, mas não os binários reais do aplicativo. Uma nova imagem é preparada quando a configuração ou qualquer das dependências for alterada, mas não para cada compilação de aplicativo. Isso ajuda a evitar a lentidão do canal de CI/CD do aplicativo.
  • O aplicativo é instalado usando um script de inicialização. Para minimizar o risco e a lentidão, esse processo precisa ser o mais simples possível.

Caso queira implantar muitos aplicativos ou serviços diferentes que tenham uma configuração básica comum, essa abordagem híbrida pode evitar a necessidade de criar e manter dezenas ou centenas de imagens quase idênticas.

É possível usar grupos de instâncias gerenciadas para orquestrar implantações para cargas de trabalho do Linux e do Windows. Para o Linux, o uso de grupos de instâncias gerenciadas para implantar contêineres do Docker em instâncias de VM é possível e compatível com a plataforma. No entanto, é aconselhável apenas para aplicativos muito utilizados. Em outros casos, a implantação de um único contêiner do Docker por VM oferece pouca vantagem em relação ao uso do ambiente flexível do GKE ou do App Engine.

Se você usa contêineres do Windows Server, siga estas diretrizes para executar os contêineres usando o Compute Engine e os grupos gerenciados de instâncias:

  • Use uma imagem personalizada com o Docker pré-instalado ou uma das seguintes imagens públicas:
    • Windows Server 2019 Datacenter Core for Containers
    • Windows Server 2019 Datacenter for Containers
  • Use um script de inicialização para extrair a imagem do Docker e inicializá-lo como um contêiner do Windows Server durante a inicialização da VM. É possível usar mapeamentos de portas apropriados para expor os serviços em execução no contêiner.

Observe que não há garantia de que um script de inicialização seja executado somente após o início do serviço do Docker. Nos casos em que o script é executado antes da disponibilização do Docker, incorpore a lógica de repetição apropriada no script.

Ao criar imagens baseadas no Windows em um ambiente que não seja na nuvem, use o Microsoft Deployment Toolkit (MDT, na sigla em inglês) ou os Serviços de Implantação do Windows (WDS, na sigla em inglês) (links em inglês). No entanto, como o gerenciamento de imagens e a criação de instâncias de VM com base em imagens personalizadas são recursos essenciais do Compute Engine, essas ferramentas adicionais não são necessárias. O Compute Engine é compatível tanto com scripts de inicialização quanto com scripts de especialização para instâncias de VM baseadas no Windows. Portanto, geralmente não é necessário trabalhar com arquivos unattend.xml personalizados. Entretanto, ainda é importante que a instalação do Windows seja generalizada usando GCESysprep antes de criar uma imagem.

Implantação baseada em pull usando o Spinnaker

Os grupos de instâncias gerenciadas oferecem uma maneira leve e robusta de incluir implantações contínuas, mas os recursos dos grupos de instâncias gerenciadas podem ser insuficientes para determinados aplicativos. Para incluir estratégias de implantação e canais mais sofisticados, use o Spinnaker.

A abordagem básica adotada pelo Spinnaker para orquestrar as implantações no Compute Engine é semelhante à discutida na seção anterior, ou seja, ela também depende da preparação de imagens. Portanto, aplicam-se as mesmas considerações.

Como o Spinnaker não é um serviço gerenciado, é preciso implantá-lo e mantê-lo separado do app. Ele pode ser implantado em instâncias de VM separadas do Linux ou em um cluster do GKE.

Implantação remota baseada em push

As opções de implantação baseadas em pull discutidas nas seções anteriores oferecem vários benefícios. Mas elas não são adequadas para todos os tipos de aplicativos. Os apps com estado, especificamente, geralmente não funcionam bem com essa abordagem e podem ser mais adequados para abordagens baseadas em push.

Na abordagem baseada em push, as três tarefas de implantação (provisionamento de instâncias de VM, execução da implantação do aplicativo e manutenção do sistema operacional) precisam ser tratadas individualmente. É possível usar as mesmas ferramentas para as três tarefas, mas não é incomum usar alguma diferente para cada tarefa.

É possível provisionar as instâncias de VM do servidor de apps da mesma maneira que outras infraestruturas, usando ferramentas de automação, como o Terraform. É possível usar scripts de inicialização ou de especialização para instalar as ferramentas necessárias para automatizar a implantação do app. Por exemplo, se usar Puppet, Chef ou Octopus Deploy, certifique-se de que o software do agente esteja instalado para essas ferramentas.

Do ponto de vista de segurança, para reduzir a superfície de ataque, verifique se qualquer comunicação entre o servidor de distribuição e os agentes em execução nas instâncias de VM do servidor de aplicativos usa a rede interna. Além disso, verifique se as portas que estão sendo usadas não estão expostas à Internet pública.

Em um ambiente em que o escalonamento automático não é usado, a junção de servidores de aplicativos baseados no Windows em um domínio do Active Directory é uma maneira viável de centralizar a configuração. O uso do Active Directory também permite controlar tarefas de gerenciamento, como a manutenção do sistema operacional.

Como escolher uma opção de implantação

Conforme observado no início deste artigo, não há uma única maneira que seja a melhor para implantar um app .NET no Google Cloud. As melhores opções de implantação dependem do app e das suas necessidades. Para escolher o modelo correto, uma das primeiras questões é usar o .NET Core ou o .NET Framework e, dependendo disso, implantar no Linux ou no Windows. Depois de identificar o sistema operacional de destino, use as seguintes árvores de decisão para ajudar a identificar um modelo de implantação adequado.

Para implantar aplicativos .NET Core no Linux:

Árvore de decisão para implantação usando o .NET Core e o Linux

Para implantar um aplicativo .NET Core ou .NET Framework no Windows:

Árvore de decisão para implantação usando o Windows

A seguir