Práticas de entrega contínua com Docker (revisão e vídeo)

Iniciaremos nosso blog com publicações baseadas nas últimas palestras do nosso diretor técnico distol (Dmitry Stoliarov). Todos eles aconteceram em 2016 em diversos eventos profissionais e foram dedicados ao tema DevOps e Docker. Um vídeo da reunião do Docker Moscou no escritório do Badoo, já vimos Publicados On-line. Os novos serão acompanhados de artigos que transmitam a essência dos relatórios. Então…

31 de maio na conferência RootConf 2016, realizado no âmbito do festival “Russian Internet Technologies” (RIT++ 2016), a seção “Continuous Deployment and Deployment” abriu com o relatório “Best Practices of Continuous Delivery with Docker”. Resumiu e sistematizou as melhores práticas para a construção de um processo de Entrega Contínua (CD) usando Docker e outros produtos Open Source. Trabalhamos com essas soluções em produção, o que nos permite contar com experiência prática.

Práticas de entrega contínua com Docker (revisão e vídeo)

Se você tiver a oportunidade de passar uma hora vídeo da reportagem, recomendamos assisti-lo na íntegra. Caso contrário, abaixo está o resumo principal em forma de texto.

Entrega Contínua com Docker

Em Entrega Contínua entendemos a cadeia de eventos como resultado da qual o código do aplicativo do repositório Git chega primeiro à produção e depois termina no arquivo. Ela fica assim: Git → Construir → Teste → Liberar → Operar.

Práticas de entrega contínua com Docker (revisão e vídeo)
A maior parte do relatório é dedicada à fase de construção (montagem da aplicação), e os tópicos de lançamento e operação são abordados brevemente. Falaremos sobre problemas e padrões que permitem resolvê-los, e as implementações específicas desses padrões podem ser diferentes.

Por que o Docker é necessário aqui? Não é à toa que decidimos falar sobre práticas de Entrega Contínua no contexto desta ferramenta Open Source. Embora todo o relatório seja dedicado ao seu uso, muitos motivos são revelados quando se considera o padrão principal de implementação do código do aplicativo.

Padrão de implementação principal

Então, quando lançamos novas versões do aplicativo, certamente nos deparamos com problema de inatividade, gerado durante a comutação do servidor de produção. O tráfego da versão antiga do aplicativo para a nova não pode mudar instantaneamente: primeiro devemos ter certeza de que a nova versão não apenas foi baixada com sucesso, mas também “aquecida” (ou seja, completamente pronta para atender solicitações).

Práticas de entrega contínua com Docker (revisão e vídeo)
Assim, por algum tempo ambas as versões do aplicativo (antiga e nova) funcionarão simultaneamente. O que leva automaticamente a conflito de recursos compartilhados: rede, sistema de arquivos, IPC, etc. Com o Docker, esse problema é facilmente resolvido executando diferentes versões da aplicação em contêineres separados, para os quais o isolamento de recursos é garantido dentro do mesmo host (servidor/máquina virtual). Claro, você pode fazer alguns truques sem nenhum isolamento, mas se houver uma ferramenta pronta e conveniente, então há o motivo oposto - não negligenciá-la.

A conteinerização oferece muitos outros benefícios quando implantada. Qualquer aplicação depende versão específica (ou intervalo de versões) intérprete, disponibilidade de módulos/extensões, etc., bem como suas versões. E isso se aplica não apenas ao ambiente executável imediato, mas também a todo o ambiente, incluindo software de sistema e sua versão (até a distribuição Linux utilizada). Devido ao fato de os contêineres conterem não apenas o código do aplicativo, mas também o sistema pré-instalado e o software do aplicativo das versões necessárias, você pode esquecer os problemas com dependências.

Resumir padrão de implementação principal novas versões levando em consideração os seguintes fatores:

  1. A princípio, a versão antiga da aplicação roda no primeiro contêiner.
  2. A nova versão é então lançada e “aquecida” em um segundo contêiner. Vale ressaltar que esta nova versão em si pode conter não apenas o código atualizado da aplicação, mas também qualquer uma de suas dependências, bem como componentes do sistema (por exemplo, uma nova versão do OpenSSL ou toda a distribuição).
  3. Quando a nova versão está totalmente pronta para atender solicitações, o tráfego muda do primeiro contêiner para o segundo.
  4. A versão antiga agora pode ser interrompida.

Essa abordagem de implantação de diferentes versões do aplicativo em contêineres separados oferece outra conveniência - reversão rápida para a versão antiga (afinal, basta transferir o tráfego para o contêiner desejado).

Práticas de entrega contínua com Docker (revisão e vídeo)
A primeira recomendação final soa como algo que nem mesmo o Capitão conseguiu criticar: “[ao organizar a Entrega Contínua com Docker] Use o Docker [e entenda o que isso dá]" Lembre-se de que esta não é uma solução mágica que resolverá todos os problemas, mas uma ferramenta que fornece uma base maravilhosa.

Reprodutibilidade

Por “reprodutibilidade” queremos dizer um conjunto generalizado de problemas encontrados durante a operação de aplicativos. Estamos falando sobre esses casos:

  • Os scripts verificados pelo departamento de qualidade para preparação devem ser reproduzidos com precisão na produção.
  • Os aplicativos são publicados em servidores que podem receber pacotes de diferentes espelhos de repositórios (com o tempo eles são atualizados, e com eles as versões dos aplicativos instalados).
  • “Tudo funciona para mim localmente!” (...e os desenvolvedores não têm permissão para produção.)
  • Você precisa verificar algo na versão antiga (arquivada).
  • ...

