Kubernetes no espírito da pirataria: nosso caminho para microsserviços e um modelo pronto para implementação



Olá, sou Yuri Buylov, estou desenvolvendo na CarPrice e também implementando práticas de DevOps, microsserviços e Kubernetes. Eu quero falar sobre Kubernetes no espírito da pirataria - não apenas sobre gerenciar um grande navio bonito em velas, mas também sobre uma frota de pequenos barcos de pesca feios, às vezes enferrujados, mas muito rápidos, ágeis e perigosos.

Será interessante para quem desenvolver ou transferir a infraestrutura para microsserviços, implementar o DevOps sobre o Kubernetes e acessar a nuvem nativa de todas as maneiras. Vou falar sobre o nosso caminho. No final do artigo, compartilharei nossas bases para o ambiente de microsserviços - fornecerei um link para um modelo que será conveniente para desenvolvedores e testadores.

Este artigo é baseado em uma apresentação em vídeo na @Kubernetes Conference pelo Mail.ru Cloud SolutionsSe você não quiser ler, pode ver .

Como vivemos antes do Kubernetes: servidores de desenvolvimento, bare metal e Ansible


Vivemos e vivemos em um modo de constantes mudanças e experimentos: testes AV, testando várias hipóteses. Lançamos novos serviços; se algo não funcionar, cortamos.

Certa vez, tivemos um monólito no PHP, o que trouxe muita dor e sofrimento. Para fornecer um tempo de comercialização aceitável, seguimos o caminho típico - começamos a ver esse monólito para microsserviços. Como resultado, verificou-se que um grande monólito se transformou em muitos pequenos monólitos. Isso é normal, é o caso de todos que enfrentaram uma tarefa semelhante.

Então começamos a experimentar outras tecnologias, em particular, Golang apareceu em nossa empresa, que mais tarde se tornou a principal linguagem de desenvolvimento. Havia perguntas: como desenvolver, testar e implantar tudo isso? A resposta foi óbvia - você precisa de um servidor de desenvolvimento. Cada desenvolvedor deve ter um servidor dev, onde ele pode se conectar para escrever um código de alta qualidade e alto desempenho lá.

Como resultado, os caras escreveram um servidor de desenvolvimento. O resultado foi uma interface da web que controlava a composição do docker nos servidores. Havia também um contêiner com o código-fonte, montado em docker-compose. O desenvolvedor pode se conectar via SSH e programa. Os testadores também trabalharam lá, tudo funcionou perfeitamente.



Mas com o aumento do número de serviços, tornou-se impossível trabalhar. Chegou o momento em que era necessário implantar algo, não descompactar os contêineres. Pegamos metal nu, enrolamos o Docker lá. Então eles pegaram Ansible, escreveu vários papéis. Cada função é um serviço em que o docker-compose fica, que "veio" a um dos carros.



Então, nós vivemos: no nginx, registramos a montante com nossas mãos, eles disseram para qual porto devemos ir, onde esse serviço mora. Havia até um arquivo yaml onde todas as portas estavam listadas para que os aplicativos não competissem por elas.

Como chegamos ao Kubernetes e construímos a infraestrutura nele


Obviamente, não se pode viver assim, é necessária orquestração. Entendemos isso em 2017-2018, então não estava claro onde conseguir essa orquestra. Kubernetes estava apenas começando, havia HashiCorp Nomad, Rancher, OpenShift. Tentamos o Nomad, não era ruim, mas não queríamos reescrever o docker-composite para as configurações do Nomad.

Sobre Kubernetes, percebemos imediatamente que colegas estrangeiros tentaram fazê-lo, nem sempre tiveram sucesso. E não tínhamos administradores barbudos que pudessem nos tornar um cluster. Eles começaram a pensar em como implementar isso. Mesmo então, Kubernetes estava, por exemplo, na Amazônia, mas lembramos das fechaduras, após as quais elas se moviam com urgência. Portanto, essa opção foi descartada imediatamente, com tráfego mais caro por lá.

E então o Kubernetes apareceu na plataforma Mail.ru Cloud Solutions como um serviço Mail.ru Cloud Containers. Já mudamos nosso armazenamento S3 para lá da Amazon, decidimos experimentar os K8s também. Nós implantamos um cluster na nuvem, tudo funcionou.

