O que aprendi testando 200 linhas de código de infraestrutura

O que aprendi testando 200 linhas de código de infraestrutura

Abordagem IaC (Infraestrutura como Código) consiste não apenas no código que está armazenado no repositório, mas também nas pessoas e processos que cercam esse código. É possível reutilizar abordagens desde o desenvolvimento de software até o gerenciamento e descrição de infraestrutura? Seria uma boa ideia manter essa ideia em mente enquanto você lê o artigo.

Versão em Inglês

Esta é uma transcrição do meu performances em DevopsConf 2019/05/28.

Slides e vídeos

Infraestrutura como histórico do bash

O que aprendi testando 200 linhas de código de infraestrutura

Suponha que você chegue a um novo projeto e eles lhe digam: “temos Infraestrutura como código". Na realidade acontece Infraestrutura como histórico do bash ou por exemplo Documentação como histórico do bash. Esta é uma situação muito real, por exemplo, um caso semelhante foi descrito por Denis Lysenko num discurso Como substituir toda a infraestrutura e começar a dormir profundamente, ele contou como eles conseguiram uma infraestrutura coerente para o projeto a partir da história do bash.

Com algum desejo, podemos dizer que Infraestrutura como histórico do bash isso é como o código:

  1. reprodutibilidade: você pode pegar o histórico do bash, executar os comandos a partir daí e, a propósito, obter uma configuração funcional como saída.
  2. versionamento: você sabe quem entrou e o que fez, novamente, não é fato que isso o levará a uma configuração funcional na saída.
  3. história: a história de quem fez o quê. só que você não poderá usá-lo se perder o servidor.

O que fazer?

Infraestrutura como código

O que aprendi testando 200 linhas de código de infraestrutura

Mesmo um caso tão estranho como Infraestrutura como histórico do bash você pode puxá-lo pelas orelhas Infraestrutura como código, mas quando quisermos fazer algo mais complicado que o bom e velho servidor LAMP, chegaremos à conclusão de que esse código precisa ser modificado, alterado, melhorado de alguma forma. A seguir, gostaríamos de considerar os paralelos entre Infraestrutura como código e desenvolvimento de software.

SECO

O que aprendi testando 200 linhas de código de infraestrutura

Em um projeto de desenvolvimento de sistema de armazenamento, havia uma subtarefa configurar periodicamente o SDS: estamos lançando uma nova versão - ela precisa ser lançada para mais testes. A tarefa é extremamente simples:

  • faça login aqui via ssh e execute o comando.
  • copie o arquivo lá.
  • corrija a configuração aqui.
  • inicie o serviço lá
  • ...
  • LUCRO!

Para a lógica descrita, o bash é mais que suficiente, principalmente nas fases iniciais do projeto, quando ele está apenas começando. Esse não é ruim você usar o bash, mas com o tempo surgem solicitações para implantar algo semelhante, mas um pouco diferente. A primeira coisa que vem à mente é copiar e colar. E agora já temos dois scripts muito parecidos que fazem quase a mesma coisa. Com o passar do tempo o número de scripts cresceu, e nos deparamos com o fato de que existe uma certa lógica de negócio para implantar uma instalação que precisa ser sincronizada entre diferentes scripts, isso é bastante complicado.

O que aprendi testando 200 linhas de código de infraestrutura

Acontece que existe uma prática chamada DRY (Do not Repeat Yourself). A ideia é reutilizar o código existente. Parece simples, mas não chegamos a isso imediatamente. No nosso caso, foi uma ideia banal: separar configurações de scripts. Aqueles. lógica de negócios de como a instalação é implantada separadamente, configurações separadamente.

SÓLIDO para CFM

O que aprendi testando 200 linhas de código de infraestrutura

Com o tempo o projeto cresceu e continuação natural foi o surgimento do Ansible. O principal motivo de seu surgimento é que há expertise na equipe e que o bash não foi projetado para lógicas complexas. Ansible também começou a conter lógica complexa. Para evitar que lógica complexa se transforme em caos, existem princípios para organizar código no desenvolvimento de software SÓLIDO Além disso, por exemplo, Grigory Petrov no relatório “Por que um especialista em TI precisa de uma marca pessoal” levantou a questão de que uma pessoa é projetada de tal forma que é mais fácil para ela operar com algumas entidades sociais, no desenvolvimento de software estas são objetos. Se combinarmos estas duas ideias e continuarmos a desenvolvê-las, perceberemos que também podemos usar SÓLIDO para facilitar a manutenção e modificação desta lógica no futuro.

