Beleza! Se você chegou até aqui, é porque provavelmente já leu a Parte 1 (O Porquê) e quer saber mais sobre como configurar direito ambientes de desenvolvimento nativos da nuvem. Ótimo!
Vamos acompanhar o exemplo de um time de projeto já existente e ver como dá para melhorar o fluxo de desenvolvimento dele.
Este guia foi escrito pensando no GCP (Google Cloud Platform), mas os mesmos conceitos também podem ser aplicados à AWS.
Foto de Jason Richard no Unsplash
📖 Estudo de caso
Uma empresa chamada MajesticFantastic tem alguns produtos ligados a pagamentos 💸
O time do projeto de billing cuida do desenvolvimento de uma aplicação de cobrança.
Ela é composta por:
- Alguns microsserviços implantados como containers no GKE 🛳
- Serviços do GCP utilizados: Pub/Sub, Cloud SQL (PostgreSQL), Cloud Monitoring, Container Registry.
- Ambientes atuais: Dev e Prod.
- Um time de 2 desenvolvedores: David e Martha. Em breve, um desenvolvedor chamado Ezekiel e mais alguns devs devem entrar no time, já que a empresa está em uma fase de crescimento acelerado. Tempos animadores! 🚀
Prova de conceito
Vamos introduzir um novo tipo de ambiente. Vamos chamá-lo de "ambiente Pessoal".
Para o ambiente pessoal, nossa POC vai contar com:
- Um projeto GCP que vai atuar como projeto Host. Ele vai hospedar o cluster GKE, a instância do Cloud SQL e as imagens de container no GCR.
- Vários Projetos Pessoais no GCP — um para cada desenvolvedor. Cada projeto vai conter os recursos não compartilhados, com escopo por desenvolvedor. No nosso caso, por exemplo, ele vai hospedar os tópicos e subscriptions do Pub/Sub.
- Uma Shared VPC. O host dela será o projeto Host, e cada projeto Pessoal vai atuar como projeto de serviço da Shared VPC.
Cluster GKE multi-tenant
Vamos alocar um namespace do K8s para cada ambiente (por exemplo: o ambiente do David recebe o namespace david-env, o da Martha recebe martha-env, e assim por diante).
Cada ambiente deve acessar exclusivamente o seu próprio namespace, sem depender de recursos que estejam nos namespaces de outros ambientes.
Observação: por enquanto, não vamos aplicar nada do ponto de vista de segurança. Medidas de segurança podem ser adotadas — falaremos mais sobre isso no fim do artigo.
Cloud SQL multi-tenant
O Cloud SQL suporta Users e Databases, então dá para alocar um User e um Database por ambiente (Observação: estamos usando uma única instância do Cloud SQL e somos cobrados só por ela!)
Vamos criar uma única instância privada do Cloud SQL e "conectá-la" à nossa Shared VPC usando private service access.
Chegou a parte prática! 👩🔧
O repositório developer-envs contém todo o código relevante de IaC e GitOps.
Infrastructure-as-Code (IaC)
Não precisa fazer isso na mão. Vamos usar o Terraform como Infrastructure-as-Code para fazer o bootstrap pra gente. Me mostra o código!
Vamos usar o Terraform Kubernetes Provider para configurar o namespace do K8s por ambiente, além de criar ConfigMaps gerais com parâmetros relacionados à infra (por exemplo, nome do tópico Pub/Sub, GCP Project ID, etc.).
Usei os Terraform Modules do Google, que fazem parte do Cloud Foundation Toolkit, ao longo de toda a solução, e achei bem fácil de usar. Eles também trazem várias boas práticas do Google, então vale muito a pena conferir.
Usar uma ferramenta de infra-as-code (como o Terraform) é fundamental nesse conceito — afinal, a ideia é justamente reduzir e automatizar trabalho repetitivo sujeito a erro humano e manter todas as configurações alinhadas conforme você escala. Um pouco mais de trabalho agora em troca de muito menos trabalho lá na frente.
GitOps
Em seguida, vamos usar também o ArgoCD para controlar e fazer o deploy dos nossos diferentes ambientes no K8s. O ArgoCD é uma ferramenta popular de continuous delivery GitOps que, na minha opinião, se encaixa muito bem no nosso caso de uso multi-tenant. Me mostra o código!
Vamos definir a maior parte dos nossos recursos K8s como arquivos YAML e usar o Kustomize para customizar a configuração.
O Kustomize é uma ferramenta de configuração que permite definir uma configuração "base" e várias "overlays" em cima dela, todas compartilhando a base (uma espécie de herança do pobre). É ideal para situações em que você tem vários ambientes e quer que todos compartilhem um ancestral de configuração comum.
Para a nossa sorte, o ArgoCD, nossa solução de CD, tem integração nativa com o Kustomize.
Acho o Kustomize simples e fácil de usar, mas, claro, você pode usar outra ferramenta no lugar (como o Helm).
Microsserviços de exemplo
Vamos implantar dois microsserviços bem simples e ingênuos escritos em Go.
O microsserviço env-producer publica eventos de pagamento periodicamente em um tópico Pub/Sub a cada 10 segundos.
O microsserviço env-consumer consome as mensagens de "eventos de pagamento" do Pub/Sub e persiste esses eventos em uma tabela no PostgreSQL.
O ponto-chave desses serviços é que a configuração de múltiplos ambientes é transparente para eles, já que expomos os detalhes do ambiente como variáveis de ambiente. Separar configuração e código é uma prática essencial do Twelve-Factor que vale conhecer.
Em resumo, esses microsserviços rodam de forma independente em cada ambiente, integrando-se apenas aos recursos específicos daquele ambiente.

