
Um dia, decidi escrever um artigo sobre a entrega de pacotes docker e deb na forma de contêineres, mas quando comecei, por algum motivo, sofri nos dias distantes dos primeiros computadores pessoais e até calculadoras. Em geral, em vez de comparações secas de estivador e deb, esses são os pensamentos sobre evolução que apresento ao seu tribunal.
Qualquer produto, seja ele qual for, precisa acessar os servidores do produto, deve ser configurado e iniciado. Este artigo será sobre isso.
Vou refletir no contexto histórico, "o que vejo - que canto", o que vi quando comecei a escrever código e o que estou observando agora, o que nós mesmos estamos usando no momento e por quê. O artigo não pretende ser um estudo completo, alguns pontos foram perdidos, esta é minha visão pessoal do que era e é agora.
Então, nos bons velhos tempos ... o método de entrega mais antigo que encontrei foi com fitas cassete. Eu tinha um computador BK-0010.01 ...
A Era das Calculadoras
Não, houve um ponto ainda anterior, havia também uma calculadora
MK-61 e
MK-52 .

Portanto, quando eu tinha o
MK-61 , a maneira de transferir o programa era usar um pedaço de papel comum em uma caixa na qual o programa foi gravado e, se necessário, foi gravado manualmente na calculadora. Se você quiser jogar (sim, até houve jogos nesta calculadora antediluviana), sente-se e insira o programa na calculadora. Naturalmente, quando a calculadora foi desligada, o programa entrou no esquecimento. Além dos códigos das calculadoras escritos pessoalmente em papel, os programas foram publicados nas revistas Radio and Technique of Youth, bem como em livros da época.
A próxima modificação foi a calculadora
MK-52 , que já possuía algum tipo de armazenamento de dados não volátil. Agora, o jogo ou programa não precisava ser acionado manualmente, mas, depois de fazer alguns passes mágicos com botões, ele se carregava.
O volume do maior programa da calculadora era de 105 etapas e o tamanho da memória permanente no MK-52 era de 512 etapas.
A propósito, se existem fãs dessas calculadoras que estão lendo este artigo - no processo de redação do artigo, encontrei um emulador de calculadora para Android e um programa para ele. Encaminhar para o passado!
Uma pequena digressão sobre o MK-52 (da Wikipedia)
O MK-52 voou para o espaço na sonda Soyuz TM-7. Era para ser usado para calcular a trajetória de pouso, caso o computador de bordo falhasse.
O MK-52, com a unidade de expansão de memória "Electronics-Astro", desde 1988, foi fornecido aos navios da Marinha como parte de um kit de computação de navegação.
Os primeiros computadores pessoais

Vamos voltar aos tempos do
BK-0010 . É claro que havia mais memória lá e não era mais uma opção para gerar código de um pedaço de papel (embora a princípio eu tenha feito exatamente isso, porque simplesmente não havia outro meio). Os principais meios de armazenamento e entrega de software são cassetes de áudio para gravadores.

O armazenamento em um cassete era geralmente na forma de um ou dois arquivos binários, e todo o resto estava contido. A confiabilidade era muito baixa, eu tive que manter 2-3 cópias do programa. O tempo de carregamento também não foi bom, os entusiastas experimentaram diferentes codificações de frequência para superar essas deficiências. Naquela época, eu mesmo ainda não estava envolvido no desenvolvimento profissional de software (além de programas básicos simples); portanto, infelizmente, não vou lhe contar em detalhes como tudo foi organizado por dentro. O fato de ter apenas RAM no computador determinou a simplicidade do esquema de armazenamento de dados.
O surgimento de mídias de armazenamento grandes e confiáveis
Mais tarde, os disquetes aparecem, o processo de cópia é simplificado e a confiabilidade está aumentando.
Mas a situação muda drasticamente somente quando armazenamentos locais suficientemente grandes aparecem na forma de HDD.
O tipo de entrega muda fundamentalmente: aparecem os instaladores que controlam o processo de configuração do sistema, bem como a limpeza após a exclusão, pois os programas não são apenas lidos na memória, mas já são copiados para o armazenamento local, do qual você precisa poder limpar e desnecessariamente, se necessário.
Ao mesmo tempo, a complexidade do software fornecido aumenta.
O número de arquivos na entrega aumenta de unidades para centenas e milhares, conflitos de versões de bibliotecas e outras alegrias começam quando programas diferentes usam os mesmos dados.