O Princípio da Responsabilidade Única

O que aprendi testando 200 linhas de código de infraestrutura

Cada turma executa apenas uma tarefa.

Não há necessidade de misturar códigos e criar monstros de espaguete divinos monolíticos. A infraestrutura deverá consistir em tijolos simples. Acontece que se você dividir o manual do Ansible em pequenos pedaços e ler os papéis do Ansible, eles serão mais fáceis de manter.

O Princípio Aberto Fechado

O que aprendi testando 200 linhas de código de infraestrutura

Princípio aberto/fechado.

  • Aberto à extensão: significa que o comportamento de uma entidade pode ser estendido através da criação de novos tipos de entidade.
  • Fechado para alterações: como resultado da extensão do comportamento de uma entidade, nenhuma alteração deve ser feita no código que utiliza essas entidades.

Inicialmente, implantamos a infraestrutura de teste em máquinas virtuais, mas devido ao fato da lógica de negócios de implantação ser separada da implementação, adicionamos a implementação para baremetall sem problemas.

O Princípio da Substituição de Liskov

O que aprendi testando 200 linhas de código de infraestrutura

Princípio da substituição de Barbara Liskov. objetos em um programa devem ser substituíveis por instâncias de seus subtipos sem alterar a execução correta do programa

Se você olhar de forma mais ampla, não é uma característica de nenhum projeto específico que possa ser aplicado lá SÓLIDO, geralmente é sobre CFM, por exemplo, em outro projeto é necessário implantar um aplicativo Java in a box sobre vários Java, servidores de aplicativos, bancos de dados, sistemas operacionais, etc. Usando este exemplo, considerarei outros princípios SÓLIDO

No nosso caso, existe um acordo dentro da equipe de infraestrutura de que se tivermos instalado a função imbjava ou oraclejava, então teremos um executável binário java. Isto é necessário porque As funções upstream dependem desse comportamento; elas esperam java. Ao mesmo tempo, isso nos permite substituir uma implementação/versão Java por outra sem alterar a lógica de implantação do aplicativo.

O problema aqui reside no facto de ser impossível implementar isto no Ansible, pelo que surgem alguns acordos dentro da equipa.

O Princípio de Segregação de Interface

O que aprendi testando 200 linhas de código de infraestrutura

Princípio de separação de interface: “Muitas interfaces específicas do cliente são melhores do que uma interface de uso geral.

Inicialmente, tentamos colocar toda a variabilidade de implantação de aplicativos em um manual do Ansible, mas era difícil de suportar, e a abordagem quando especificamos uma interface externa (o cliente espera a porta 443), então uma infraestrutura pode ser montada a partir de indivíduos tijolos para uma implementação específica.

O Princípio da Inversão de Dependência

O que aprendi testando 200 linhas de código de infraestrutura

O princípio da inversão de dependência. Módulos em níveis superiores não devem depender de módulos em níveis inferiores. Ambos os tipos de módulos devem depender de abstrações. As abstrações não devem depender de detalhes. Os detalhes devem depender de abstrações.

Aqui o exemplo será baseado em um antipadrão.

  1. Um dos clientes tinha uma nuvem privada.
  2. Encomendamos máquinas virtuais dentro da nuvem.
  3. Porém, devido à natureza da nuvem, a implantação do aplicativo estava vinculada ao hipervisor em que a VM estava.

Aqueles. A lógica de implantação de aplicativos de alto nível fluía com dependências para níveis inferiores do hipervisor, e isso significava problemas ao reutilizar essa lógica. Não faça assim.

Interação

O que aprendi testando 200 linhas de código de infraestrutura

Infraestrutura como código não trata apenas de código, mas também do relacionamento entre código e pessoas, de interações entre desenvolvedores de infraestrutura.

