Enterprise DevOps: como uma grande empresa coleta microsserviços

Olá pessoal!


A Netracker desenvolve e fornece aplicativos corporativos para o mercado global de operadoras de telecomunicações há muitos anos. O desenvolvimento de tais soluções é bastante complicado: centenas de pessoas participam de projetos e o número de projetos ativos nas dezenas.


Anteriormente, os produtos eram monolíticos, mas agora estamos avançando com confiança para aplicativos de microsserviço. O DevOps enfrentou uma tarefa bastante ambiciosa - fornecer esse salto tecnológico.


Como resultado, obtivemos um conceito de montagem bem-sucedido, que queremos compartilhar como uma prática recomendada. A descrição da implementação com detalhes técnicos será bastante volumosa; não faremos isso dentro da estrutura deste artigo.


No caso geral, montagem é a transformação de alguns artefatos em outros.


Quem estará interessado


As empresas que fornecem software pronto para uma organização completamente terceirizada e são pagas por isso.


Veja como o desenvolvimento pode parecer sem entrega externa:


  • O departamento de TI da fábrica desenvolve software para sua empresa.
  • A empresa está envolvida na terceirização para um cliente estrangeiro. O cliente compila e opera esse código independentemente em seu próprio servidor web.
  • A empresa fornece software para clientes externos, mas sob uma licença de código aberto. A maior parte da responsabilidade é assim aliviada.

Se você não se deparar com suprimentos externos, grande parte do que está escrito abaixo parecerá redundante ou até paranóico.


Na prática, tudo deve ser feito em conformidade com os requisitos internacionais para as licenças e criptografia usadas, caso contrário, pelo menos, conseqüências legais surgirão.


Um exemplo de violação é pegar o código de uma biblioteca com uma licença GPL3 e incorporá-lo em um aplicativo comercial.


O surgimento de microsserviços requer mudanças


Adquirimos uma vasta experiência na montagem e entrega de aplicações monolíticas.


Vários servidores Jenkins, milhares de trabalhos de CI, várias linhas de montagem totalmente automatizadas baseadas no Jenkins, dezenas de engenheiros de versão dedicados, seu próprio grupo de especialistas em gerenciamento de configurações.


Historicamente, a abordagem da empresa era a seguinte: os desenvolvedores escrevem o código-fonte e o DevOps inventa e escreve a configuração do sistema de montagem.


Como resultado, tivemos duas ou três configurações típicas de montagem projetadas para operação no ecossistema corporativo. Esquematicamente, fica assim:



A ferramenta de compilação geralmente é ant ou maven, e algo é implementado por plug-ins publicamente disponíveis, algo é escrito por si só. Isso funciona bem quando uma empresa usa um conjunto restrito de tecnologias.


Os microsserviços diferem das aplicações monolíticas principalmente na variedade de tecnologias.


Acontece muitas configurações de montagem para pelo menos cada linguagem de programação. O controle centralizado se torna impossível.


É necessário simplificar o máximo possível os scripts de montagem e permitir que os desenvolvedores os editem independentemente.


Além da compilação e empacotamento simples (no diagrama em verde ), esses scripts contêm muito código para integração com o ecossistema corporativo (no diagrama em vermelho ).


Portanto, decidiu-se perceber a montagem como uma "caixa preta", na qual um ambiente de montagem "inteligente" pode resolver todos os problemas, exceto a compilação e a própria embalagem.


No início do trabalho, não estava claro como obter esse sistema. Tomar decisões de arquitetura para tarefas do DevOps requer experiência e conhecimento. Como obtê-los? As opções possíveis estão abaixo:


  • Pesquise informações na Internet.
  • Experiência e conhecimento próprios da equipe de DevOps. Para fazer isso, é bom fazer dessa equipe de programadores uma experiência versátil.
  • Experiência e conhecimento adquiridos fora da equipe do DevOps. Muitos desenvolvedores da empresa têm boas idéias - você precisa ouvi-las. A comunicação é útil.
  • Nós inventamos e experimentamos!

Preciso de automação?