Colocando para rodar 🏃🏻♂️
Para colocar isso para rodar, clone o repositório de exemplo e siga as instruções do README.md.

Depois disso, o console do ArgoCD deve ficar assim
Esse é o lugar onde você acompanha todos os seus ambientes em um único dashboard. Naturalmente, dá para adicionar aqui também os outros ambientes (como dev e prod), talvez em um "projeto" diferente do ArgoCD.
Repare que existe uma aplicação chamada argocd-config responsável por sincronizar automaticamente a configuração e os arquivos de instalação do ArgoCD, além de mais 2 aplicações — uma para cada desenvolvedor.
Como fazer o deploy de mudanças no seu ambiente
Você fez uma alteração em um dos serviços e quer fazer o deploy dela no seu ambiente. Quais são as opções?
Opção 1: criar uma imagem customizada
Você pode alterar o código-fonte e construir uma nova imagem de container. Depois, uma rápida modificação na tag da imagem, na aplicação dele dentro do ArgoCD, faz o deploy da nova imagem em segundos.

Informações da aplicação no ArgoCD, onde o desenvolvedor pode alterar a tag da imagem e clicar em Save
Isso pode ser feito manualmente ou de forma automática, por meio de uma pipeline de CI ou de scripts customizados. (O ArgoCD também tem uma CLI que pode ser usada para automatizar tudo isso.)
Opção 2: rodar localmente
Espera… Como assim? Isso não vai contra tudo o que estamos tentando fazer?
Conheça o Telepresence. É uma das ferramentas mais bacanas que conheci nos últimos tempos. Já usei várias vezes e ela me ajudou demais a aumentar a produtividade como desenvolvedor.
É meio difícil explicar o que ela faz em uma frase, mas vou tentar. Aqui vai uma descrição que peguei do site deles:
O Telepresence substitui o seu pod normal, que roda no cluster Kubernetes, por um proxy de rede bidirecional. Esse pod faz proxy dos dados do seu ambiente Kubernetes (por exemplo, conexões TCP, variáveis de ambiente, volumes) para o processo local. A rede do processo local é sobreposta de forma transparente, de modo que chamadas DNS e conexões TCP são roteadas pelo proxy até o cluster Kubernetes remoto.
Ou, em termos mais simples: ela permite rodar o seu serviço localmente, na sua máquina, enquanto faz proxy de conexões de entrada e saída, variáveis de ambiente e volumes para o cluster K8s. Isso é demais! 👍
Então, digamos que você fez uma alteração no microsserviço env-consumer e quer testá-la. Você executa:
E em poucos segundos a alteração já está implantada e rodando.
Em essência, o que ela faz é substituir o pod do seu serviço por um pod proxy e rodar o seu serviço localmente, conversando com esse pod proxy.
O legal aqui é que você está rodando um app local, mas, na prática, está conectado tanto ao PubSub quanto ao Cloud SQL (PostgreSQL) remotamente!
E tudo isso sem precisar mudar o código da aplicação nem configurar certificados e chaves secretas. O mesmo código no ambiente pessoal e em produção!
Quando termino, aperto Ctrl+C e a imagem volta a ser o que era antes. Que delícia! 🤩