fator de barramento

O que aprendi testando 200 linhas de código de infraestrutura

Vamos supor que você tenha Vasya em seu projeto. Vasya sabe tudo sobre sua infraestrutura. O que acontecerá se Vasya desaparecer repentinamente? Esta é uma situação muito real, porque ele poderia ser atropelado por um ônibus. As vezes acontece. Se isso acontecer e o conhecimento sobre o código, sua estrutura, funcionamento, aparência e senhas não for distribuído entre a equipe, você poderá se deparar com uma série de situações desagradáveis. Para minimizar esses riscos e distribuir o conhecimento dentro da equipe, você pode usar diversas abordagens

Devolução em pares

O que aprendi testando 200 linhas de código de infraestrutura

Não é como Como uma piada, que os administradores beberam cerveja, mudaram senhas e um análogo da programação em pares. Aqueles. dois engenheiros sentam-se em frente a um computador, um teclado e começam a configurar sua infraestrutura juntos: configurar um servidor, escrever uma função Ansible, etc. Parece bom, mas não funcionou para nós. Mas casos especiais desta prática funcionaram. Chega um novo funcionário, seu mentor assume uma tarefa real junto com ele, trabalha e transfere conhecimento.

Outro caso especial é uma chamada de incidente. Durante um problema, um grupo de plantonistas e envolvidos se reúne, um líder é nomeado, que compartilha sua tela e expressa a linha de pensamento. Outros participantes acompanham os pensamentos do líder, espionam truques no console, verificam se não perderam nenhuma linha no log e aprendem coisas novas sobre o sistema. Essa abordagem funcionou na maioria das vezes.

Revisão de código

O que aprendi testando 200 linhas de código de infraestrutura

Subjetivamente, foi mais eficaz disseminar o conhecimento sobre a infraestrutura e como ela funciona por meio da revisão de código:

  • A infraestrutura é descrita por código no repositório.
  • As alterações ocorrem em uma filial separada.
  • Durante uma solicitação de mesclagem, você pode ver o delta das alterações na infraestrutura.

O destaque aqui foi que os revisores foram selecionados um a um, de acordo com um cronograma, ou seja, com algum grau de probabilidade você entrará em uma nova peça de infraestrutura.

Estilo do código

O que aprendi testando 200 linhas de código de infraestrutura

Com o passar do tempo, começaram a aparecer brigas durante as avaliações, porque... os revisores tinham seu próprio estilo e a rotação dos revisores os empilhava em estilos diferentes: 2 espaços ou 4, camelCase ou snake_case. Não foi possível implementar isso imediatamente.

  • A primeira ideia foi recomendar o uso do linter, afinal todo mundo é engenheiro, todo mundo é inteligente. Mas diferentes editores, sistemas operacionais, não são convenientes
  • Isso evoluiu para um bot que escrevia no Slack para cada commit problemático e anexa a saída do linter. Mas na maioria dos casos havia coisas mais importantes a fazer e o código permanecia sem correção.

Mestre de construção verde

O que aprendi testando 200 linhas de código de infraestrutura

O tempo passa e chegamos à conclusão de que commits que não passam em determinados testes não podem ser permitidos no master. Voilá! Inventamos o Green Build Master, que já é praticado no desenvolvimento de software há muito tempo:

  • O desenvolvimento está em andamento em uma filial separada.
  • Os testes estão sendo executados neste tópico.
  • Se os testes falharem, o código não chegará ao mestre.

Tomar essa decisão foi muito doloroso, porque... causou muita polêmica, mas valeu a pena, porque. As avaliações começaram a receber solicitações de fusões sem diferenças de estilo e, com o tempo, o número de áreas problemáticas começou a diminuir.

Teste IaC

O que aprendi testando 200 linhas de código de infraestrutura

Além da verificação de estilo, você pode usar outras coisas, por exemplo, para verificar se sua infraestrutura pode realmente ser implantada. Ou verifique se as mudanças na infraestrutura não levarão à perda de dinheiro. Por que isso pode ser necessário? A questão é complexa e filosófica, é melhor responder com uma história de que de alguma forma houve um escalonador automático no Powershell que não verificou as condições de limite => mais VMs foram criadas do que o necessário => o cliente gastou mais dinheiro do que o planejado. Isso não é muito agradável, mas seria bem possível detectar esse erro em estágios anteriores.