Para responder a essa pergunta, você precisa entender em que estágio da evolução nossas abordagens de montagem são. Em geral, uma tarefa passa pelos seguintes níveis.


  1. Nível inconsciente



    Precisamos liberar uma montagem por semana, nosso pessoal está indo bem. Isso é natural, por que falar sobre isso?

  2. O nível de "artesão", eventualmente se transformando no nível de "trapaceiro"



    É necessário produzir duas montagens por dia de forma estável e sem erros. Temos Vasya, ele é legal, e ninguém além dele passa esse tempo.

  3. Nível de Fabricação



    As coisas foram longe. Você precisa de 20 assembléias por dia, Vasya não aguenta e agora uma equipe de dez pessoas já está sentada. Eles têm um chefe, planos, férias, licença médica, motivação, formação de equipes, treinamentos, tradições e regras. Esta é uma especialização, seu trabalho deve ser estudado.


    Nesse nível, a tarefa é separada do executor concreto e, assim, se transforma em um processo.


    O resultado será uma descrição clara, elaborada, executada e corrigida centenas de vezes do processo com texto.

  4. O nível de "produção automatizada"



    Os requisitos modernos para montagens estão crescendo: tudo deve ser rápido, confiável, 800 montagens devem ser fornecidas por dia. Isso é crítico, porque sem esses volumes a empresa perderá vantagens competitivas.


    A automação cara está ocorrendo e alguns DevOps qualificados podem manter o processo em execução. Escalas adicionais não são mais um problema.


Nem todas as tarefas devem atingir o último estágio de automação.


Muitas vezes, um artesão com uma linha de comando resolve problemas de maneira fácil e eficaz.


A automação “congela” o processo, reduz o custo da operação e aumenta o custo da mudança.


Você pode ir imediatamente à montagem do carro, mas o sistema será inconveniente, não acompanhará os requisitos da empresa e, como resultado, ficará obsoleto.


O que são as montagens e por que o problema não é resolvido pelos sistemas de montagem prontos



Usamos a seguinte classificação para determinar os níveis de agregação de montagem.

  • L1 Uma pequena parte independente de um aplicativo grande. Pode ser um componente, microsserviço ou uma biblioteca auxiliar. A montagem L1 é uma solução para problemas técnicos lineares: compilação, empacotamento, trabalho com dependências. Maven, gradle, npm, grunt e outros sistemas de compilação fazem um ótimo trabalho nisso. Existem centenas deles.

    A montagem L1 deve ser feita usando ferramentas de terceiros prontas.

  • L2 +. Entidades de integração. As entidades L1 são combinadas em formações maiores, por exemplo, em aplicativos de microsserviço de pleno direito. Vários desses aplicativos podem ser agrupados como uma solução única. Usamos o sinal “+”, pois, dependendo do nível de agregação da montagem, um nível de L3 ou mesmo L4 pode ser atribuído.


    Um exemplo desses assemblies no mundo de terceiros é a preparação de distribuições Linux. Meta-pacotes lá.


    Além de tarefas técnicas bastante complexas (como esta: ru.wikipedia.org/wiki/Dependency_hell ). As montagens L2 + geralmente são o produto final e, portanto, têm muitos requisitos de processo: um sistema de direitos, fixação de pessoas responsáveis, ausência de erros legais, fornecimento de várias documentações.


    No L2 +, os requisitos do processo são priorizados pela automação.


    Se a solução automática não funcionar, pois é conveniente para as pessoas interessadas, ela não será implementada.


    As montagens L2 + provavelmente serão executadas por uma ferramenta proprietária adaptada especificamente aos processos da empresa. Você acha que os gerenciadores de pacotes do Linux propõem isso?



Nossas melhores práticas


A infraestrutura


Disponibilidade permanente de ferro


Toda a infraestrutura de montagem está localizada em servidores fechados dentro da rede corporativa. Em alguns casos, serviços comerciais em nuvem são possíveis.


Autonomia


Em todos os processos de IC, a Internet não está disponível. Todos os recursos necessários são espelhados e armazenados em cache internamente. Parcialmente até github.com (obrigado, npm!) A maioria desses problemas é resolvida pelo Artifactory.


Portanto, somos calmos ao excluir artefatos da central central ou fechar repositórios populares. Há um exemplo: community.oracle.com/community/java/javanet-forge-sunset .


