Por que montar uma arquitetura?
Quando começamos o nosso trabalho em uma solução, é muito usual para profissionais técnicos já colocar a mão na massa e desenvolver código para resolver os desafios. O maior problema de uma abordagem não orientada pela arquitetura são as famosas "gambiarras" que emendam componentes desconexos de formas um tanto quanto criativas. A pergunta é "Qual é o mal nisso?", a resposta é simples e direta, arquiteturas não planejadas encontram muitos problemas de escala, resiliência, segurança dentre outros pilares importantes para sistemas produtivos.
Tendo isso em mente, o primeiro trabalho a ser feito na solução de um desafio é o desenho da arquitetura, montar um diagrama e realizar tomadas de decisão em escopo macro. Após ter um desenho de referência, a implementação dos componentes será bem mais fluida e estruturada.
Quais são os guidelines?
A AWS apresenta 6 pilares para o desenvolvimento de uma arquitetura bem estruturada pelo Well-Architected Framework:
Os pilares são bem diretos e simples de entender por conta, porém, o desafio vem com o catálogo de serviços AWS que atendem a diferentes demandas em diferentes situações. Assim, o desafio não é em entender os pilares em si, mas saber como orientar decisões com base nesses pilares.
Como orquestrar minha arquitetura?
Componentes de computação possuem um grande volume de geração de logs e métricas. Monitorar individualmente todo esse volume é inviável, assim, arquiteturas robustas normalmente contam com sistemas de monitoramento integrado, como o Grafana.
Além do monitoramento, componentes precisam comunicar entre si e existem diferentes abordagens para casos específicos. Caso o desafio necessite de uma orquestração determinística de serviços, o AWS Step Functions pode ser a solução para desenvolvimento de fluxos de execução encadeado. Para disparos programados por tempo ou eventos específicos (como o put de dados em um bucket S3), o EventBridge pode disparar serviços com base em regras temporais ou eventos em outros recursos. Por outro lado, caso um componente precise processar um volume muito acima de sua capacidade, filas de processamento SQS podem ser utilizadas para organizar a entrada desses payloads para processamento.
Finalmente, o melhor caminho para realizar a integração e deploy de novo código continuamente, o ideal não seria atualizações manuais, mas sim esteiras automáticas de CI/CD. A AWS fornece elementos para esse processo usando AWS CodeConnections para conectar a um repositório Git, CodePipeline para orquestrar o CI/CD, CodeBuild para realizar o empacotamento de códigos IaC e deploy na nuvem AWS.
Como montar soluções seguras?
Esse é um tema recorrente em todos os serviços e recursos AWS. Existem diversas formas e níveis de aumentar a segurança no uso da nuvem. Uma dessas formas é a criptografia de dados, que pode ser feita at-rest usando KMS ou in-flight usando API Gateway HTTPS por exemplo. Muitos dos serviços AWS já fornecem criptografia at-rest default, como S3 e DynamoDB. Ao usar KMS, a gestão das chaves passa a ser responsabilidade da arquitetura, dando também maior flexibilidade de uso.
Para recursos de computação, como EC2, ECS, EKS, Lambda, dentre outros, podemos sempre isolar os mesmos em uma VPC com regras específicas de acesso por meio de Security Groups. Assim, a arquitetura passa a ter um controle de acesso feito por meio de um isolamento dos recursos em uma rede privada. Para se conectar à rede, serviços como NAT Gateway, Internet Gateway, VPC endpoints, dentre outros podem ser utilizados para criar uma conexão segura.
Em termos de segurança de acesso, serviços como o WAF proveem uma camada de firewall para APIs criadas na arquitetura. O IAM restringe o nível de acesso que serviços e recursos possuem na arquitetura. Ao construir roles e policies, optar por permissionamento mínimo sempre provê uma camada extra de segurança. Além desses, serviços como Cognito adicionam uma camada de segurança de acesso ao criar um sistema de autenticação.
Como fazer uma arquitetura resiliente?
A pior coisa que um sistema pode sofrer é uma queda de serviços ou recursos, logo, lidar com esse cenário é essencial para ter uma arquitetura resiliente a falhas. Nesse contexto, a AWS provê ferramentas de robustez, como as Regions e Availability Zones, que permitem o deploy de estruturas em regiões geográficas distintas e independentes. Bancos de dados e S3 podem se beneficiar disso realizando réplicas cross-region dos dados e permitindo recuperação até em janelas de tempo bem pequenas. Já serviços de computação podem aproveitar de deploy multi-AZ para permitir que recursos continuem operando mesmo em quedas locais de AZ.
Em alguns cenários, desastres são inevitáveis, mas uma arquitetura resiliente é projetada para se recuperar nesses casos. Estratégias de replicação de infraestrutura em outras regiões podem ser adotadas para mitigar downtime, desde uma replicação completa do sistema sempre operante (multi-site) até backups prontos para subir em outras regiões. O ponto decisivo nesses casos é sempre o equilíbrio entre custo e tempo de resposta, se a aplicação é crítica talvez faça mais sentido ter um multi-site pronto para ter 0 downtime. Já aplicações menos delicadas podem se beneficiar de ter uma estrutura warm-started em outra região e passar por um período de indisponibilidade de serviços.
Como projetar soluções eficientes?
Em termos de performance, existem 2 grandes aspectos a serem considerados: o uso eficiente de recursos e a escalabilidade. Muitos serviços AWS já são preparados para atender esses dois aspectos por meio de provisão serverless, onde não há servidores a serem gerenciados. Assim, opções de computação como Lambda, EMR Serverless e Glue possuem uma escalabilidade natural de forma horizontal. Alguns serviços de armazenamento como S3, DynamoDB e Aurora também possuem elasticidade para que você possa armazenar dados sem limites.
Entretanto, em muitos casos precisamos adotar serviços server-based em nossas arquiteturas, para isso temos opções de elasticidade com Auto Scaler e Load Balancer, que permite que novas instâncias sejam lançadas horizontalmente à medida que demandas aumentam no sistema. Essas soluções andam em par com provisionamento por containers, como ECS ou EKS. Em termos de bancos de dados provisionados, réplicas de leitura podem aumentar o poder de escala do seu sistema provendo instâncias dedicadas a leitura de dados.
Finalmente, quanto à escala vertical de serviços e recursos (sejam ou não serverless), o CloudWatch pode ser a ferramenta apropriada para monitorar as métricas de instâncias ou recursos acusando déficits ou super-provisionamento. A escolha da família correta de instâncias ou tamanho apropriado de serviços serverless balanceia melhor o custo e poder de processamento das soluções.
Como otimizar o consumo?
Uma grande potência ou grande problema da arquitetura é o custo dos serviços e recursos. Uma arquitetura mal projetada ou mal dimensionada pode facilmente inviabilizar o sistema em produção. Quando escolher recursos e serviços, pense sempre em alguns pontos de otimização:
Finalmente, sempre utilize dos serviços de monitoramento do CloudWatch para verificar o dimensionamento apropriado de recursos, além de usar o Cost Explorer para buscar por pontos do seu sistema que possam estar custando alto.
Como reduzir o impacto ambiental?
Finalmente, no pilar de sustentabilidade, o impacto ambiental das nossas soluções é analisado. Ao otimizar o uso de recursos e dimensionamento de serviços, você já garante que a sua arquitetura não está gerando consumo desnecessário (tanto em energia quanto em água). Outro ponto para ficar atento é o armazenamento indeterminado de dados, que pode não só causar impacto ambiental, mas também de custos. Aplique regras de lifecicle nos dados para movê-los para armazenamentos frios e fatalmente deletar dados que não serão mais necessários.
Um caso bem específico, mas crescente no mundo moderno é o uso de IA generativa, que consome um grande volume de processamento (energia e água). Ao usar modelos de IA, busque otimizar o seu prompt para um processamento mais preciso, além de escolher um modelo de dimensionamento apropriado para a tarefa. Essa preocupação não só vai reduzir o impacto dos prompts no ambiente como vai economizar em tokens na fatura AWS.
É hora de pôr em prática!
Projetar uma arquitetura bem desenvolvida na AWS não é algo apenas de teoria, o jeito mais eficiente de aprender como usar melhor os recursos e como escolher serviços para casos específicos é colocar a mão na massa! Ao pensar sempre nesses 6 pilares de uma boa arquitetura e ao desenvolver muitas soluções em nuvem, a tomada de decisão passa a ficar cada vez mais intuitiva e natural. Finalmente, sempre esteja atento às ferramentas de monitoramento e observabilidade dos seus sistemas para identificar pontos de melhoria e bons padrões de desenvolvimento!