Alguém poderia perguntar: por que tornar a infraestrutura complexa ainda mais complexa? Os testes de infraestrutura, assim como os de código, não tratam de simplificação, mas de saber como sua infraestrutura deve funcionar.

Pirâmide de Teste IaC

O que aprendi testando 200 linhas de código de infraestrutura

Teste IaC: Análise Estática

Se você implantar toda a infraestrutura de uma vez e verificar se ela funciona, poderá descobrir que isso leva muito tempo e exige muito tempo. Portanto, a base deve ser algo que funcione rápido, é muito e cobre muitos lugares primitivos.

Bash é complicado

Vejamos um exemplo trivial. selecione todos os arquivos no diretório atual e copie para outro local. A primeira coisa que vem à mente:

for i in * ; do 
    cp $i /some/path/$i.bak
done

E se houver um espaço no nome do arquivo? Bem, ok, somos inteligentes, sabemos como usar aspas:

for i in * ; do cp "$i" "/some/path/$i.bak" ; done

Bom trabalho? Não! E se não houver nada no diretório, ou seja, globbing não funcionará.

find . -type f -exec mv -v {} dst/{}.bak ;

Bem feito agora? Não... Esqueci o que pode estar no nome do arquivo n.

touch x
mv x  "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir

Ferramentas de análise estática

O problema da etapa anterior pode ser detectado quando esquecemos as aspas, para isso existem muitos remédios na natureza Verificação de shell, em geral, existem muitos deles e provavelmente você pode encontrar um linter para sua pilha no seu IDE.

Língua
ferramenta

bater
Verificação de shell

Ruby
Rubo Cop

python
Pilão

ansible
Lint Ansible

Teste IaC: testes unitários

O que aprendi testando 200 linhas de código de infraestrutura

Como vimos no exemplo anterior, os linters não são onipotentes e não podem apontar todas as áreas problemáticas. Além disso, por analogia com os testes no desenvolvimento de software, podemos relembrar os testes unitários. O que imediatamente vem à mente é evite, Junit, rspec, pergunta. Mas o que fazer com ansible, chef, saltstack e outros como eles?

No início falamos sobre SÓLIDO e que a nossa infra-estrutura deveria consistir em pequenos tijolos. Chegou a hora deles.

  1. A infraestrutura é dividida em pequenos blocos, por exemplo, funções Ansible.
  2. Algum tipo de ambiente é implantado, seja um docker ou uma VM.
  3. Aplicamos nossa função Ansible a este ambiente de teste.
  4. Verificamos se tudo funcionou como esperávamos (realizamos testes).
  5. Nós decidimos ok ou não.

Teste IaC: ferramentas de teste unitário

Pergunta, o que são testes para CFM? Você pode simplesmente executar o script ou usar soluções prontas para isso:

CFM
ferramenta

Ansible
Testinfra

Chefe de cozinha
Inspecionar

Chefe de cozinha
Especificação do servidor

Saltstack
Goss

Exemplo para testinfra, verificando se os usuários test1, test2 existem e estão em um grupo sshusers:

def test_default_users(host):
    users = ['test1', 'test2' ]
    for login in users:
        assert host.user(login).exists
        assert 'sshusers' in host.user(login).groups

O que escolher? A questão é complexa e ambígua, aqui está um exemplo de mudanças em projetos no GitHub para 2018-2019:

O que aprendi testando 200 linhas de código de infraestrutura

Estruturas de teste IaC

Surge a pergunta: como juntar tudo e lançar? Pode pegue e faça você mesmo se houver um número suficiente de engenheiros. Ou você pode pegar soluções prontas, embora não existam muitas delas:

CFM
ferramenta

Ansible
molécula

Chefe de cozinha
Cozinha de teste

Terraform
Terratest

Exemplo de mudanças em projetos no GitHub para 2018-2019:

O que aprendi testando 200 linhas de código de infraestrutura

Molécula vs. Cozinha de teste