O espelhamento reduz significativamente o tempo de montagem, libera o canal corporativo da Internet. Menos recursos críticos de rede aumentam a estabilidade da construção.


Três repositórios para cada tipo de artefato


  1. Dev é um repositório onde qualquer pessoa pode publicar artefatos de qualquer origem. Aqui você pode experimentar abordagens fundamentalmente novas sem adaptá-las aos padrões corporativos desde o primeiro dia.
  2. A preparação é um repositório preenchido apenas com um pipeline de montagem.
  3. Liberação - montagens únicas, prontas para entrega externa. É preenchido com uma operação de transferência especial com confirmação manual.

Regra de 30 dias


Nos repositórios Dev e Staging, excluímos tudo com mais de 30 dias. Isso ajuda a garantir que todos tenham oportunidades iguais de publicação gastando uma quantidade finita de espaço em disco do servidor.


A liberação é armazenada para sempre, o arquivamento é feito, se necessário.


Ambiente de montagem limpo


Geralmente, após as montagens, os arquivos auxiliares permanecem no sistema, o que pode afetar outros processos de montagem. Exemplos típicos:


  • o problema mais comum é um cache danificado por um assembly incorreto (como lidar com caches, descritos abaixo);
  • alguns utilitários, como o npm, deixam os arquivos de serviço no diretório $ HOME que afetam todas as ativações subsequentes desses utilitários;
  • um assembly específico pode gastar todo o espaço em disco em alguma partição / tmp, o que levará a uma indisponibilidade geral do ambiente.

Portanto, é melhor abandonar o ambiente unificado em favor dos contêineres de docker. Os contêineres devem conter apenas o software necessário para um conjunto específico com versões fixas.


O DevOps mantém uma coleção de imagens da janela de encaixe de montagem, que é constantemente atualizada. No início, havia cerca de seis, depois tinha menos de 30 anos, e então configuramos a geração automática de imagens a partir da lista de softwares. Agora, basta especificar requisitos como require ('maven 3.3.9', 'python') - e o ambiente estará pronto.


Auto diagnóstico


Não é apenas necessário organizar o suporte ao usuário para solicitações, devemos analisar o comportamento de nosso próprio sistema. Coletamos registros constantemente, procuramos neles palavras-chave que mostram problemas.


Em um sistema "ativo", basta escrever de 20 a 30 expressões regulares para que, para cada montagem, você possa dizer o motivo de sua queda no nível:


  • Falha no servidor Git
  • espaço em disco acabou por aí;
  • erro de construção devido à falha do desenvolvedor;
  • Erro conhecido no Docker.

Se algo caiu, mas nenhum problema conhecido foi detectado, esta é uma ocasião para reabastecer a coleção de máscaras.


Em seguida, vamos ao usuário e dizemos que ele tem uma compilação e isso pode ser corrigido dessa maneira.


Você ficará surpreso com quantos problemas os usuários não relatam no suporte. É melhor repará-los com antecedência e em um momento conveniente. Freqüentemente, um pequeno erro de publicação é ignorado por duas semanas e, na sexta-feira à noite, ocorre que isso bloqueia a saída externa.


Escolhemos cuidadosamente de quais sistemas a montagem depende


Idealmente, em geral, para garantir total autonomia da montagem, mas na maioria das vezes isso é impossível. Para montagens baseadas em java, é necessário pelo menos Artifactory para espelhamento - veja acima para autonomia. Cada sistema integrado aumenta o risco de falha. É desejável que todos os sistemas funcionem no modo HA decente.


Interface da linha de montagem


Interface única para chamar o assembly


Fazemos qualquer tipo de montagem com um sistema. As montagens de todos os níveis (L1, L2 +) são descritas pelo código do programa e são chamadas por meio de um trabalho Jenkins.


No entanto, essa abordagem não é ideal. É melhor usar os mecanismos de geração automática de tarefas Jenkins: por exemplo, 1 tarefa = 1 repositório git ou 1 tarefa = 1 ramificação git. Isso alcançará o seguinte:


  • logs de assembléias heterogêneas não são confundidos em uma história na página de trabalho da Jenkins;
  • de fato, você obtém trabalhos alocados confortáveis ​​para uma equipe ou para um desenvolvedor; a sensação de conforto pode ser aprimorada ajustando os gráficos dos resultados de junit, cobertura, sonar.