Naquela época, a existência do Linux ainda não estava aberta para mim, eu morava no mundo do MS DOS e, mais tarde, no Windows, e escrevi em Borland Pascal e Delphi, às vezes olhando para C ++. Para fornecer produtos naquela época, muitos usavam o InstallShield
ru.wikipedia.org/wiki/InstallShield , que resolveu com êxito todas as tarefas de implantação e configuração de software.
Era da Internet
Gradualmente, a complexidade dos sistemas de software se torna ainda mais complicada; a partir de um monólito e aplicativos de desktop, há uma transição para sistemas distribuídos, thin clients e microsserviços. Agora você precisa configurar não apenas um programa, mas o conjunto deles, e para que eles sejam amigos todos juntos.
O conceito mudou completamente, a Internet chegou, a era dos serviços em nuvem chegou. Até o momento, ele é interpretado apenas na fase inicial, na forma de sites, ninguém sonhava especialmente com serviços. mas esse foi um ponto de virada no setor, tanto no desenvolvimento quanto na entrega real de aplicativos.
Por mim, observei que, neste momento, havia uma mudança de gerações de desenvolvedores (ou era apenas no meu ambiente), e eu tinha a sensação de que todos os bons métodos de entrega antigos foram esquecidos em um momento e tudo começou desde o início: eles começaram a fazer a entrega inteira com scripts na altura do joelho e orgulhosamente chamou de "entrega contínua". De fato, começou um período de caos, quando o antigo é esquecido e não usado, mas simplesmente não há novo.
Lembro-me dos momentos em que em nossa empresa, onde trabalhava na época (não ligo), em vez de construir através da formiga (o maven ainda não era popular ou não é de todo), as pessoas apenas coletavam jar no IDE e se ele em svn. Assim, a implantação foi obter o arquivo do SVN e copiá-lo via SSH para a máquina desejada. Tão simples e desajeitado.
Ao mesmo tempo, a entrega de sites simples ao PHP foi bastante primitiva, simplesmente copiando o arquivo corrigido via FTP para a máquina de destino. Às vezes, não havia isso - o código era editado ao vivo no servidor do produto e era especialmente chique se houvesse backups em algum lugar.
Pacotes RPM e DEB

Por outro lado, com o desenvolvimento da Internet, sistemas do tipo UNIX começaram a ganhar cada vez mais popularidade, em particular, foi nessa época que eu descobri o RedHat Linux 6 para mim, por volta de 2000. Naturalmente, havia certas ferramentas para a entrega de software lá, de acordo com a Wikipedia, o RPM como o principal gerenciador de pacotes já apareceu em 1995, na versão do RedHat Linux 2.0. E a partir de então até agora, o sistema foi entregue na forma de pacotes RPM e existe e se desenvolve com êxito.
As distribuições da família Debian seguiram um caminho semelhante e implementaram a entrega na forma de pacotes deb, que também são inalterados até hoje.
Os gerenciadores de pacotes permitem fornecer os produtos de software, configurá-los durante o processo de instalação, gerenciar dependências entre pacotes diferentes, remover produtos e limpar o excesso durante a desinstalação. I.e. na maioria das vezes, isso é tudo o que é necessário, e é por isso que duraram várias décadas com pouca ou nenhuma mudança.
Nuvens adicionadas à instalação dos gerenciadores de pacotes não apenas da mídia física, mas também dos repositórios da nuvem, mas basicamente pouco mudou.
Vale a pena notar que, atualmente, existem algumas falhas no sentido de evitar o deb e alternar para tirar pacotes, mas mais sobre isso mais tarde.
Portanto, essa nova geração de desenvolvedores de nuvem, que não conhecia DEB ou RPM, também estava crescendo lentamente, ganhando experiência, os produtos se tornaram mais complicados e foram necessários métodos de entrega mais razoáveis do que FTP, scripts de bash e artesanato similar.
E aqui o Docker entra em cena, uma espécie de mistura de virtualização, alocação de recursos e métodos de entrega. Agora está na moda, juventude, mas é necessário para tudo? É uma panacéia?
De acordo com minhas observações, muitas vezes o Docker é oferecido não como uma escolha razoável, mas simplesmente porque é, por um lado, discutido na comunidade, e aqueles que o oferecem apenas o conhecem. Por outro lado, na maioria das vezes eles não falam sobre os bons e antigos sistemas de embalagem - eles são e são, estão realizando seu trabalho de maneira silenciosa e imperceptível. Em tal situação, não há outra escolha - a escolha é óbvia - Docker.
Vou tentar compartilhar minha experiência de como implementamos o Docker e o que aconteceu como resultado.
Scripts auto-escritos
Inicialmente, havia scripts bash que implantavam arquivos jar nas máquinas necessárias. Gerenciado esse processo por Jenkins. Isso funcionou com sucesso, pois o próprio arquivo jar já é um assembly que contém classes, recursos e até configuração. Se você colocar tudo ao máximo - e depois expandir com um script -, isso não é a coisa mais difícil que você precisa
Mas os scripts têm várias desvantagens:
- os scripts geralmente são escritos às pressas e, portanto, são tão primitivos que contêm apenas um dos scripts mais bem-sucedidos. Isso é facilitado pelo fato de o desenvolvedor estar interessado em uma entrega rápida, e um script normal requer uma quantidade razoável de recursos.
- Como conseqüência do parágrafo anterior, os scripts não contêm o procedimento de desinstalação
- nenhum procedimento de atualização estabelecido
- quando um novo produto aparecer, você precisará escrever um novo script
- nenhum suporte de dependência
Obviamente, você pode escrever um script sofisticado, mas, como escrevi acima, esse é o tempo de desenvolvimento, e não o menor, mas, como você sabe, nem sempre há tempo suficiente.
Obviamente, tudo isso limita o escopo desse método de implantação aos sistemas mais simples. Chegou a hora de mudar isso.
Docker