Uma demonstração rodando nosso serviço de exemplo usando o telepresence
Agora se imagine corrigindo um bug, rodando o Telepresence, esperando alguns segundos e percebendo que você fez o serviço quebrar. Pois é… aí você corrige de novo. O ciclo de feedback aqui é bem rápido! 😁
Repare que não construí nenhuma imagem Docker aqui. Estou compilando o código-fonte modificado e rodando o executável localmente. Você também pode fazer com que ele construa a imagem Docker e a substitua.
Ambientes pessoais e onboarding
O Ezekiel acaba de entrar no time como desenvolvedor! Boas-vindas! Ele já recebeu o notebook e alguns brindes. Eba! 🥳
Como parte do onboarding dele, te pedem para preparar um ambiente pessoal para o Ezekiel, para que ele possa mexer na aplicação, na infraestrutura e talvez fazer pequenas alterações para ver o impacto.
Como fazer isso:
- Edite o arquivo
tf/personal.tfvarse adicione o Ezekiel à lista de tenants:
2. Aplique a alteração executando terraform apply -f personal.tfvars
3. Adicione uma aplicação ArgoCD para o ambiente do Ezekiel anexando o trecho a seguir ao argo/apps/applications.yaml; depois faça commit e push da alteração.
É isso! Como o ArgoCD está sincronizado para acompanhar a pasta apps, ele vai notar automaticamente que o ezekiel-env foi adicionado e preparar o ambiente. Tenho certeza de que o Ezekiel vai ficar feliz.
Ambientes pessoais e offboarding
Ah, não! O David está saindo do time para buscar outras oportunidades!
Que pena, vamos sentir saudade dele. ⭐️ 😩
Mas, por outro lado, agora a gente vê como é fácil limpar o ambiente pessoal dele. 😌
Basta ir até argo/apps/applications.yaml, deletar a definição da aplicação david-env, fazer commit e push. Como o ArgoCD está sincronizado para acompanhar a pasta apps, ele vai notar automaticamente que o david-env foi removido e excluir o ambiente.
Em seguida, você deve deletar a infra do ambiente removendo o david da lista de tenants em tf/personal.tfvars, seguido de terraform apply -f personal.tfvars
É isso! Nenhum vestígio do David 💀
👣 Próximos passos
Se quiser adaptar isso para a sua organização, fique à vontade. Mas você vai precisar levar em conta alguns pontos extras, como:
É só uma POC
Como já dito, esta é uma POC, pensada para servir de exemplo e como ponto de partida. Algumas partes da implementação foram simplificadas por questão de brevidade. Por favor, não trate a implementação como melhores práticas e fique à vontade para adaptá-la aos seus requisitos e preferências.
Segurança
Como mencionei no capítulo anterior, segurança pode ser uma preocupação nessa solução. Existem algumas formas de melhorar a segurança e o isolamento a partir dessa solução (por exemplo, RBAC, Network Policies, Resource Quotas, Pod anti-affinity. Confira aqui para mais informações).
Multi-tenancy
Demos exemplos de multi-tenancy para serviços de nuvem como GKE, Pub/Sub e Cloud SQL, mas você pode adaptar esses conceitos a outros serviços de nuvem também.
Projeto GCP por desenvolvedor
O escopo atual do projeto GCP por desenvolvedor é bem enxuto. Esta é uma base para estender e ampliar esse escopo. Por exemplo, dá para configurar o roteamento para que logs e métricas específicos de um namespace sejam enviados a um projeto GCP de um desenvolvedor específico. Outro exemplo: o projeto GCP do desenvolvedor pode ser usado para subir recursos customizados que não fazem parte da linha principal do projeto, com o objetivo de testar se as coisas funcionam como o esperado. O projeto GCP por desenvolvedor não é um requisito, e sim uma possibilidade, então você pode dispensá-lo se quiser.
Shared VPC
Estamos usando uma Shared VPC, que dá aos seus diversos projetos pessoais no GCP a possibilidade de compartilhar a mesma rede VPC. Isso tem alguns pré-requisitos de IAM que você precisa considerar. Por exemplo, o usuário IAM do desenvolvedor precisa ter o papel compute.networkUser no projeto Host para criar recursos na Shared VPC.
Soluções alternativas
As alternativas a seguir buscam oferecer uma solução. Algumas não são gratuitas. Pelo que sei, essas alternativas não entregam uma solução "full-stack" quando se trata de ajustar a infraestrutura à configuração de deploy como na nossa POC. Em vez disso, focam principalmente na parte do Kubernetes. Cada uma tem seus prós e contras dependendo do seu contexto, então leve isso em conta.
É isso! Espero que tenha curtido 🙂
Na DoiT International, nós, Architects & Engineers, sempre buscamos diminuir a distância entre Infraestrutura e Desenvolvimento de Software, pois acreditamos que os dois lados compartilham um objetivo comum: produtividade e confiabilidade.
Obrigado pela leitura! Para se manter conectado, siga-nos no DoiT Engineering Blog, no DoiT Linkedin Channel e no DoiT Twitter Channel. Para conhecer as oportunidades de carreira, acesse https://careers.doit-intl.com.