Liberdade de escolha da tecnologia


Iniciando a construção é uma chamada para o script bash “./build.sh”. E então - quaisquer sistemas de montagem, linguagens de programação e tudo o mais necessário para concluir uma tarefa de negócios. Isso fornece uma abordagem para montagem como uma caixa preta.


Postagem inteligente


A linha de montagem intercepta publicações da caixa preta e as coloca no armazenamento corporativo. Para isso, problemas chatos, como gerar nomes de imagens do docker e escolher o repositório certo para publicação, são resolvidos automaticamente.


Os repositórios de preparação e liberação sempre têm ordem. É necessário dar suporte às especificidades de publicações de diferentes tipos: maven, npm, file, docker.


Descritor de montagem


Build.sh descreve como compilar código, mas isso não é suficiente para um contêiner de assembly.


Você também deve saber:


  1. qual ambiente de montagem usar;
  2. variáveis ​​de ambiente disponíveis no build.sh;
  3. quais publicações serão realizadas;
  4. outras opções específicas.

Optamos por uma maneira conveniente de descrever essas informações na forma de um arquivo yaml que lembra remotamente o arquivo .gitlab-ci.yaml.


Parametrização de montagem


O usuário pode especificar parâmetros arbitrários sem executar o comando git commit logo no início da montagem.


Implementamos isso definindo variáveis ​​de ambiente diretamente da interface do trabalho Jenkins.


Por exemplo, transferimos a versão da biblioteca dependente para esse parâmetro de assembly e, em alguns casos, redefinimos essa versão para outra experimental. Sem esse mecanismo, o usuário teria que executar o comando "git commit" a cada vez.


Portabilidade do sistema


Você deve poder reproduzir o processo de montagem não apenas no servidor de IC principal, mas também no computador do desenvolvedor. Isso ajuda na depuração de scripts de compilação complexos. Além disso, em vez de Jenkins, às vezes será mais conveniente usar o Gitlab CI. Portanto, o sistema de construção deve ser um aplicativo java independente. Nós o implementamos como um plugin gradle.


Um artefato pode ser publicado com nomes diferentes.


Existem dois requisitos opostos para publicação que podem surgir simultaneamente.


Por um lado, para armazenamento de longo prazo e gerenciamento de liberação, é necessário garantir a exclusividade dos nomes dos artefatos publicados. Isso protegerá pelo menos os artefatos de serem substituídos.


Por outro lado, às vezes é conveniente ter um artefato real com um nome fixo como o mais recente. Por exemplo, o desenvolvedor não precisa saber a versão exata da dependência a cada vez, basta trabalhar com a mais recente.


O artefato nesse caso é publicado com dois ou mais nomes, pois é adequado a todos.


Por exemplo:


  1. um nome exclusivo com carimbo de data / hora ou UUID - para quem precisa de precisão;
  2. o nome "mais recente" - para seus desenvolvedores, que sempre escolhem o código mais recente;
  3. o nome "<versão principal> .x-latest" é para uma equipe vizinha pronta para pegar as versões mais recentes, mas apenas dentro da estrutura de uma determinada versão principal.

Maven faz algo semelhante em sua abordagem ao INSTANTÂNEO.


Menos restrições de segurança


Todos podem começar a montagem. Isso não fará mal a ninguém, uma vez que a montagem cria apenas artefatos.


Conformidade legal


Controle de interações externas do processo de montagem


A montagem não pode usar nada proibido no processo de seu trabalho.


Para isso, é implementado o registro do tráfego de rede e o acesso aos caches de arquivos. Nós obtemos o log da atividade de rede do assembly na forma de uma lista de URLs com sha256 hashes dos dados recebidos. Além disso, cada URL é validado:


  1. lista de permissões estática;
  2. banco de dados dinâmico de artefatos permitidos (por exemplo, para dependências maven, rpm-, npm). Cada vício é considerado individualmente. Uma permissão automática ou uma proibição de uso pode funcionar, e uma longa discussão com advogados também pode começar.