Em algum momento, os meios recém-assados começaram a chegar até nós, fervilhando de idéias e delirando com uma estivadora. Bem, a bandeira na mão - faça! Houve duas tentativas. Ambos sem sucesso - digamos assim, por causa de grandes ambições, mas a falta de experiência real. Era necessário forçar e terminar por qualquer meio? É improvável - a equipe deve evoluir progressivamente para o nível desejado antes de poder usar as ferramentas apropriadas. Além disso, usando imagens prontas do docker, deparamos com o fato de que a rede funcionava incorretamente lá (o que, talvez, também estava conectada à umidade do docker) ou era difícil expandir os contêineres de outras pessoas.
Que inconveniente encontramos?
- Problemas de rede no modo bridge
- É inconveniente olhar para os logs no contêiner (se eles não forem levados a nenhum lugar separadamente para o sistema de arquivos do host)
- O ElasticSearch periodicamente estranho trava dentro do contêiner, o motivo não foi estabelecido, o contêiner é oficial
- É difícil usar a concha dentro do contêiner - tudo é muito aparado, não há ferramentas familiares
- Recipientes grandes para coletar - caros para armazenar
- Devido ao grande tamanho dos contêineres, é difícil suportar várias versões
- Compilação mais longa, diferente de outros métodos (scripts ou pacotes deb)
Por outro lado, é pior implantar um serviço Spring na forma de um arquivo jar através da mesma deb? O isolamento de recursos é realmente necessário? Vale a pena perder as ferramentas convenientes do sistema operacional, colocando o serviço em um contêiner muito aparado?
Como a prática mostrou, na realidade isso não é necessário, um pacote deb é suficiente em 90% dos casos.
Quando o bom e velho deb ainda falha e quando realmente precisamos de uma janela de encaixe?
Para nós, essa foi uma implantação de serviços em python. Muitas bibliotecas necessárias para aprendizado de máquina e não disponíveis na entrega padrão do sistema operacional (e o que havia de versões erradas), hacks com configurações, a necessidade de versões diferentes para diferentes serviços que vivem no mesmo sistema host levaram a que a única maneira razoável de fornecer essa mistura nuclear era o estivador. A complexidade de montar o contêiner do docker acabou sendo menor do que a idéia de compactar tudo em pacotes deb separados com dependências, e ninguém em sã consciência teria aceitado.
O segundo ponto em que você planeja usar a janela de encaixe é para implantar serviços usando o esquema de implantação azul-verde. Mas aqui quero obter um aumento gradual na complexidade: primeiro, os pacotes deb são coletados e, em seguida, um contêiner de docker é montado a partir deles.
Pacotes de snap

Voltar para os pacotes de snap. Eles apareceram oficialmente no Ubuntu 16.04. Diferente dos pacotes deb e rpm, o snap carrega todas as dependências. Por um lado, isso evita o conflito de bibliotecas, por outro lado, significa tamanhos mais significativos do pacote resultante. Além disso, isso pode afetar a segurança do sistema: no caso de um snap, todas as alterações nas bibliotecas incluídas devem ser monitoradas pelo desenvolvedor que cria o pacote. Em geral, nem tudo é tão simples e a felicidade geral de seu uso não chega. Mas, no entanto, essa é uma alternativa bastante razoável, se o mesmo Docker for usado apenas como um meio de empacotamento e não como virtualização.
Como resultado, agora usamos pacotes deb e contêineres de encaixe em uma combinação razoável, que, talvez, em alguns casos, substituímos por pacotes snap.