Como implantar aplicativos .NET no GCP

Neste artigo, apresentamos uma visão geral de como implantar aplicativos .NET no Google Cloud Platform (GCP) e fornecemos 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 maneira única de implantar um aplicativo .NET no GCP. As melhores opções de implantação dependem do aplicativo e de seus requisitos. 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 várias maneiras de executar aplicativos .NET e implantá-los no GCP, incluindo as condições que determinam qual opção é mais adequada. No final, as opções de implantação são resumidas em uma árvore de decisão para ajudar na seleção dos melhores componentes e abordagens do GCP para seu aplicativo .NET.

Modelos de implantação

Há duas maneiras básicas de conduzir a implantação automatizada de um aplicativo. O pacote de implantação é enviado por push aos servidores de aplicativos ou os servidores de aplicativos recebem o pacote de aplicativos 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.

O diagrama a seguir ilustra esse fluxo.

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:

As ferramentas conhecidas de código aberto incluem Ansible, Chef 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 Cloud IAM, o GCP poderá cuidar automaticamente da distribuição da chave pública usada para o SSH nos servidores de aplicativos. No entanto, se não estiver usando o Cloud IAM, o GCP não poderá gerenciar a chave e você 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 ou por outros meios, como a autenticação HTTP básica. 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 Cloud IAM. No entanto, o uso de vários mecanismos para controlar o acesso aos sistemas aumenta a complexidade geral e, assim, a probabilidade 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 a respectiva 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 ilustra esse 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 do sistema operacional fornecidas pelo GCP, que são atualizadas pelo Google. Como essas imagens contêm apenas o sistema operacional, você precisa manipular qualquer personalização, como código do aplicativo, 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 sistema operacional e mantê-la atualizada. Isso permite que você aplique personalizações à imagem, mas aumenta a complexidade geral do gerenciamento de suas implantações.

A execução de implantações baseadas em push é intuitiva, mas pode resultar em complexidade substancial ao se considerar a segurança, as atualizações do sistema operacional e o 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 com a reinicialização do Compute Engine ou a substituição da VM. Isso pode evitar os desafios de segurança associados a 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 precisa interagir apenas com as APIs do GCP 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 Cloud 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 fazer pull e instalar o artefato de implantação mais recente quando o sistema operacional for iniciado, será possível acionar uma atualização fazendo com que o GCP reinicie a VM. A reinicialização pode levar tempo, mas 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 que você use o mesmo mecanismo de implantação para atualizar o sistema operacional e o aplicativo. Nesse caso, você precisa verificar se um novo artefato de implantação pode ser criado e publicado para dois casos separados. 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á pull e instalará o pacote de implantação mais recente.

Se estiver usando imagens da VM ou do Docker, os mecanismos para extraí-las serão fornecidos pelo GCP. Se estiver usando outros pacotes, como arquivos zip ou NuGet, você 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;
  • possibilidade de 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, apresenta um bom desempenho, mas não oferece o mesmo conjunto de recursos do IIS. Por isso, 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 abordagens diferentes:

  • Coloque o IIS, com todos os diretórios virtuais e pools de aplicativos, 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.
  • Para cada aplicativo, use imagens do Docker separadas, baseadas no Windows, cada uma executando o IIS. Isso garante que você possa gerenciar aplicativos de maneira independente. No entanto, o IIS resulta em uma sobrecarga insignificante que pode se tornar importante se você precisar 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.

O IIS permite que vários aplicativos da Web sejam 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ê usar contêineres do Docker baseados no Windows, observe que atualmente o GCP não é compatível com o Hyper-V e não permite a execução desse tipo de contêiner. Assim, somente os contêineres do Windows Server podem ser usados no GCP. Mesmo oferecendo isolamento um pouco mais fraco, os contêineres do Windows Server são mais leves do que os do Hyper-V.

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 aplicativos

Ao escolher o destino e o modelo de implantação, pense também na arquitetura do aplicativo. Em uma extremidade do espectro, um aplicativo 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 aplicativos 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 criar aplicativos para a nuvem, tente mantê-los sem estado e gerenciar esse estado externamente usando um serviço de armazenamento baseado no GCP. 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, você poderá armazenar o estado em um cookie criptografado ou assinado.
  • Em vez de usar o provedor de estado de 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 aplicativo. 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 causar impacto no 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 essas incoerências, use um cache distribuído, seja diretamente ou usando a interface IDistributedCache. Servidores de cache, como Redis ou Memcached, 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 minimiza o impacto no aplicativo. No entanto, operar um servidor SMB ou NFS altamente disponível implica em custo extra e mais manutenção.
  • Mova os dados para o Cloud Storage. Isso exige alterações no aplicativo, mas 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.

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 é parar o aplicativo em execução em todos os servidores, implantar uma nova versão e iniciá-lo. Essa estratégia tem a desvantagem óbvia de causar uma interrupção de serviço. No entanto, isso evita possíveis problemas quando duas versões diferentes de um aplicativo coexistem temporariamente e acessam dados em comum.

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 próximas seções, veremos opções específicas para implantação de aplicativos .NET no GCP.