Conteúdo transparente de artefatos publicados


Às vezes, a tarefa é fornecer uma lista de software de terceiros dentro de qualquer montagem. Para fazer isso, eles criaram um analisador de composição simples que analisa todos os arquivos e arquivos da montagem, reconhece os terceiros por hashes e faz um relatório.


O código-fonte emitido não pode ser removido do GIT


Às vezes, você pode precisar encontrar o código-fonte observando o artefato binário compilado há dois anos. Para fazer isso, é necessário alocar tags no Git automaticamente com saída externa, além de proibir sua remoção.


Logística e Contabilidade


Todos os assemblies são armazenados no banco de dados.


Usamos o repositório de arquivos no Artifactory para esses fins. Ele contém todas as informações de suporte: quem o lançou, quais foram os resultados das verificações, quais artefatos foram publicados, qual git hash foi usado etc.


Sabemos como reproduzir a montagem com a maior precisão possível


De acordo com os resultados da montagem, armazenamos as seguintes informações:


  • o estado exato do código que foi coletado;
  • com quais parâmetros o lançamento foi feito;
  • quais comandos foram chamados;
  • que acesso a recursos externos ocorreu;
  • ambiente de montagem usado.

Se necessário, podemos responder com precisão à questão de como foi montada.


Comunicação bidirecional da montagem com o ticket JIRA


Certifique-se de poder resolver os seguintes problemas:


  1. para montagem, crie uma lista de tickets do JIRA incluídos nele;
  2. escreva no ticket do JIRA em que montagens ele está incluído.

É fornecida uma comunicação bidirecional estreita entre o assembly e o commit do git. E, a partir do texto dos comentários, você já pode descobrir todos os links para o JIRA.


Velocidade


Caches do sistema de montagem


A ausência de um cache automatizado pode aumentar o tempo de compilação em uma hora.


O cache viola o isolamento do ambiente de montagem e a limpeza da montagem. Esse problema pode ser resolvido determinando sua origem para cada artefato em cache. Cada arquivo de cache está associado a um link https do qual foi baixado uma vez. Além disso, processamos a leitura de um cache como endereço de rede.


Cache de Recursos de Rede


O crescimento geográfico da empresa leva à necessidade de transferir arquivos de 300 MB entre continentes. Muito tempo é gasto, especialmente se você tiver que fazer isso com frequência.


Repositórios Git, imagens de encaixe de ambientes de montagem, armazenamento de arquivos - tudo precisa ser cuidadosamente armazenado em cache. Bem, é claro, periodicamente limpo.


Montagem - o mais rápido possível, tudo o resto -


A primeira etapa: fazemos a montagem e imediatamente, sem gestos desnecessários, damos o resultado.


A segunda etapa: validação, análise, contabilidade e outras burocracias. Isso já pode ser feito em um trabalho separado da Jenkins e sem prazos estritos.


Qual é o resultado


  1. O principal é que a montagem ficou clara para os desenvolvedores , eles mesmos podem desenvolver e otimizar.
  2. A fundação foi criada para criar processos de negócios que dependem da montagem: instalação, gerenciamento de problemas, testes, gerenciamento de versões, etc.
  3. A equipe do DevOps não escreve mais scripts de montagem: os desenvolvedores fazem isso.
  4. Requisitos corporativos complexos se transformaram em um relatório transparente com uma lista final de verificações.
  5. Qualquer pessoa pode criar qualquer repositório simplesmente chamando build.sh através de uma única interface. É o suficiente para ele simplesmente especificar as coordenadas git do código fonte. Essa pessoa pode ser gerente de equipe, engenheiro de controle de qualidade / TI etc.

E alguns números


  1. . 15 Jenkins job build.sh. 15 docker-, , . . .
  2. . . 2200 . — on-commit-.
  3. 300 git-, .
  4. 30 , (25 ) — docker.
  5. , :
    1. glide, golang, promu;
    2. maven, gradle;
    3. python & pip;
    4. ruby;
    5. nodejs & npm;
    6. docker;
    7. rpm build tools & gcc;
    8. Android ADT;
    9. ;
    10. legacy-;
    11. .

Source: https://habr.com/ru/post/pt421423/


All Articles