O que aprendi testando 200 linhas de código de infraestrutura

Inicialmente nós tentei usar testkitchen:

  1. Crie uma VM em paralelo.
  2. Aplique funções Ansible.
  3. Execute a inspeção.

Para 25 a 35 funções funcionou de 40 a 70 minutos, o que foi longo.

O que aprendi testando 200 linhas de código de infraestrutura

O próximo passo foi a transição para jenkins/docker/ansible/molecule. Idiologicamente tudo é igual

  1. Manuais do Lint.
  2. Alinhe os papéis.
  3. Lançar contêiner
  4. Aplique funções Ansible.
  5. Execute testinfra.
  6. Verifique a idempotência.

O que aprendi testando 200 linhas de código de infraestrutura

Linting para 40 papéis e testes para uma dúzia começou a levar cerca de 15 minutos.

O que aprendi testando 200 linhas de código de infraestrutura

O que escolher depende de muitos fatores, como a pilha utilizada, a experiência da equipe, etc. aqui cada um decide por si mesmo como fechar a questão do teste de unidade

Teste IaC: testes de integração

O que aprendi testando 200 linhas de código de infraestrutura

O próximo passo na pirâmide de testes de infraestrutura serão os testes de integração. Eles são semelhantes aos testes de unidade:

  1. A infraestrutura é dividida em pequenos blocos, por exemplo, funções Ansible.
  2. Algum tipo de ambiente é implantado, seja um docker ou uma VM.
  3. Para este ambiente de teste, aplique muitos Papéis ansible.
  4. Verificamos se tudo funcionou como esperávamos (realizamos testes).
  5. Nós decidimos ok ou não.

Grosso modo, não verificamos o desempenho de um elemento individual do sistema como nos testes unitários, verificamos como o servidor está configurado como um todo.

Teste IaC: testes ponta a ponta

O que aprendi testando 200 linhas de código de infraestrutura

No topo da pirâmide somos recebidos por testes End to End. Aqueles. Não verificamos o desempenho de um servidor separado, de um script separado ou de um bloco separado de nossa infraestrutura. Verificamos se há muitos servidores conectados entre si, nossa infraestrutura funciona como esperamos. Infelizmente, nunca vi soluções prontas em caixa, provavelmente porque... A infraestrutura costuma ser única e difícil de modelar e criar uma estrutura para testes. Como resultado, cada um cria suas próprias soluções. Há uma demanda, mas não há resposta. Portanto, vou lhe contar o que existe para levar os outros a pensamentos sólidos ou esfregar meu nariz no fato de que tudo foi inventado há muito tempo, antes de nós.

O que aprendi testando 200 linhas de código de infraestrutura

Um projeto com uma história rica. Ele é usado em grandes organizações e provavelmente cada um de vocês se cruzou indiretamente com ele. O aplicativo suporta muitos bancos de dados, integrações, etc. Saber como será a infraestrutura envolve muitos arquivos docker-compose e saber quais testes executar em qual ambiente é o Jenkins.

O que aprendi testando 200 linhas de código de infraestrutura

Este esquema funcionou durante bastante tempo, até que no âmbito pesquisa não tentamos transferir isso para o Openshift. Os contêineres permanecem os mesmos, mas o ambiente de lançamento mudou (olá DRY novamente).

O que aprendi testando 200 linhas de código de infraestrutura

A ideia da pesquisa foi além e, no openshift, eles encontraram algo como APB (Ansible Playbook Bundle), que permite agrupar o conhecimento de como implantar infraestrutura em um contêiner. Aqueles. existe um ponto de conhecimento repetível e testável sobre como implantar a infraestrutura.

O que aprendi testando 200 linhas de código de infraestrutura

Tudo isso parecia bom até que nos deparamos com uma infraestrutura heterogênea: precisávamos do Windows para testes. Como resultado, o conhecimento sobre o que, onde, como implantar e testar está no Jenkins.

Conclusão

O que aprendi testando 200 linhas de código de infraestrutura

Infraestrutura como código é

  • Código no repositório.
  • Interação humana.
  • Testes de infraestrutura.

Links

Fonte: habr.com

Adicionar um comentário