.NET CI/CD com GitHub Actions em múltiplos servidores Windows no Google Compute Engine (GCP)

Gustavo Tedesco
Único
Published in
5 min readApr 6, 2022

Neste artigo você irá acompanhar como foi o processo de construção do pipeline de CI/CD no GitHub Actions em múltiplos servidores no GCP de um projeto desenvolvido na plataforma .NET.

O primeiro passo para realizar automações que façam a integração continua e a entrega (CI/CD) de uma aplicação é entender o contexto que o sistema está, pois dependendo desse contexto podem ser utilizadas diferentes abordagens.

Cenário

Em nosso contexto, a aplicação continha o seguinte cenário: foi desenvolvida em VB.NET, contendo um sistema web SOAP e outro como serviço do Windows no mesmo projeto, a web está implantada no IIS, e ambas estão em máquinas virtuais com Windows no GCP.

Para realizar a implantação do sistema era necessário realizar os seguintes passos manuais:

  1. Remover o tráfego de requisições das máquinas no balanceador de carga.
  2. Parar o pool do IIS da aplicação web.
  3. Copiar os arquivos para pasta do sistema web no servidor.
  4. Substituir os arquivos antigos pelos novos que foram copiados da aplicação web.
  5. Parar os serviços do Windows deste projeto.
  6. Copiar os arquivos dos serviços do Windows no servidor.
  7. Substituir os arquivos antigos pelos novos que foram copiados dos serviços do Windows.
  8. Iniciar o pool do IIS da aplicação web.
  9. Iniciar os serviços do Windows deste projeto.
  10. Por fim retornar o tráfego de requisições no balanceador de carga do sistema.

Este processo era repetido em duas regiões com 12 máquinas cada, totalizando 24 máquinas com o processo manual descrito.

Após a compreensão do nosso cenário, realizamos escolhas de algumas ferramentas para auxiliar na tarefa de criação do CI/CD. Como a aplicação é armazenada no GitHub, foi escolhido o GitHub Actions para controlar e integrar todo o processo.

Foi utilizada uma estratégia de disparar ações (actions) do GitHub Actions diferentes para cada fluxo de trabalho (workflow) no repositório do projeto, conforme demonstrado na figura abaixo.

Iremos abordar esta implementação do CI/CD na prática.

GitHub Secret

Sempre que tivermos alguma informação sensível, iremos utilizar o GitHub Secrets.

Os GitHub Secrets são criptografados e permitem que você armazene informações confidenciais, como nossas credenciais de acessos aos recursos do GCP, em seu repositório.

Ansible Playbooks

Para automação dos processos manuais nas máquinas descritas no contexto, foi utilizado o Ansible para fazer o controle e orquestração dessa tarefa.

Os Ansible Playbooks tem como uma de suas ações a automação da execução de tarefas. Ele basicamente também é um arquivo ymlcontendo os passos de uma ou mais tarefas a serem executadas.

Vamos criar um arquivo chamadoinventory que contém nossas credenciais de acesso as máquinas do GCP. Importante ser o mesmo usuário/senha em todas as máquinas e com direitos de administrador.

Não iremos salvar este arquivo, devemos gerar um base64 dele e colocar no GitHub Secret, conforme demonstrado na imagem abaixo.

Comando para criar o usuário via powershell.

NET USER <USUARIO> "<SENHA>" /ADD /y && NET LOCALGROUP "Administrators" "<USUARIO>" /add

Também devemos liberar nas máquinas o acesso para o winrm localmente conforme comando abaixo.

Set-Item -Force WSMan:\localhost\Service\auth\Basic $true

Agora devemos criar um arquivo na raiz do projeto denominadodeploy-playbook.ymlque irá conter os passos para executar as tarefas automatizadas nas máquinas windows do GCP para a aplicação web, utilizando o powershell.

Para os serviços do Windows iremos criar outro arquivo com o nome deploy-service-playbook.yml , muito semelhante ao descrito acima, mas para automatizar a parada, atualização e inicio de múltiplos serviços do Windows instalados de forma automatizada, também utilizando o powershell.

Balancedor de carga

Para automatizar o balancedor de carga, mudamos do nginx para o ILB (Internal Load Balancer) do GCP. Com isso conseguimos automatizar a carga de requisições recebidas no momento da atualização do sistema via script bash que será executado pelos fluxos de trabalho do GitHub Actions. Para este script iremos criar um arquivo com o nome update_balancing_weight.sh.

GitHub Actions

Os GitHub Actions são ações distribuidas em fluxos de trabalho (workflows) que realizarão o CI/CD da nossa aplicação de forma automatizada.

Um fluxo de trabalho nada mais é do que um arquivo yml com os passos que o GitHub Actions deve executar para publicar nossa aplicação. Por padrão os fluxos de trabalho devem ficar na pasta .github/worflows.

Dentro da pasta de workflows primeiramente iremos criar o arquivo on_pull_request.yml para o fluxo de trabalho da ação Pull Request.

Na mesma pasta de workflows iremos criar o arquivo para o fluxo de trabalho de deploy no ambiente produtivo denominadoon_manual_dispatch.yml. Este fluxo contempla as seguintes etapas:

  1. É gerada uma nova versão da aplicação, feita a compressão do pacote, renomeado a versão antiga no bucket com a última tag gerada, para versionamento, e enviada a nova versão para o bucket do GCP.
  2. Remove o tráfego de requisições no ILB da região selecionada.
  3. Lista os servidores a serem atualizados pela região selecionada, para realizar a implantação em múltiplos servidores paralelamente, utilizando o recurso do GitHub Actions chamado de matrix.
  4. Em cada máquina do GitHub Actions criada paralelamente é feito um túnel no GCP para executar localmente os scripts do Ansible para atualização da aplicação nas respectivas máquinas listadas.

Para os serviços do Windows iremos criar um arquivo on_manual_dispatch_service.yml que contém quase as mesmas etapas da aplicação web, mudando apenas que não possuímos regiões de máquinas para atualização em paralelo e sim somente uma máquina, e também trocamos o script do Ansible a ser executado, para o que criamos especifico para os serviços do Windows.

Podemos também ter estes arquivos separados em 2 fluxos para um melhor controle.

No primeiro iremos só realizar o build da aplicação e mandar para o bucket.

E por fim o arquivo para realizar o deploy com as opções de alternar entre as releases que se encontram no bucket.

Para os demais ambientes iremos criar os arquivos de fluxos de trabalho do GitHub Actions com os nomes on_push.ymle on_tag.yml, também criarmos os mesmos arquivos para os serviços do Windows se houverem nesses ambientes. Estes arquivos contém as ações (jobs) idênticas ao de produção acima, somente mudando como é disparada a ação em cada arquivo e as variáves de ambiente conforme exemplos.

Para controlar as requisições no balanceador de carga criamos mais uma action denominadaon_manual_dispatch_ilb.yml, que podemos programar a porcentagem de requisições para cada região de máquinas.

Conclusão

Após a automação do processo de CI/CD, conseguimos equalizar os ambientes com a mesma versão da aplicação, otimizamos o tempo das entregas em produção, temos mais resiliência evitando a falha humana e voltamos mais rápido para versões estáveis do sistema de forma automatizada.

Vemos na imagem abaixo o pipeline do deploy em produção.

Versões utilizadas nos exemplos:

  • .NET 4.6.2
  • Ansible 5.5.0

Contribuidores

Gustavo Tedesco / Gildson Bezerra / Rangel Daykes

--

--