Integração Contínua na Coinbase: Como otimizamos o CircleCI em velocidade e reduzimos o tempo de construção em 75%

Sam Rubin em The Coinbase Blog Seguir Jul 10 · 7 min

Ajustar um servidor de integração contínua apresenta um desafio interessante – os engenheiros de infraestrutura precisam equilibrar a velocidade de construção, o custo e os tempos de fila em um sistema que muitos desenvolvedores não têm amplo gerenciamento de experiência em escala. Os resultados, quando feitos corretamente, podem ser um grande benefício para sua empresa, conforme ilustrado pela recente jornada que fizemos para melhorar nossa configuração de IC.

Integração Contínua na Coinbase

Como a Coinbase cresceu, manter nossos desenvolvedores satisfeitos com nossas ferramentas internas tem sido uma alta prioridade. Durante a maior parte da história da Coinbase, usamos o servidor CircleCI , que tem sido uma ferramenta de baixo desempenho e baixa manutenção. Como a empresa e nossa base de código cresceram, no entanto, as demandas em nosso servidor de CI também aumentaram. Antes das otimizações descritas aqui, as compilações para o aplicativo de monotrilho que executa o Coinbase.com aumentaram significativamente em comprimento (duplicando ou triplicando os tempos de construção médios anteriores) e os desenvolvedores geralmente reclamavam de construções demoradas ou não concluídas.

Nossas instalações de CI não estavam mais atendendo às nossas expectativas, e foi com as edições anteriores em mente que decidimos iniciar uma campanha para recuperar nossa configuração.

Vale a pena compartilhar aqui que a Coinbase usa especificamente a versão de servidor no local do CircleCI em vez de sua oferta na nuvem – hospedar nossa própria infraestrutura é importante para nós por motivos de segurança, e esses conceitos se aplicam especificamente a clusters de CI autogerenciados.

Os quatro sinais de ouro

Nós descobrimos que a primeira chave para otimizar qualquer sistema de CI é a observabilidade, pois sem uma maneira de medir os efeitos de seus ajustes e mudanças é impossível saber realmente se você realmente fez ou não uma melhoria. No nosso caso, o CircleCI hospedado pelo servidor usa um cluster nomad para compilações e, no momento, não forneceu nenhum método de monitoramento do cluster ou dos nós internos. Tivemos que construir sistemas próprios, e decidimos que uma boa abordagem seria usar a estrutura dos quatro sinais dourados , latência, tráfego, erros e saturação .

Latência

Latência é o tempo total necessário para atender a uma solicitação. Em um sistema de CI, isso pode ser considerado como o tempo total que uma compilação demora para ser executada do início ao fim. A latência é melhor medida em uma base por repo ou mesmo por compilação, pois a duração da compilação pode variar enormemente com base no projeto.

Para medir isso, criamos um pequeno aplicativo que consultou a API do CircleCI regularmente para comprimentos de compilação e, em seguida, enviamos essas informações ao Datadog para permitir a criação de gráficos e visualizações dos tempos médios de compilação. Isso nos permitiu mapear os resultados de nossos experimentos de melhoria de maneira empírica e automática, em vez de confiar em resultados informados ou curados manualmente, como fizemos anteriormente.

Resultados da API do CircleCI

Tráfego

Tráfego é a quantidade de demanda que está sendo colocada em seu sistema a qualquer momento. Em um sistema de CI, isso pode ser representado pelo número total de construções em execução simultaneamente.

Conseguimos medir isso usando o mesmo sistema que criamos para medir as métricas de latência. Isso foi útil ao determinar os limites superior e inferior para o uso de nossos recursos de construção, pois nos permitiu ver exatamente quantos trabalhos estavam sendo executados a qualquer momento.

Erros

Erros são a quantidade total de solicitações ou chamadas que falharam. Em um sistema de IC isso pode ser representado pelo número total de construções que falham devido a razões de infra-estrutura. É importante fazer aqui uma distinção entre compilações que falham corretamente, devido a testes, linting, erros de código, etc., em vez de construções que falham devido a problemas de plataforma.

Um problema que encontramos foi que, ocasionalmente, a AWS nos dava casos "ruins" ao girar novos construtores que seriam executados muito mais lentamente do que uma instância "boa" normal. Adicionando detecção de erro em nossos scripts de inicialização do construtor nos permitiu encerrar estes e criar novos nós antes que eles pudessem retardar nossas compilações em execução.

Saturação

A saturação é como o serviço está “cheio” ou o quanto dos recursos do sistema estão sendo usados. Em um sistema de CI, isso é bastante simples – quanto de E / S, CPU e memória são os construtores sob carga usando.

Para medir a saturação da nossa configuração, conseguimos acessar as métricas do cluster instalando um Agente do Datadog em cada um dos nossos construtores, o que nos permitiu obter uma visualização das estatísticas do sistema em todo o cluster.

Estatísticas do trabalho do Datadog

Identificando a causa raiz