A sua essência geral resume-se ao facto de ser necessária a total conformidade dos ambientes utilizados (bem como a ausência do factor humano). Como podemos garantir a reprodutibilidade? Faça imagens Docker com base no código do Git, e depois utilizá-los para qualquer tarefa: em locais de teste, em produção, em máquinas locais de programadores... Ao mesmo tempo, é importante minimizar as ações que são executadas depois montagem da imagem: quanto mais simples, menor a probabilidade de erros.

Infraestrutura é código

Se os requisitos de infraestrutura (disponibilidade do software de servidor, sua versão, etc.) não forem formalizados e “programados”, a implementação de qualquer atualização de aplicativo poderá resultar em consequências desastrosas. Por exemplo, no teste você já mudou para o PHP 7.0 e reescreveu o código de acordo - então sua aparição em produção com algum PHP antigo (5.5) certamente surpreenderá alguém. Você pode não esquecer de uma grande mudança na versão do intérprete, mas “o diabo está nos detalhes”: a surpresa pode estar em uma pequena atualização de alguma dependência.

Uma abordagem para resolver este problema é conhecida como IaC (Infraestrutura como Código, “infraestrutura como código”) e envolve o armazenamento de requisitos de infraestrutura junto com o código do aplicativo. Usando-o, desenvolvedores e especialistas em DevOps podem trabalhar com o mesmo repositório de aplicativos Git, mas em partes diferentes dele. A partir desse código, é criada uma imagem Docker no Git, na qual a aplicação é implantada levando em consideração todas as especificidades da infraestrutura. Simplificando, os scripts (regras) para montagem de imagens devem estar no mesmo repositório do código-fonte e mesclados.

Práticas de entrega contínua com Docker (revisão e vídeo)

No caso de uma arquitetura de aplicação multicamadas - por exemplo, existe o nginx, que fica na frente de uma aplicação já em execução dentro de um contêiner Docker - as imagens Docker devem ser criadas a partir do código no Git para cada camada. Então a primeira imagem conterá um aplicativo com um intérprete e outras dependências “próximas”, e a segunda imagem conterá o nginx upstream.

Imagens Docker, comunicação com Git

Dividimos todas as imagens Docker coletadas do Git em duas categorias: temporárias e de lançamento. Imagens temporárias marcados pelo nome do branch no Git, podem ser substituídos pelo próximo commit e são implementados apenas para visualização (não para produção). Esta é a principal diferença em relação aos lançamentos: você nunca sabe qual commit específico está neles.

Faz sentido coletar em imagens temporárias: branch master (você pode implementá-lo automaticamente em um site separado para ver constantemente a versão atual do master), branchs com lançamentos, branchs de inovações específicas.

Práticas de entrega contínua com Docker (revisão e vídeo)
Depois que a visualização das imagens temporárias chega à necessidade de tradução para produção, os desenvolvedores colocam uma determinada tag. Coletado automaticamente por tag imagem de lançamento (sua tag corresponde à tag do Git) e é implementada no teste. Se for verificado com sucesso pelo departamento de qualidade, vai para produção.

dapp

Tudo o que é descrito (lançamento, montagem da imagem, manutenção posterior) pode ser implementado de forma independente usando scripts Bash e outras ferramentas “improvisadas”. Mas se você fizer isso, em algum momento a implementação levará a uma grande complexidade e pouca controlabilidade. Compreendendo isso, criamos nosso próprio utilitário de fluxo de trabalho especializado para construir CI/CD - dapp.

Seu código fonte é escrito em Ruby, open source e publicado em GitHub. Infelizmente, a documentação é atualmente o ponto mais fraco da ferramenta, mas estamos trabalhando nisso. E escreveremos e falaremos sobre o dapp mais de uma vez, porque... Sinceramente, mal podemos esperar para compartilhar suas capacidades com toda a comunidade interessada, mas enquanto isso, envie seus problemas e pull requests e/ou acompanhe o desenvolvimento do projeto no GitHub.

Atualizado em 13 de agosto de 2019: atualmente um projeto dapp renomeado para bem, seu código foi completamente reescrito em Go e sua documentação foi significativamente melhorada.

Kubernetes

Outra ferramenta Open Source pronta e que já recebeu reconhecimento significativo no ambiente profissional é Kubernetes, um cluster de gerenciamento Docker. O tema de sua utilização na operação de projetos construídos em Docker foge ao escopo do relatório, portanto a apresentação se limita a uma visão geral de alguns recursos interessantes.

Para implementação, o Kubernetes oferece:

  • sonda de prontidão — verificando a prontidão de uma nova versão do aplicativo (para transferir tráfego para ela);
  • atualização contínua - atualização sequencial de imagens em um cluster de contêineres (desligamento, atualização, preparação para lançamento, comutação de tráfego);
  • atualização síncrona - atualização de uma imagem em um cluster com uma abordagem diferente: primeiro em metade dos contêineres, depois no restante;
  • lançamentos canário - lançamento de uma nova imagem em um número limitado (pequeno) de contêineres para monitorar anomalias.

Como a Entrega Contínua não é apenas o lançamento de uma nova versão, o Kubernetes possui uma série de recursos para manutenção posterior da infraestrutura: monitoramento e registro integrados para todos os contêineres, escalonamento automático, etc. implementação em seus processos.

Recomendações finais

  1. Utilize o Docker.
  2. Crie imagens Docker de aplicativos para todas as suas necessidades.
  3. Siga o princípio “Infraestrutura é código”.
  4. Vincule o Git ao Docker.
  5. Regular a ordem de lançamento.
  6. Use uma plataforma pronta (Kubernetes ou outra).

Vídeos e slides

Vídeo da apresentação (cerca de uma hora) publicado no YouTube (o relatório em si começa a partir do 5º minuto - siga o link para jogar a partir deste momento).

Apresentação do relatório:

PS

Outras reportagens sobre o tema em nosso blog:

Fonte: habr.com

Adicionar um comentário