O que é Nativo de Nuvem?
Dica
Esse conteúdo é um trecho do livro eletrônico, para Projetar os Aplicativos .NET nativos de nuvem para o Azure, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.
Pare o que você está fazendo e peça a seus colegas que definam o termo "Cloud Native". Há uma boa chance de você obter várias respostas diferentes.
Vamos começar com uma definição simples:
A arquitetura e as tecnologias nativas de nuvem são uma abordagem para projetar, construir e operar cargas de trabalho criadas na nuvem e aproveitar ao máximo o modelo de computação em nuvem.
A Cloud Native Computing Foundation fornece a definição oficial:
As tecnologias nativas de nuvem capacitam as organizações a criar e executar aplicativos escalonáveis em ambientes modernos e dinâmicos, como nuvens públicas, privadas e híbridas. Contêineres, malhas de serviço, microsserviços, infraestrutura imutável e APIs declarativas exemplificam essa abordagem.
Essas técnicas permitem sistemas flexíveis que são resilientes, gerenciáveis e observáveis. Combinados com automação robusta, eles permitem que os engenheiros façam alterações de alto impacto de maneira frequente e previsível com o mínimo de trabalho.
A nuvem nativa diz respeito a velocidade e agilidade. Os sistemas de negócios estão evoluindo desde a habilitação de funcionalidades de negócios até o desenvolvimento de transformações estratégicas que aceleram a velocidade e o crescimento dos negócios. É fundamental colocar novas ideias no mercado imediatamente.
Ao mesmo tempo, os sistemas de negócios também se tornaram cada vez mais complexos, com os usuários exigindo mais. Eles esperam capacidade de resposta rápida, recursos inovadores e tempo de inatividade zero. E não aceitam mais problemas com desempenho, erros recorrentes e incapacidade de se mover rapidamente. Seus usuários visitarão seu concorrente. Os sistemas nativos de nuvem foram projetados para adotar mudanças rápidas, grandes escalas e resiliência.
Aqui estão algumas empresas que implementaram técnicas nativas de nuvem. Pense na velocidade, na agilidade e na escalabilidade que eles atingiram.
Empresa | Experiência |
---|---|
Netflix | Tem mais de 600 serviços em produção. Implanta 100 vezes por dia. |
Uber | Tem mais de mil serviços em produção. Implanta milhares de vezes por semana. |
Tem mais de 3.000 serviços em produção. Implanta mil vezes por dia. |
Como você pode ver, Netflix, Uber e WeChat expõem sistemas nativos de nuvem que consistem em muitos serviços independentes. Esse estilo de arquitetura permite que eles respondam rapidamente às condições do mercado. Eles atualizam instantaneamente pequenas áreas de um aplicativo ativo e complexo, sem uma reimplantação completa. Eles dimensionam individualmente os serviços conforme a necessidade.
Os pilares da nuvem nativa
A velocidade e a agilidade da nuvem nativa derivam de muitos fatores. Em primeiro lugar, é a infraestrutura de nuvem. Mas há mais: cinco outros pilares fundamentais mostrados na Figura 1-3 também fornecem a base de sistemas nativos de nuvem.
Figura 1-3. Pilares básicos nativos de nuvem
Vamos levar algum tempo para entender melhor a importância de cada pilar.
A nuvem
Os sistemas nativos de nuvem aproveitam ao máximo o modelo de serviço de nuvem.
Projetados para crescer em um ambiente de nuvem dinâmico e virtualizado, esses sistemas fazem uso extensivo da infraestrutura de computação de PaaS (Plataforma como Serviço) e serviços gerenciados. Eles tratam a infraestrutura subjacente como descartável, provisionada em minutos e redimensionada, escalada ou destruída sob demanda, por meio de automatização.
Considere a diferença entre como tratamos animais de estimação e mercadorias. Em um data center tradicional, os servidores são tratados como animais de estimação: uma máquina física, que recebe um nome significativo e cuidados. Você dimensiona adicionando mais recursos ao mesmo computador (escala vertical). Se o servidor ficar mal, você o cura. Se o servidor ficar indisponível, todos notarão.
O modelo de serviço de mercadorias é diferente. Você provisiona cada instância como uma máquina virtual ou um contêiner. Eles são idênticos e atribuídos a um identificador do sistema, como Service-01, Service-02 e assim por diante. Você dimensiona criando mais instâncias (escalar horizontalmente). Ninguém percebe quando uma instância fica indisponível.
O modelo de mercadorias adota uma infraestrutura imutável. Os servidores não são reparados nem modificados. Se um falha ou exige atualização, ele é destruído e outro é provisionado, tudo por meio de automação.
Os sistemas nativos de nuvem adotam o modelo de serviço de mercadorias. Eles continuam a ser executados à medida que a infraestrutura é dimensionada ou reduzida horizontalmente, sem levar em conta os computadores nos quais eles estão em execução.
A plataforma de nuvem do Azure dá suporte a esse tipo de infraestrutura altamente elástica com recursos automáticos de dimensionamento, autorrecuperação e monitoramento.
Design moderno
Como você criaria um aplicativo nativo de nuvem? Qual seria a aparência da sua arquitetura? Quais princípios, padrões e práticas recomendadas você seguiria? Quais preocupações operacionais e de infraestrutura seriam importantes?
O aplicativo Twelve-Factor
Uma metodologia amplamente aceita para criar aplicativos baseados em nuvem é o Aplicativo Twelve-Factor. Ele descreve um conjunto de princípios e práticas que os desenvolvedores seguem para construir aplicativos otimizados para ambientes de nuvem modernos. Atenção especial é dada à portabilidade entre ambientes e à automação declarativa.
Embora aplicável a qualquer aplicativo baseado na Web, muitos profissionais consideram o Twelve-Factor uma base sólida para a criação de aplicativos nativos de nuvem. Sistemas com base nesses princípios podem implantar e dimensionar rapidamente e adicionar recursos para reagir rapidamente às alterações no mercado.
A tabela abaixo destaca a metodologia Twelve-Factor:
Fator | Explicação |
---|---|
1 – Base de Código | Uma única base de código para cada microsserviço, armazenada em seu próprio repositório. Rastreada com controle de versão, ela pode ser implantada em vários ambientes (QA, Preparação, Produção). |
2 – Dependências | Cada microsserviço isola e empacota suas próprias dependências, adotando alterações sem afetar todo o sistema. |
3 – Configurações | As informações de configuração são removidas do microsserviço e externalizadas por meio de uma ferramenta de gerenciamento de configuração fora do código. A mesma implantação pode se propagar entre ambientes com a configuração correta aplicada. |
4 – Serviços de backup | Os recursos auxiliares (armazenamentos de dados, caches, agentes de mensagens) devem ser expostos por meio de uma URL acessível. Isso desacopla o recurso do aplicativo, permitindo que ele seja intercambiável. |
5 – Compilar, lançar, executar | Cada versão deve impor uma separação estrita nas fases de build, liberação e execução. Cada uma deve ser marcada com uma ID exclusiva e dar suporte à capacidade de reversão. Os sistemas de CI/CD modernos ajudam a atender a esse princípio. |
6 – Processos | Cada microsserviço deve ser executado em seu próprio processo, isolado de outros serviços em execução. Externalize o estado necessário para um serviço de backup, como um cache distribuído ou um armazenamento de dados. |
7 – Associação de porta | Cada microsserviço deve ser autossuficiente, com as interfaces e funcionalidades expostas em sua própria porta. Isso fornece isolamento em relação a outros microsserviços. |
8 – Simultaneidade | Quando a capacidade precisar aumentar, escale os serviços horizontalmente em vários processos idênticos (cópias) em vez de escalar verticalmente uma única instância grande no computador mais poderoso disponível. Desenvolva o aplicativo para ser simultâneo, fazendo o dimensionamento contínuo em ambientes de nuvem. |
9 – Descartabilidade | As instâncias de serviço devem ser descartáveis. Favoreça a inicialização rápida para aumentar as oportunidades de escalabilidade e desligamentos suaves a fim de deixar o sistema em um estado correto. Os contêineres do Docker, juntamente com um orquestrador, atendem inerentemente a esse requisito. |
10 – Paridade Desenvolvimento/Produção | Mantenha os ambientes em todo o ciclo de vida do aplicativo o mais semelhantes possível, evitando atalhos caros. Aqui, a adoção de contêineres pode contribuir muito com a promoção do mesmo ambiente de execução. |
11 – Registro em log | Trate logs gerados por microsserviços como fluxos de eventos. Processe-os com um agregador de eventos. Propague dados de log para ferramentas de gerenciamento de log/mineração de dados, como o Azure Monitor ou o Splunk, e, eventualmente, para arquivamento de longo prazo. |
12 – Processos de Administração | Execute tarefas administrativas/de gerenciamento, como limpeza de dados ou análise de computação, como processos únicos. Use ferramentas independentes para invocar essas tarefas do ambiente de produção, mas separadamente do aplicativo. |
No livro Além do aplicativo Twelve-Factor,o autor Kevin Hoffman detalha cada um dos 12 fatores originais (escritos em 2011). Além disso, ele aborda três fatores extras que refletem o design moderno de aplicativos de nuvem de hoje.
Novo Fator | Explicação |
---|---|
13 – Priorização da API | Torne tudo um serviço. Suponha que seu código será consumido por um cliente de front-end, gateway ou outro serviço. |
14 – Telemetria | Em uma estação de trabalho, você tem visibilidade profunda sobre seu aplicativo e seu comportamento. Na nuvem, não há isso. Faça com que seu design inclua a coleção de dados de monitoramento, específicos do domínio e de saúde/sistema. |
15 – Autenticação/autorização | Implemente a identidade desde o início. Considere os recursos do RBAC (controle de acesso baseado em função) disponíveis em nuvens públicas. |
Nos referiremos a muitos outros dos 12 fatores neste capítulo e em todo o livro.
Estrutura bem arquitetada do Azure
Projetar e implantar cargas de trabalho baseadas em nuvem pode ser um desafio, especialmente ao implementar a arquitetura nativa de nuvem. A Microsoft fornece práticas recomendadas padrão do setor para ajudar você e sua equipe a fornecer soluções robustas de nuvem.
O Microsoft Well-Architected Framework fornece um conjunto de princípios de orientação que podem ser usados para melhorar a qualidade de uma carga de trabalho nativa de nuvem. A estrutura consiste em cinco pilares de excelência em arquitetura:
Princípios | Descrição |
---|---|
Gerenciamento de Custos | Concentre-se em gerar valor incremental antecipadamente. Aplique os princípios de Criar-Medir-Aprender para acelerar o tempo de colocação no mercado a fim de evitar soluções com uso intensivo de capital. Usando uma estratégia de pagamento conforme o uso, invista à medida que escalar, em vez de fazer um grande investimento inicial. |
Excelência operacional | Automatize o ambiente e as operações para aumentar a velocidade e reduzir o erro humano. Reverta ou propague atualizações de problemas rapidamente. Implemente o monitoramento e o diagnóstico desde o início. |
Eficiência do desempenho | Cumpra com eficiência as demandas colocadas em suas cargas de trabalho. Favorecer o dimensionamento horizontal (expansão) e projete-o em seus sistemas. Conduza continuamente testes de desempenho e carga para identificar possíveis gargalos. |
Confiabilidade | Crie cargas de trabalho resilientes e disponíveis. A resiliência permite que as cargas de trabalho se recuperem de falhas e continuem funcionando. A disponibilidade garante que os usuários acessem sua carga de trabalho o tempo todo. Projete aplicativos para que esperem falhas e se recuperem delas. |
Segurança | Implemente a segurança em todo o ciclo de vida de um aplicativo, desde o design e a implementação até a implantação e as operações. Preste muita atenção ao gerenciamento de identidades, ao acesso à infraestrutura, à segurança do aplicativo, à soberania e à criptografia de dados. |
Para começar, a Microsoft fornece um conjunto de avaliações online para ajudá-lo a avaliar suas cargas de trabalho de nuvem atuais em relação aos cinco pilares de boa arquitetura.
Microsserviços
Os sistemas nativos de nuvem adotam microsserviços, um estilo de arquitetura popular para a construção de aplicativos modernos.
Criado como um conjunto distribuído de serviços pequenos e independentes que interagem por meio de uma malha compartilhada, os microsserviços compartilham as seguintes características:
Cada um implementa uma funcionalidade de negócios específica dentro de um contexto de domínio maior.
Cada um é desenvolvido de forma autônoma e pode ser implantado de forma independente.
Cada um deles é autossuficiente e encapsula sua própria tecnologia de armazenamento de dados, dependências e plataforma de programação.
Cada é executado em seu próprio processo e se comunica com outros usando protocolos de comunicação padrão, como HTTP/HTTPS, gRPC, WebSockets ou AMQP.
Eles se juntam para formar um aplicativo.
A Figura 1-4 contrasta uma abordagem de aplicativo monolítico com uma abordagem de microsserviços. Observe como o monolito é composto por uma arquitetura em camadas, que é executada em um único processo. Normalmente, ele consome um banco de dados relacional. No entanto, a abordagem de microsserviço separa a funcionalidade em serviços independentes, cada um com sua própria lógica, estado e dados. Cada microsserviço hospeda seu próprio armazenamento de dados.
Figura 1-4. Arquitetura monolítica X Microsserviços
Observe como os microsserviços promovem o princípio de Processos do Aplicativo Twelve-Factor discutido anteriormente no capítulo.
O fator n.º 6 especifica que cada microsserviço deve ser executado em seu próprio processo, isolado de outros serviços em execução.
Por que os microsserviços?
Os microsserviços fornecem agilidade.
No início do capítulo, comparamos um aplicativo de comércio eletrônico criado como um monolito a um com microsserviços. No exemplo, vimos alguns benefícios claros:
Cada microsserviço tem um ciclo de vida autônomo e pode evoluir independentemente e implantá-los com frequência. Você não precisa aguardar uma versão trimestral para implantar um novo recurso ou atualização. Você pode atualizar uma pequena área de um aplicativo ao vivo com menos risco de interromper todo o sistema. A atualização pode ser feita sem uma reimplantação completa do aplicativo.
Cada microsserviço pode ser dimensionado independentemente. Em vez de dimensionar todo o aplicativo como uma única unidade, você expande apenas os serviços que exigem mais capacidade de processamento para atender aos níveis de desempenho e contratos de nível de serviço desejados. O dimensionamento granular fornece maior controle do sistema e ajuda a reduzir os custos gerais à medida que você dimensiona partes do sistema, não tudo.
Um excelente guia de referência para entender os microsserviços é o Microsserviços .NET: arquitetura para aplicativos .NET em contêineres. O livro se aprofunda no design e na arquitetura de microsserviços. Ele acompanha uma arquitetura de referência de microsserviços full-stack disponível como um download gratuito da Microsoft.
Desenvolvendo microsserviços
Os microsserviços podem ser criados em qualquer plataforma de desenvolvimento moderna.
A plataforma Microsoft.NET é uma excelente opção. Gratuito e de código aberto, ele tem muitos recursos integrados que simplificam o desenvolvimento de microsserviços. O.NET é uma plataforma cruzada. Os aplicativos podem ser criados e executados no Windows, no macOS e na maioria dos tipos do Linux.
O.NET é de alto desempenho e tem boa pontuação em comparação com Node.js e outras plataformas concorrentes. É curioso que o TechEmpower estabeleceu um amplo conjunto de parâmetros de comparação de desempenho em várias plataformas e estruturas de aplicativo Web. O .NET ficou entre os 10 principais, bem acima do Node.js e de outras plataformas concorrentes.
O .NET é mantido pela Microsoft e pela comunidade do .NET GitHub.
Desafios de microsserviço
Embora os microsserviços nativos de nuvem distribuídos possam fornecer agilidade e velocidade enormes, eles apresentam muitos desafios:
Comunicação
Como os aplicativos cliente de front-end se comunicarão com microsserviços de back-end essenciais? Você permitirá a comunicação direta? Ou pode abstrair os microsserviços de back-end com uma fachada de gateway que fornece flexibilidade, controle e segurança?
Como os microsserviços de back-end essenciais se comunicarão entre si? Você permitirá chamadas HTTP diretas que podem aumentar o acoplamento e afetar o desempenho e a agilidade? Ou poderá considerar o sistema de mensagens desacoplado com tecnologias de fila e tópico?
A comunicação é abordada no capítulo Padrões de comunicação nativos de nuvem.
Resiliência
Uma arquitetura de microsserviços move seu sistema de comunicação de rede do processo para fora dele. Em uma arquitetura distribuída, o que acontece quando o Serviço B não está respondendo a uma chamada de rede do Serviço A? Ou o que acontece quando o Serviço C fica temporariamente indisponível e outros serviços que o chamam ficam bloqueados?
A resiliência é abordada no capítulo Resiliência nativa de nuvem.
Dados Distribuídos
Por design, cada microsserviço encapsula seus próprios dados, expondo operações por meio de sua interface pública. Se esse é o caso, como consultar dados ou implementar uma transação em vários serviços?
Os dados distribuídos são abordados no capítulo Padrões de dados nativos da nuvem.
Segredos
Como seus microsserviços armazenarão e gerenciarão com segurança segredos e dados confidenciais de configuração?
Os segredos são abordados em detalhes em Segurança nativa de nuvem.
Gerenciar complexidade com Dapr
O Dapr é um runtime de aplicativo de código aberto distribuído. Por meio de uma arquitetura de componentes conectáveis, ele simplifica drasticamente o encanamento por trás de aplicativos distribuídos. Ele fornece uma cola dinâmica que associa seu aplicativo a recursos e componentes de infraestrutura pré-criados do runtime do Dapr. A Figura 1-5 mostra o Dapr a 20 mil pés.
Figura 1-5. Dapr a 20 mil pés.
Na linha superior da figura, observe como o Dapr fornece SDKs específicos à linguagem para plataformas de desenvolvimento populares. O Dapr v1 inclui suporte a .NET, Go, Node.js, Python, PHP, Java e JavaScript.
Embora os SDKs específicos à linguagem aprimorem a experiência do desenvolvedor, o Dapr é independente da plataforma. Nos bastidores, o modelo de programação do Dapr expõe os recursos por meio de protocolos de comunicação HTTP/gRPC padrão. Qualquer plataforma de programação pode chamar o Dapr por meio de suas APIs HTTP e gRPC nativas.
As caixas azuis no centro da figura representam os blocos de construção do Dapr. Cada um expõe o código de encanamento pré-criado a uma funcionalidade de aplicativo distribuído que seu aplicativo pode consumir.
A linha de componentes representa um grande conjunto de componentes de infraestrutura pré-definidos que seu aplicativo pode consumir. Pense em componentes como código de infraestrutura que você não precisa programar.
A linha inferior destaca a portabilidade do Dapr e os diversos ambientes nos quais ele pode ser executado.
Pensando no futuro, o Dapr tem o potencial de ter um impacto profundo no desenvolvimento de aplicativos nativos de nuvem.
Contêineres
É natural ouvir o termo contêiner mencionado em qualquer conversa sobre nativo de nuvem. No livro Padrões Nativos de Nuvem, a autora Cornelia Davis observa que "os contêineres são ótimos para permitir software nativo de nuvem". A Cloud Native Computing Foundation coloca a conteinerização de microsserviço como a primeira etapa em seu Mapa de Trilha de Nativo de Nuvem, diretrizes para empresas que começam sua jornada nativa de nuvem.
A conteinerização de um microsserviço é simples e direta. O código, suas dependências e o runtime são empacotados em um binário chamado imagem de contêiner. As imagens são armazenadas em um registro de contêiner, que atua como um repositório ou uma biblioteca para imagens. Um registro pode estar localizado em seu computador de desenvolvimento, em seu data center ou em uma nuvem pública. O próprio Docker mantém um registro público por meio do Docker Hub. A nuvem do Azure apresenta um registro de contêiner privado para armazenar imagens de contêiner perto dos aplicativos de nuvem que as executarão.
Quando um aplicativo é iniciado ou escalado, você transforma a imagem de contêiner em uma instância de contêiner em execução. A instância é executada em qualquer computador que tenha um mecanismo de runtime de contêiner instalado. Você pode ter quantas instâncias do serviço conteinerizado forem necessárias.
A Figura 1-6 mostra três microsserviços diferentes, cada um em seu próprio contêiner, todos em execução em um único host.
Figura 1-6. Vários contêineres em execução em um host de contêiner
Observe como cada contêiner mantém seu próprio conjunto de dependências e runtime, que podem ser diferentes uns dos outros. Aqui, vemos versões diferentes do microsserviço Produto em execução no mesmo host. Cada contêiner compartilha uma fatia do sistema operacional, memória e processador do sistema operacional host, mas está isolado um do outro.
Observe como o modelo de contêiner adota o princípio Dependências do Aplicativo Twelve-Factor.
O fator n.º 2 especifica que cada microsserviço isola e empacota suas próprias dependências, adotando alterações sem afetar todo o sistema.
Os contêineres são suportados por cargas de trabalho Windows e Linux. A nuvem do Azure adota ambos amplamente. O interessante é que o Linux, não o Windows Server, se tornou o sistema operacional mais popular no Azure.
Embora existam vários fornecedores de contêineres, o Docker obteve a maior participação do mercado. A empresa tem impulsionado o movimento de contêineres de software. Ela se tornou o padrão de fato para empacotamento, implantação e execução de aplicativos nativos de nuvem.
Por que contêineres?
Os contêineres fornecem portabilidade e garantem a consistência entre ambientes. Ao encapsular tudo em um único pacote, você isola o microsserviço e suas dependências da infraestrutura subjacente.
Você pode implantar o contêiner em qualquer ambiente que hospede o mecanismo de runtime do Docker. As cargas de trabalho em contêineres também eliminam as despesas de pré-configuração de cada ambiente com estruturas, bibliotecas de software e mecanismos de runtime.
Ao compartilhar o sistema operacional subjacente e os recursos de host, um contêiner tem uma pegada muito menor do que uma máquina virtual completa. O tamanho menor aumenta a densidade, ou o número de microsserviços que um determinado host pode executar ao mesmo tempo.
Orquestração de contêineres
Embora ferramentas como o Docker criem imagens e executem contêineres, você também precisa de ferramentas para gerenciá-las. O gerenciamento de contêineres é feito com um programa de software especial chamado orquestrador de contêineres. Na operação em escala com muitos contêineres em execução independentes, a orquestração é essencial.
A Figura 1-7 mostra as tarefas de gerenciamento que os orquestradores de contêineres automatizam.
Figura 1-7. O que os orquestradores de contêineres fazem
A tabela a seguir descreve tarefas de orquestração comuns.
Tarefas | Explicação |
---|---|
Agendamento | Provisionar automaticamente instâncias de contêiner. |
Afinidade/antiafinidade | Provisionar contêineres próximos ou distantes uns dos outros, ajudando na disponibilidade e no desempenho. |
Monitoramento da integridade | Detectar e corrigir falhas automaticamente. |
Failover | Reprovisionar automaticamente uma instância com falha em um computador íntegro. |
Scaling | Adicionar ou remover automaticamente uma instância de contêiner para atender à demanda. |
Rede | Gerenciar uma sobreposição de rede para comunicação entre contêineres. |
Descoberta de Serviços | Habilitar os contêineres a localizarem uns aos outros. |
Atualizações sem interrupção | Coordenar atualizações incrementais com uma implantação sem tempo de inatividade. Reverter alterações problemáticas automaticamente. |
Observe como os orquestradores de contêineres adotam os princípios de Descartabilidade e Simultaneidade do Aplicativo Twelve-Factor.
O fator n.º 9 especifica que as instâncias de serviço devem ser descartáveis, favorecendo as inicializações rápidas para aumentar as oportunidades de escalabilidade e os desligamentos normais para deixar o sistema em um estado correto. Os contêineres do Docker, junto com um orquestrador, atendem inerentemente a esse requisito.
O fator n.º 8 especifica que os serviços se expandem por um grande número de pequenos processos idênticos (cópias), em oposição à expansão de uma única instância grande no computador mais potente disponível.
Embora existam vários orquestradores de contêineres, o Kubernetes se tornou o padrão de fato para o mundo nativo de nuvem. É uma plataforma portátil, extensível e de código aberto para gerenciar cargas de trabalho em contêineres.
Você pode hospedar sua própria instância do Kubernetes, mas seria responsável por provisionar e gerenciar seus recursos, o que pode ser complexo. A nuvem do Azure apresenta o Kubernetes como um serviço gerenciado. Tanto o AKS (Serviço de Kubernetes do Azure) quanto o Red Hat OpenShift no Azure permitem que você aproveite totalmente os recursos e a potência do Kubernetes como um serviço gerenciado, sem precisar instalá-lo e mantê-lo.
A orquestração de contêineres é abordada em detalhes no Dimensionamento de aplicativos nativos de nuvem.
Serviços de backup
Os sistemas nativos de nuvem dependem de vários recursos auxiliares diferentes, como armazenamentos de dados, agentes de mensagens, monitoramento e serviços de identidade. Esses serviços são conhecidos como serviços de backup.
A Figura 1-8 mostra muitos serviços de backup comuns que os sistemas nativos de nuvem consomem.
Figura 1-8. Serviços de backup comuns
Você pode hospedar seus próprios serviços de backup, mas aí será responsável por licenciar, provisionar e gerenciar esses recursos.
Os provedores de nuvem oferecem uma vasta variedade de serviços de backup gerenciados. Em vez de possuir o serviço, basta consumi-lo. O provedor de nuvem opera o recurso em escala e assume a responsabilidade pelo desempenho, pela segurança e pela manutenção. O monitoramento, a redundância e a disponibilidade são incorporados ao serviço. Os provedores garantem o desempenho no nível do serviço e dão suporte total aos serviços gerenciados; abra um tíquete para que eles corrijam o problema.
Os sistemas nativos de nuvem favorecem serviços de backup gerenciados de fornecedores de nuvem. A economia no tempo e no trabalho pode ser significativa. O risco operacional de hospedar seu próprio sistema e enfrentar problemas pode sair mais caro.
Uma prática recomendada é tratar um serviço de backup como um recurso anexado, vinculado dinamicamente a um microsserviço com informações de configuração (uma URL e credenciais) armazenadas em uma configuração externa. Essa diretriz está descrita no Aplicativo Twelve-Factor discutido anteriormente no capítulo.
O fator n.º 4 especifica que os serviços de backup devem ser expostos por meio de uma URL acessível. Isso desacopla o recurso do aplicativo, permitindo que ele seja intercambiável.
O fator n.º 3 especifica que as informações de configuração são removidas do microsserviço e externalizadas por meio de uma ferramenta de gerenciamento de configuração fora do código.
Com esse padrão, um serviço de backup pode ser anexado e desanexado sem alterações de código. Você pode promover um microsserviço de QA para um ambiente de preparo. Você atualiza a configuração de microsserviço para apontar para os serviços de backup no preparo e injetar as configurações em seu contêiner por meio de uma variável de ambiente.
Os fornecedores de nuvem fornecem APIs para que você se comunique com seus serviços de backup proprietários. Essas bibliotecas encapsulam a complexidade e o encanamento proprietários. No entanto, a comunicação direta com essas APIs acoplará seu código rigidamente a esse serviço de backup específico. É uma prática amplamente aceita isolar os detalhes de implementação da API do fornecedor. Introduza uma camada de intermediação, ou uma API intermediária, expondo operações genéricas ao seu código de serviço e encapsulando o código do fornecedor dentro dele. Esse acoplamento flexível permite que você troque um serviço de backup por outro ou mova seu código para um ambiente de nuvem diferente sem precisar fazer alterações no código de serviço principal. O Dapr, discutido anteriormente, segue esse modelo com seu conjunto de blocos de construção predefinidos.
Em uma ideia final, os serviços de backup também promovem o princípio Sem estado do Aplicativo Twelve-Factor discutido anteriormente no capítulo.
O fator n.º 6 especifica que cada microsserviço deve ser executado em seu próprio processo, isolado de outros serviços em execução. Externalize o estado necessário para um serviço de backup, como um cache distribuído ou um armazenamento de dados.
Os serviços de backup são discutidos em Padrões de dados nativos de nuvem e Padrões de comunicação nativos de nuvem.
Automação
Como você viu, os sistemas nativos de nuvem adotam microsserviços, contêineres e design de sistema modernos para obter velocidade e agilidade. Mas isso é apenas parte da história. Como provisionar os ambientes de nuvem nos quais esses sistemas são executados? Como você implanta rapidamente recursos e atualizações do aplicativo? Como você arredonda o panorama completo?
Entra aqui a prática amplamente aceita da Infraestrutura como Código, ou IaC.
Com a IaC, você automatiza o provisionamento de plataforma e a implantação de aplicativos. Essencialmente, você aplica práticas de engenharia de software, como teste e controle de versão, às suas práticas de DevOps. Sua infraestrutura e implantações são automatizadas, consistentes e repetíveis.
Automatizando a infraestrutura
Ferramentas como o Azure Resource Manager, o Azure Bicep, o Terraform da HashiCorp e a CLI do Azure permitem que você crie declarativamente o script de infraestrutura de nuvem. Nomes de recursos, locais, capacidades e segredos são parametrizados e dinâmicos. O script tem controle de versão e há check-in no controle do código-fonte como um artefato do seu projeto. Você invoca o script para provisionar uma infraestrutura consistente e reproduzível entre ambientes de sistema, como QA, preparo e produção.
Nos bastidores, a IaC é idempotente, o que significa que você pode executar o mesmo script repetidamente sem efeitos colaterais. Se a equipe precisar fazer uma alteração, ela editará e executará novamente o script. Somente os recursos atualizados são afetados.
No artigo O que é Infraestrutura como Código, o autor Sam Guckenheimer a descreve como "equipes que implementam a IaC pode fornecer ambientes estáveis rapidamente e em escala. Elas evitam a configuração manual de ambientes e impõem a consistência, representando o estado desejado de seus ambientes por meio de código. As implantações de infraestrutura com IaC são repetíveis e evitam problemas de tempo de execução causados por descompasso de configuração ou dependências ausentes. As equipes de DevOps podem trabalhar junto com um conjunto unificado de práticas e ferramentas para fornecer aplicativos e sua infraestrutura de suporte de forma rápida, confiável e em escala.”
Automatizando implantações
O Aplicativo Twelve-Factor, discutido anteriormente, pede etapas separadas ao transformar o código concluído em um aplicativo em execução.
O fator n.º 5 especifica que cada versão precisa impor uma separação estrita nas fases de build, liberação e execução. Cada uma deve ser marcada com uma ID exclusiva e dar suporte à capacidade de reversão.
Os sistemas de CI/CD modernos ajudam a atender a esse princípio. Eles fornecem etapas de compilação e entrega separadas que ajudam a garantir o código consistente e de qualidade que fica prontamente disponível para os usuários.
A Figura 1-9 mostra a separação ao longo do processo de implantação.
Figura 1-9. Etapas de implantação em um pipeline de CI/CD
Na figura anterior, preste atenção especial à separação das tarefas:
- O desenvolvedor constrói um recurso em seu ambiente de desenvolvimento, iterando por meio do que é chamado de "loop interno" de código, execução e depuração.
- Quando concluído, esse código é enviado por push a um repositório de código, como GitHub, Azure DevOps ou BitBucket.
- O push dispara uma fase de build que transforma o código em um artefato binário. O trabalho é implementado com um pipeline de CI (integração contínua). Ele compila, testa e empacota automaticamente o aplicativo.
- A fase de liberação pega o artefato binário, aplica informações de configuração de ambiente e aplicativo externo e produz uma versão imutável. A versão é implantada em um ambiente especificado. O trabalho é implementado com um pipeline de CD (Entrega Contínua). Cada versão deve ser identificável. Você pode escrever "esta implantação está executando a versão 2.1.1 do aplicativo".
- Por fim, o recurso liberado é executado no ambiente de execução de destino. As versões são imutáveis, o que significa que toda alteração precisa criar uma nova versão.
Com a aplicação dessas práticas, as organizações evoluíram radicalmente o modo de enviar software. Muitos mudaram de versões trimestrais para atualizações sob demanda. O objetivo é capturar problemas no início do ciclo de desenvolvimento, quando eles são menos caros de corrigir. Quanto maior a duração entre as integrações, mais cara fica a solução dos problemas. Com a consistência no processo de integração, as equipes podem confirmar as alterações de código com maior frequência, levando a uma melhor colaboração e qualidade de software.
A infraestrutura como automação de código e implantação, juntamente com o GitHub e o Azure DevOps, são discutidos detalhadamente no DevOps.