Apostila - Módulo 2 - Bootcamp Profissional DevOps
Apostila - Módulo 2 - Bootcamp Profissional DevOps
Antonio Muniz
2022
A Primeira Maneira: Os Princípios do Fluxo
Bootcamp: Profissional DevOps
Antonio Muniz
© Copyright do Instituto de Gestão e Tecnologia da Informação.
Todos os direitos reservados.
2
Sumário
Referências……… ..............................................................................................................47
3
Capítulo 1. Pipeline de Implantação
No livro Entrega Contínua (2014), por Jez Humble e David Farley, é apresentado
um fluxo muito interessante de como funciona a entrega contínua, apresentado na
figura a seguir. Neste processo, alguns detalhes mais específicos serão abstraídos
apenas para o melhor entendimento de como funciona o processo do início ao fim.
4
É importante conhecer os principais benefícios e requisitos que a utilização de
pipelines traz para a organização. Listamos a seguir algumas práticas de mercado, assim
como recomendações do livro The DevOps Handbook (2016):
1. Benefícios:
5
em um ambiente de pré-produção, mas que seja feito todos os dias.
Este processo ensina como fazer mais e errar menos.
6
este material. Tudo fica registrado por padrão, deixando a equipe mais
ágil também com auditorias.
Requisitos:
7
importância, pois eles serão fundamentais para a evolução do projeto, de forma que se
tornem um estado futuro do seu ambiente, algo que a empresa busque alcançar para
melhorar seu ambiente como um todo.
Definição de pronto
8
entregue. Esta seria a definição mais comum para as equipes ágeis. O complemento do
mundo DevOps é que isso deve ser demonstrado em um ambiente do tipo produção.
Então, quando tudo que foi feito e que pode ser entregue for demonstrado em
ambiente tipo produção (ambiente muito próximo ou de preferência igual ao de
produção) será considerado como pronto.
9
Capítulo 2. Testes Automatizados
Este capítulo apresenta os principais conceitos sobre os testes, que são uma
parte fundamental do desenvolvimento do software, já que são eles que garantem e
atestam a qualidade (funcionalidade, usabilidade, performance, segurança etc.) do
software desenvolvido antes mesmo de ser implantado (entrar em produção).
10
Execução de casos testes =entrada
(dados de teste) + saída esperada.
11
Figura 1 – Entrega Contínua: Modelo Ideal.
12
Testes unitários: inicialmente, os testes focalizam cada componente do
produto individualmente, garantindo que ele funcione como unidade.
13
eoutros casos sensíveis ao tempo e identifica a carga ou volume
máximo persistente que o sistema pode suportar por um dado período.
Precisa ser pensado em qual momento do pipeline esses testes devem ser
executados para não perder tempo no deploy da aplicação. Idealmente, os testes
unitários são executados sempre que se sobe uma versão para o primeiro ambiente que
o código for promovido. Eles podem ser executados de forma paralela (potencialmente
em servidores diferentes), ganhando tempo na sua execução.
14
Fonte: LivroJornada DevOps, Brasport (2019).
15
Que o desenvolvedor entenda que não é só o código, mas que também a
qualidade do código é da sua responsabilidade. Quando a execução dos testes
é realizada de forma manual e por outra pessoa, a tendência é que o
desenvolvedor “relaxe” na qualidade, já que existe outra fase de garantia de
qualidade após o desenvolvimento. Quando esta fase passa a não existir, ou é
limitada, o desenvolvedor e o time tomam para si (senso de propriedade) a
responsabilidade pela qualidade.
Que seja feita a análise estática do código, ou seja, que o código seja analisado
por ferramentas que o levem a seguir um padrão de codificação que provê uma
melhor manutenibilidade no código.
16
Aprendizado constante: o ciclo curto de errar e acertar permite ao
desenvolvedor aprender e não propagar o mesmo erro em outros trechos de
código. Nos testes manuais os erros são descobertos tardiamente, dificultando
o aprendizado.
Neste cenário, a priorização deve ser dada aos testes unitários, que são a base
da pirâmide. Nós precisamos de testes automatizados mais rápidos e mais baratos, que
sejam executados junto com o build e em ambientes de testes sempre que uma nova
alteração for submetida ao sistema de controle de versão (pipeline de implantação).
Neste sentido, deveríamos ter grandes volumes de testes unitários automatizados.
17
Nem sempre os níveis de testes são desenvolvidos pelos mesmos
desenvolvedores. Em determinadas situações, os profissionais de qualidade
desenvolvem os testes de aceitação. No entanto, é necessário que seja discutido com o
time quais testes foram implementados e em quais níveis, para que os testes não se
tornem redundantes.
O seu desenvolvimento deve ser formado por uma pirâmide ideal de testes,
garantindo uma entrega contínua com o objetivo final do green build e de um software
com qualidade.
18
Além disso, os testes de aceitação só devem ser implementados quando há
uma certa “estabilidade” das interfaces dela. Funcionalidades que estão ainda em testes
A/B ou de usabilidade não devem ser possíveis de serem automatizadas, já que isso
causaria certo desperdício, visto que a aplicação está mudando muito dinamicamente.
Uma das maneiras mais eficazes para garantir que haja testes automatizados
confiáveis é escrever esses testes como parte da metodologia de desenvolvimento. Ken
Beck, um dos criadores da agilidade, definiu TDD da seguinte forma: “TDD = Test-First +
Design Incremental”.
19
Figura 3 – Sequência básica TDD.
Esta é uma técnica voltada para escrita de testes unitários automatizados, que
funciona em três passos:
20
2. No segundo passo, o desenvolvedor escreve somente o código suficiente
para passar no teste e, ao executar a compilação deste código, o teste vai
passar. Por isso, chamamos esta etapa de verde.
21
Um único teste não pode testar todas as funcionalidades em um único
método. Iniciar com Testes Unitários e depois amadurecer para pensar nos
testes de integração.
Não existe bala de prata: o teste unitário deve ser criado passo a passo.
Para que seja possível simular objetos reais e ainda não implementados, ou até
mesmo objetos que sejam difíceis de serem implementados, uma estratégia
amplamente utilizada é o mock de objetos. Os principais motivos para a sua utilização
são:
22
Figura 4 – Representação de mocks de banco de dados e serviços.
É uma abordagem que funciona muito bem com a metodologia ágil e encoraja
desenvolvedores e pessoas não técnicas e de negócio a utilizarem uma linguagem única,
facilitando a conversação. Dan North (2003) concebeu o Behavior Driven Development
(BDD) em resposta ao TDD, retirando a palavra “Teste” da técnica e trazendo para o foco
a questão do comportamento das telas. Dentro do ciclo de desenvolvimento, estes
23
cenários de testes são automatizados; são o que chamamos de testes de aceitação. Ele
segue na mesma concepção do TDD, em que os testes precisam ser desenvolvidos
primeiro. Neste caso, os comportamentos que o sistema precisa apresentar são
definidos e implementados primeiro.
24
Figura 6 – Funcionamento do BDD em cinco passos.
25
Figura 7 – Exemplo de um cenário em gherkin.
26
Facilita o aceite do cliente, pois existe a representação do negócio nos
exemplos aceitos.
27
Capítulo 3. Integração Contínua
28
Figura 8 – Histórico do controlador de versão mostrando os conceitos de master,
branches e tags.
29
em pegar todas as mudanças realizadas no branch e sincronizar com o trunk, deixando
todo o conteúdo junto na linha principal de desenvolvimento. No entanto, apesar de
juntos a partir do merge, seus históricos de alteração continuam armazenados de forma
separada
30
Atualmente, a prática mostra que as empresas estão cada vez mais buscando a
ideia de desenvolvimento em uma linha principal, onde é minimizado a quantidade de
branches em paralelo com muito tempo sem fazer o merge. Isso se dá até porque o uso
de muitas branches podem aumentar o débito técnico do projeto, tema que será
abordado em detalhes sobre a melhor estratégia de branching e como diminuir o débito
técnico do seu projeto.
31
ao DevOps ser uma cultura muito colaborativa, essa situação é uma ótima chance para
transformar um problema em uma oportunidade de melhoria e integração entre os
times, seguindo o exemplo da Toyota de puxar a corda de andon.Logo, quando um
código quebrado é encontrado, todos se juntam para resolver o problema juntose assim
seguir com os commits frequentes novamente.
A dívida técnica é aquela situação de erro ou falta de qualidade que não causa
um impacto grande a ponto de parar um processo. Com isso, acaba sempre sendo
deixada de lado para melhorias futuras, que nunca acontecem.
Essas são duas características muito comuns que aumentam a dívida técnica:
Os erros que não são corrigidos e acabam sendo deixados de lado até causar um
problema grande, que leva a uma grande dificuldade de realizar uma entrega de
qualidade pela quantidade de erros e cuidado com o processo de integração contínua.
Muitos outros fatores também são responsáveis por gerar este débito técnico.
Muitos dos erros não corrigidos têm como origem um código sujo. Quando um código
precisa de muitos comentários para ser compreendido, usa-se nomes para variáveis e
métodos que não fazem sentido, o que ignora as melhores práticas do mercado.
32
As boas práticas de desenvolvimento são conhecidas como clean code (código
limpo). Práticas que buscam sempre melhorar o código, colocar uma boa descrição na
classe e nomes para métodos e variáveis que sejam autoexplicativos evitando a
necessidade de comentários para explicar o porquê de cada linha de código. Essas
estratégias são fundamentais para evitar comentários esquecidos sem manutenção e
facilitar o entendimento do código na próxima melhoria a ser feita na aplicação.
Este cenário gera um ciclo vicioso perigoso. Código mal feito gera bugs
escondidos, que muitas vezes surgem devido a testes ineficazes. O bug pode ser aquele
erro que ninguém percebe que existe ou que o usuário já se acostumou que vai
acontecer, mesmo que isso seja algo muito ruim. O bug também pode ser não funcional,
que o cliente não percebe. Um cenário que fica gerando alertas para a equipe, faz com
que sejam considerados como normais. Algo ignorado ao invés de consertado.
33
Uma das estratégias mais importantes é o desenvolvimento baseado no trunk.
Como mencionado anteriormente, existem duas abordagens: produtividade individual
e produtividade da equipe, sendo esta a estratégia baseada no trunk. A produtividade
da equipe sempre será a melhor escolha na jornada DevOps. Desta forma, os erros são
notificados de forma mais eficiente, possibilitando sua resolução de modo muito mais
rápido.
Para remover problemas antigos, é comum reunir uma equipe para realizar
blitz de melhorias. O problema pode ser algo recorrente ou uma melhoria muito
importante para o projeto. Esse processo é similar ao feito em iniciativas Lean, que corta
34
elementos que não entregam mais valor para o projeto ou para a organização. Assim,
serão feitas melhorias em cenários que realmente importam. A equipe de reunião para
a blitz naturalmente já conhece as maiores dores de cabeça do projeto, as que
prejudicam a performance diária de seu cliente.
A blitz também pode ser feita para refatorar ou reestruturar códigos para deixá-
los mais limpos. O ponto principal é a proatividade em atuar em situações mais críticas,
ao invés da reação quando o problema já se tornou grande demais para se administrar
de forma simples.
35
Capítulo 4. Release de Baixo Risco
No final das contas, o release é que importa para o cliente na prática, e pode
ser realizado seguindo as duas categorias relacionadas apresentadas a seguir, que
detalharemos no decorrer deste capítulo.
36
Figura 10 – Categorias de Release.
Release azul-verde:
37
Uma vez que temos a carga de acessos sendo toda direcionada para um
ambiente, podemos fazer o deploy/release no ambiente que está “off-line” sem
problemas. Depois de tudo pronto, apenas trocamos a direção dos acessos para este
novo cluster e mantemos o cluster como backup, caso haja algum problema durante o
release.
Vamos supor que você desenvolveu uma nova versão do seu software, passou
por todas as etapas de ciclo de vida da aplicação e tudo já está pronto para ser inserido
no ambiente produtivo. Neste momento, teremos dois ambientes distintos no ar, um
carinhosamente apelidado de verde e o outro de azul - um com uma versão atual, outro
sem versão nenhuma. No ambiente azul temos a versão atual do software, com toda a
carga de acesso direcionada a ele. A ideia aqui é realizar o release desta nova versão
desenvolvida e testada no ambiente verde. Agora, temos duas versões, uma antiga e a
nova em ambientes similares e concorrentes. Na frente dos acessos, teremos um
roteador que irá direcionar a carga de acessos para este novo ambiente (verde). Esta
troca é feita da forma mais suave possível, sendo que, após a realização deste
chaveamento de acessos, o ambiente antigo (azul) poderá ser desativado após a troca,
ou também poderá ser mantido como backup para a próxima release. Nesta última
solução, teremos sempre uma última versão em ambiente produtivo.
Esta é uma técnica bastante usada para releases de baixo risco, pois se no
decorrer desta troca houver algum problema no deploy/release, o rollback poderá ser
38
feito o mais rápido possível e sua correção também poderá ser executada o mais rápido
possível.
Release Canário
39
o risco de introdução a uma nova versão de software em produção, por uma troca
gradual para um grupo pequeno de usuários, até que fique disponível para todos”.
O release canário (figura abaixo) é uma técnica bem utilizada para realizar a
troca de cluster da forma mais suave possível, ou focando em um nicho de mercado
primeiro.
40
Após todo o direcionamento de acessos ter sido concluído, a versão antiga é
desativada. Esta técnica também é conhecida como Lançamento Incremental
(incremental rollout) ou Lançamento em Fases (phased rollout).
41
Figura 14 – Feature Toggles e seus benefícios de Implantação canário.
Imagine que você está em casa em um final de semana tranquilo com sua
família, fazendo aquele churrasco, tomando aquela cervejinha e, de repente, toca o
celular: é o seu chefe desesperado. A aplicação da sua empresa parou e ninguém faz
ideia do que aconteceu. Você então precisa deixar sua família e os amigos de lado e sair
correndo para a empresa ou, no melhor dos casos, acessar seu ambiente remotamente
via VPN da empresa. Adeus final de semana.
42
Você calmamente olha os logs para entender o que pode ter acontecido e
descobre: uma conexão, que não é fechada em um looping, que criava diversos pools de
conexão no banco até que ele não tinha mais pool disponível e travou.
Claro que hoje esta é uma situação hipotética, mas já aconteceu muito no
passado.
Agora, imagina o tempo (e dinheiro) que a empresa perdeu com esse erro
aparentemente simples de ser resolvido? Pense na quantidade de pessoas que podem
não concretizado a compra em algum produto em uma plataforma online, digamos que
em uma Black Friday? Estudos afirmam que e-commerces off-line perdem cerca de 208
milhões de dólares por hora com este tipo de situação.
Para citarmos um exemplo prático, imagine que somos um banco e temos duas
aplicações apenas: nosso website e o aplicativo de celular. Ambos têm seu
43
desenvolvimento apartado, cada um usando uma tecnologia diferente, porém
chamando serviços relativamente iguais. Neste caso, vamos supor que temos um único
serviço de extrato desenvolvido de forma independente, com seu código simples e
online em um servidor. Tanto a aplicação web quanto o aplicativo de celular, por meio
de sua interface, irá chamar esse mesmo serviço que está online, independente dos
outros.
44
A arquitetura orientada a microsserviços permite que as aplicações sejam feitas
a partir de diversos outros serviços menores e independentes, visando uma melhoria na
disponibilidade da aplicação e evitando que diversas tardes de domingo fossem
interrompidas por problemas que facilmente poderiam ser resolvidos depois.
Não estou aqui falando que a estrutura monolítica não seja nunca
recomendada, mas acredito que é um conceito antigo, tendo em vista que hoje
reciclamos muito código (temos até padrões de desenvolvimento que ajudam nisso).
Ter em uma única aplicação todas as transações (Ex.: financeiro, cadastro de novos
usuários, meios de pagamento, cadastro de funcionários, RH etc.) não costuma ser uma
boa ideia quando precisamos de alta disponibilidade, escalabilidade e também ter uma
aplicação que se unirá automaticamente a outros ambientes e irá evoluir de forma
independente frente a outras aplicações e projetos.
45
A autora Susan Fowler apresenta com profundidade um conjunto de padrões
de microsserviços, aproveitando sua experiência de padronização de mais de mil
microsserviços do Uber.
46
Referências
HUMBLE, Jez; FARLEY, David. Entrega Contínua: Como Entregar Software de Forma
Rápida e Confiável. Tradução: Rafael Prikladnicki Marco Aurélio Valtas Cunha e Ronaldo
Melo Ferraz. Bookman, 2013.
KIM, Gene et al. The DevOps Handbook: How to Create World-Class Agility, Reliability,
and Security in Technology Organizations. IT Revolution Press, 2016.
MUNIZ, Antonio et al. Jornada DevOps: unindo cultura ágil, Lean e tecnologia para
entrega de software de qualidade. Brasport, 2019.
47