Para o teste, decidimos implantar algum serviço sem estado lá. Tomou uma API para aplicativos móveis, implantada - funciona. Enviado para lá 50% do tráfego - funciona. Sim, algo caía periodicamente, mas os caras consertavam, estava tudo bem. Como resultado, toda a infraestrutura foi transferida, agora é construída em torno do Kubernetes, principalmente servidores de desenvolvimento e de estágio.



Cada desenvolvedor tem seu próprio Minikube no VMware, com o qual ele trabalha. Lançamos novos projetos no Kubernetes na nuvem MCS, também implantamos o MySQL gerenciado, que chega imediatamente com todos os escravos, replicações e backups no S3.

Ainda temos legado no bare metal, incluindo um cluster de docker executando o Ansible, mas um dia descobriremos isso.

Como viver com um zoológico de tecnologia e não sofrer


O zoológico de tecnologia agora não é tão assustador quanto era, digamos, em 2011. É normal que você possa usar ferramentas e tecnologias especializadas de diferentes lugares e usá-lo como quiser. Por exemplo, usamos Golang para algumas coisas, mas o Data Scientist trabalha em Python, você não pode forçá-los a escrever no GO ou PHP.

Em geral, temos duas regras:

  • dockerize: deve haver contêineres;
  • observabilidade: esses recipientes devem ser observáveis.

Para continuar a analogia com o zoológico: existem células e não é tão importante quem está sentado nessas células. O principal é que a água e a comida chegam regularmente, automática e uniformemente, e os "produtos vitais" dos serviços, ou seja, toras, são enviados para algum lugar central.

Para observabilidade, temos uma pilha padrão: cada aplicativo grava logs no stdout, de onde tudo é transferido centralmente para o EFK. Ou seja, o desenvolvedor pode vir e ver os logs no Kibana. Métricas de aplicativos que lançamos no Prometheus, painéis e alertas como padrão no Grafana. Jaeger é uma história do Opentracing que mostra quem acessa qual serviço, se não soubermos ou não quisermos lidar com ele de outras maneiras.



Como desenvolver e testar com tudo isso


Digamos que um novo desenvolvedor chegue até nós, ele vê 100 serviços e 100 repositórios. Ele imediatamente tem perguntas. Como implantar esses 100 serviços e como configurar? Onde estão os bancos de dados? Quais contas existem? E há muitas dessas perguntas. Por esse motivo, o lançamento do novo desenvolvedor levou um tempo indecente, ele pode ficar sentado por uma semana e configurar tudo.

Como resultado, desenvolvemos um ambiente de desenvolvimento com 1 clique. Cada desenvolvedor possui seu próprio Minikube com núcleos e memória condicionalmente infinitos, implantados na nuvem VMware. Além de um banco de dados - ele vem diariamente da produção, é ofuscado, compactado e colocado no ZFS. Este é um desenvolvimento pessoal de nosso administrador. Estamos envolvidos na redução de custos há muito tempo, precisávamos dar a todos os desenvolvedores uma base e não ficar sem dinheiro.

Existem instantâneos no ZFS, um desenvolvedor de API pode rolar o banco de dados diretamente da produção em dois segundos. Com os autotestes, a mesma história: começamos pela API e tudo funciona.



É assim que parece o fluxo de desenvolvimento hoje: o



desenvolvedor está feliz, o DevOps e os administradores estão felizes porque todos os processos são uniformes, repetíveis e unificados. Mas há uma coisa.

Sistema de camadas em camadas


Como Linus Torvalds disse: “Conversar é barato. Mostre-me o código ". Então, usamos um sistema de camada de vários níveis. Existem camadas triviais: dev, stage, prod, que vêm à mente de todos que irão criar CI / CD.

Mas ainda existem desenvolvedores, eles precisam de alguns de seus domínios, algumas histórias específicas do usuário, por isso temos uma camada de valores de usuários. Mas isso não é suficiente - você ainda precisa testar. Suponha que tenhamos criado uma filial, talvez vários serviços, e precisamos passar isso para o testador, para que ele se repita. Para isso, temos uma camada com valores para tarefas, ou seja, valores de tarefas.