Ambiente flexível do App Engine (Linux)

O ambiente flexível do App Engine oferece uma plataforma como serviço (PaaS, na sigla em inglês) para aplicativos .NET Core. Como o ambiente flexível do App Engine é baseado em Linux, ele é útil apenas para aplicativos .NET Core.

O ambiente flexível do App Engine usa contêineres internamente para executar e escalonar aplicativos, mas você não precisa criar nem gerenciar imagens de contêineres. Em vez disso, os binários do aplicativo podem ser implantados diretamente. Ao usar serviços, o ambiente flexível do App Engine permite executar aplicativos que são decompostos em vários microsserviços menores.

O ambiente flexível do App Engine é capaz de escalonar automaticamente o número de instâncias de aplicativos de acordo com a carga, atendendo a todos os limites configurados para o aplicativo. Por padrão, são mantidas pelo menos duas instâncias, mas é possível alterar isso.

O ambiente flexível do App Engine é mais adequado para aplicativos sem estado. É possível desativar o escalonamento automático para acomodar aplicativos com estado, mas isso significa que você não está recebendo muitos dos benefícios do ambiente gerenciado. Além disso, o ambiente flexível do App Engine permite o acesso ao disco, mas esses discos são considerados efêmeros. Por isso, eles não são úteis para rastrear o estado persistente.

Para cada instância de um aplicativo, o ambiente flexível do App Engine mantém uma VM dedicada. Como o preço é baseado no número de VMs em execução, o ambiente flexível do App Engine é mais econômico quando o aplicativo é muito utilizado. No entanto, quando os aplicativos são acessados com pouca frequência, as VMs subjacentes podem ser mal utilizadas, o que, por sua vez, pode tornar o ambiente flexível do App Engine menos econômico do que outras opções de implantação, especialmente o Kubernetes Engine.

Implantação baseada em pull usando a ferramenta de linha de comando gcloud

A maneira mais comum de implantar no ambiente flexível do App Engine é usar a ferramenta de linha de comando gcloud. Ela é usada primeiro para publicar artefatos de implantação em um repositório mantido no Cloud Storage. Sempre que uma instância é iniciada, os artefatos são extraídos desse repositório. As implantações usam a estratégia azul/verde por padrão.

Cada implantação é rastreada por um número de versão. Em caso de problemas, é possível reverter a implantação para uma versão anterior. Por meio da divisão de tráfego, o ambiente flexível do App Engine também permite executar várias versões do aplicativo em paralelo e direcionar uma determinada parcela do tráfego para qualquer versão. Isso permite que você conduza implantações canário ou testes A/B com o mínimo de esforço.

GKE (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 aplicativos que não seguem o padrão de microsserviços, o GKE permite executar diversos contêineres na infraestrutura compartilhada de um modo 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. Como o GKE atualmente não é compatível com contêineres do Windows, esses contêineres precisam ser baseados em Linux. Isso, por sua vez, exige o uso do .NET Core e de um ambiente baseado em Linux para a criação de contêineres. 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 aplicativos .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 Container Registry ou em um registro externo do Docker usando gcloud docker push ou outros meios. Essa etapa é geralmente processada pelo sistema de CI.
  2. Acionamento da implantação usando o 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 Kubernetes 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 separadas de VM do Linux ou em um cluster do GKE.

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 intervalo 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. Nesta abordagem, é usada uma das imagens públicas do sistema operacional para criar uma nova instância de VM, instalar o aplicativo mais recente, criar uma imagem de VM a partir da instância e disponibilizar a imagem no projeto do GCP. Todo o processo pode ser totalmente automatizado usando uma ferramenta como o Packer. 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, muitas vezes 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.

Se você quiser 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.

Conforme comentado anteriormente, o Windows atualmente não é compatível com o GKE. Se você usa contêineres do Windows Server, siga estas diretrizes para executar os contêineres usando o Compute Engine e os grupos de instâncias gerenciadas:

  • Use a imagem pública do Windows Server 1709 Datacenter Core for Containers ou uma imagem personalizada com o Docker pré-instalado.
  • 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, conte com o Microsoft Deployment Toolkit (MDT) ou os Serviços de Implantação do Windows (WDS, na sigla 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. Por isso, geralmente não é necessário trabalhar com arquivos unattend.xml personalizados. Contudo, 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 fazer sua implantação e manutenção separadamente do aplicativo. É possível implantar o Spinnaker em instâncias separadas de VM 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. No entanto, elas não são apropriadas para todos os tipos de aplicativos. Em particular, aplicativos com estado ativo geralmente não se adaptam bem a essa abordagem e podem ser mais adequados a uma abordagem baseada 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 aplicativos da mesma maneira que outras infraestruturas. As ferramentas comuns de automação para essa finalidade incluem o Deployment Manager e 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 aplicativo. 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 maneira única de implantar um aplicativo .NET no GCP. As melhores opções de implantação dependem do aplicativo e dos seus requisitos. 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 implantar usando o .NET Core e o Linux

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

Árvore de decisão para implantar usando o Windows

A seguir

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…