Depois que a configuração de monitoramento estiver em vigor, será mais fácil investigar a causa raiz dos atrasos na criação. Uma das dificuldades em diagnosticar problemas de IC sem monitoramento em todo o cluster é que pode ser difícil identificar quais construtores estão experimentando carga a qualquer momento ou como essa carga afeta suas compilações. O monitoramento de latência pode permitir que você descubra quais builds estão demorando mais tempo, e o monitoramento de saturação pode permitir que você identifique os nós que executam esses builds para uma investigação mais detalhada.

Para nós, a nova medição de latência que adicionamos nos permitiu confirmar rapidamente o que havíamos adivinhado: nem todas as construções eram iguais. Alguns builds funcionavam nas velocidades rápidas que já tínhamos experimentado, mas outras builds se arrastavam por muito mais tempo do que esperávamos.

Em nosso caso, essa descoberta foi o grande avanço – uma vez que pudéssemos identificar rapidamente construções com maior latência e encontrar os nós saturados, o problema rapidamente se revelou: contenção de recursos entre as construções iniciais! Devido ao grande número de testes para nossas construções maiores, usamos o recurso de paralelização do CircleCI para dividir nossos testes e executá-los em toda a frota em contêineres de estivadores separados. Cada contêiner de teste também requer outro conjunto de contêineres de suporte (Redis, MongoDB, etc.) para replicar o ambiente de produção. A inicialização de todos os contêineres necessários para cada construção é uma operação que consome muitos recursos, exigindo quantidades significativas de E / S e CPU. Já que a Nomad usa o empacotamento de escaninhos para distribuições de trabalho, nossos construtores às vezes lançam até 5 conjuntos diferentes desses contêineres de uma só vez, causando grandes lentidões antes que os testes possam começar a ser executados.

Construir Experimentação

Configurar um ambiente de desenvolvimento é a chave para depurar problemas de CI, uma vez que ele permite que você leve seu sistema aos limites, garantindo que nenhum dos seus testes afetem a produtividade na produção. A Coinbase mantém um cluster de desenvolvimento para o CircleCI que usamos para testar novas versões antes de colocá-las em produção, mas para investigar nossas opções transformamos o cluster em uma réplica menor de nossa instância de produção, permitindo que carregássemos efetivamente os construtores CircleCI de teste . Manter seu cluster de desenvolvimento o mais próximo possível da produção pode ajudar a garantir que qualquer solução encontrada reflita o que realmente pode ajudar em um ambiente real.

Uma vez que identificamos porque nossos builds estavam encontrando problemas e criamos um ambiente para executar experimentos, poderíamos começar a desenvolver uma solução. Nós repetidamente executamos as mesmas compilações grandes que estavam causando os problemas em nosso cluster de produção em diferentes tamanhos e tipos de instâncias EC2, a fim de descobrir quais eram as opções mais econômicas e de menor custo a serem usadas.

Comparação do tipo de instância do EC2

Embora anteriormente estivéssemos usando números menores de grandes instâncias para executar nossas compilações, a configuração ideal para nosso cluster era na verdade um número muito grande de instâncias menores (m5.larges no nosso caso) – pequeno o suficiente para que o CircleCI só enviasse um Um container de construção paralelizado para cada instância, evitando os problemas de atropelamento de builds que foram a causa dos slow downs. Um bom efeito colateral de identificar os tipos de instância corretos foi que isso realmente nos permitiu reduzir significativamente o custo de nossos servidores, já que conseguimos dimensionar nosso cluster mais de perto para seu uso.

Problema? Resolvido!

Aplicar as alterações em um ambiente de produção é a etapa final. Determinar se os efeitos da sintonia funcionaram pode ser feito da mesma forma que os problemas foram identificados – com os quatro sinais dourados.

Depois de identificarmos o que funcionava melhor em nosso cluster de desenvolvimento, implementamos rapidamente o novo dimensionamento de construtor na produção. Os resultados? Um decréscimo de 75% no tempo de construção para nossas maiores construções, economias de custo significativas devido ao dimensionamento correto de nosso cluster e, o mais importante de tudo: desenvolvedores felizes!

Builds, antes e depois

Este site pode conter links para sites de terceiros ou outro conteúdo apenas para fins informativos (“Sites de Terceiros”). Os Sites de Terceiros não estão sob o controle da Coinbase, Inc., e suas afiliadas (“Coinbase”), e a Coinbase não é responsável pelo conteúdo de qualquer Site de Terceiros, incluindo, sem limitação, qualquer link contido em um Terceiro Site. Party Site, ou quaisquer alterações ou atualizações em um Site de Terceiros. A Coinbase não é responsável por webcasting ou qualquer outra forma de transmissão recebida de qualquer Site de Terceiros. Coinbase está fornecendo estas informações somente como uma conveniência e não indica nenhum enderemento ou recomendação por parte da Coinbase do site ou de qualquer associação com seus operadores.

Salvo indicação em contrário, todas as imagens fornecidas neste documento são da Coinbase.