Outro momento, ligeiramente holivarny - não usamos Tiller, estabelecido em Helm, mas na verdade o usamos como um mecanismo de modelo. Ou seja, usamos apenas helm-template, ele fornece um arquivo yaml na saída, que pode ser atribuído ao Minikube ou a um cluster, e nada mais é necessário.



Como o repositório K8s-helm funciona


Como eu disse, temos camadas óbvias de dev, prod e stage, existe um arquivo yaml de cada serviço, quando vimos um novo serviço, adicione o arquivo.

Além disso, há um pai dev.server com o mais interessante. Existem scripts bash que ajudam, por exemplo, a criar um novo usuário: não crie 100 serviços com as mãos e não preencha arquivos yaml, mas simplesmente execute um comando. É aqui que todos esses arquivos yaml são gerados.



Na mesma pasta, há uma tarefa de subpasta. Se precisarmos criar valores específicos para nossa implantação, basta criar uma pasta com os números das tarefas, confirmar a ramificação. Então dizemos ao testador: "Esse ramo está no repositório, pega-o e executa-o". Ele começa, puxa o comando que está no lixo, e tudo funciona - não há necessidade de configurar manualmente. O milagre do DevOps é uma infraestrutura como código.

Como resultado, o processo se resume a três equipes:



Quando um novo desenvolvedor chega, ele fornece a ele o Minikube, uma pasta de arquivo com certificados e um domínio. Em geral, ele só precisa de kubectl e Helm. Ele clona o repositório para si mesmo, mostra ao kubectl o caminho para sua configuração, executa o comando make_user com seu nome. E para todos os serviços, cópias são criadas para ele. Além disso, eles não são apenas criados - há um banco de dados que foi fornecido a ele, o desenvolvedor prescreveu credenciais para ele e todas essas credenciais vão para outros serviços.

O usuário foi criado. Como posso implantá-lo agora? Nada complicado aqui também - rodamos deploy.sh com o nome dele e tudo chega ao desenvolvedor no espaço de nomes padrão em seu Minikube, tudo fica imediatamente disponível em seu domínio.

Se o desenvolvedor programou algo, ele pega o ID do problema e o entrega ao testador. O testador copia essa ramificação, inicia uma implantação e um ambiente com um novo recurso aparece em seu cluster.

Montagem do leme K8s


O próprio repositório é adicionalmente compilado e incorporado aos processos de CI / CD. Nada de especial aqui - apenas kubectl com certificados e Helm.



No projeto, fica assim:



Suponha que você esteja implantado e que haja um estágio em que você precise primeiro o estágio e, em seguida, execute os testes usando o Jenkins. No repositório, você tem uma imagem compilada com o Helm. Executamos o comando deploy namespace service_stage run e tudo decola.

Em seguida, vem o CI, aqui .drone.yml, mas a mesma coisa acontecerá no GitLab ou em outro lugar.

Em seguida, Jenkins inicia, que executa os testes no palco. Se estiver tudo bem, ele inicia quase a mesma implantação, mas já está no produto. Ou seja, esse mecanismo não apenas facilita a vida de desenvolvedores e testadores, mas também é usado para fornecer recursos aos produtos.

Adoramos o código aberto, queremos investir no desenvolvimento do DevOps, por isso criamos um modelo que você pode usar e o carregou no github . Eu falei de tudo: você pode assistir, assistir, testar e aplicar. Será útil para todos que implementam microsserviços, ou sofrem com o fato de que a equipe implementa microsserviços, ou deseja criar processos de DevOps em torno disso.

Outros artigos relacionados:

  1. 25 ferramentas úteis do Kubernetes: implantação e gerenciamento .
  2. Segundo faturamento, mercado e sandboxes para Big Data: o que os ambientes de teste na nuvem podem fazer .
  3. Como migrar para a nuvem em duas horas, graças ao Kubernetes e à automação

Essa palestra foi feita pela primeira vez na Conferência @Kubernetes pela Mail.ru Cloud Solutions. Assista a um vídeo de outras apresentações e inscreva-se nos anúncios de eventos do Telegram Around Kubernetes no Mail.ru Group .

All Articles