DEVOXX UK. Kubernetes em produção: implantação azul / verde, dimensionamento automático e automação de implantação. Parte 2

O Kubernetes é uma ótima ferramenta para executar contêineres do Docker em um ambiente de produção em cluster. No entanto, existem tarefas que o Kubernetes não consegue resolver. Com implantações frequentes em um ambiente de produção, precisamos de uma implantação azul / verde totalmente automatizada para evitar o tempo de inatividade nesse processo, que também requer solicitações HTTP externas e upload de SSL. Isso requer integração com um balanceador de carga, como ha-proxy. Outra tarefa é o dimensionamento semiautomático do próprio cluster Kubernetes ao trabalhar na nuvem, por exemplo, redução parcial da escala do cluster à noite.

Embora o Kubernetes não tenha esses recursos prontos para uso, ele fornece uma API que pode ser usada para resolver esses problemas. As ferramentas de implantação e escala automatizadas azul / verde do cluster Kubernetes foram desenvolvidas como parte do projeto de código aberto Cloud RTI.

Esta transcrição de vídeo descreve como configurar o Kubernetes junto com outros componentes de código-fonte aberto para obter um ambiente pronto para produção que aceita código da confirmação de alteração de confirmação do git sem tempo de inatividade na produção.



DEVOXX UK. Kubernetes em produção: implantação azul / verde, dimensionamento automático e automação de implantação. Parte 1

Portanto, depois de acessar seus aplicativos do mundo exterior, você pode começar a configurar completamente a automação, ou seja, levá-la ao estágio em que pode executar o git commit e garantir que esse commit do git termine em produção. Naturalmente, na implementação dessas etapas, na implementação da implantação, não queremos enfrentar o tempo de inatividade. Portanto, qualquer automação no Kubernetes começa com uma API.



O Kubernetes não é uma ferramenta que pode ser usada “pronta para uso” de maneira produtiva. Obviamente, você pode fazer isso, usar o kubectl e assim por diante, mas a API ainda é a coisa mais interessante e útil sobre esta plataforma. Usando a API como um conjunto de recursos, você pode acessar quase tudo o que deseja fazer no Kubernetes. O próprio Kubectl também usa a API REST.

Este é o REST, portanto, você pode usar quaisquer idiomas e ferramentas para trabalhar com essa API, mas as bibliotecas de usuários facilitarão muito sua vida. Minha equipe escreveu duas dessas bibliotecas: uma para Java / OSGi e uma para Go. O segundo não é usado com frequência, mas, de qualquer forma, essas coisas úteis estão à sua disposição. Eles são um projeto de código aberto parcialmente licenciado. Existem muitas bibliotecas para diferentes idiomas, para que você possa escolher a mais adequada.



Portanto, antes de iniciar a automação de implantação, você precisa garantir que esse processo não esteja sujeito a nenhum tempo de inatividade. Por exemplo, nossa equipe realiza a implantação da produção no meio do dia, quando as pessoas tiram o máximo proveito de seus aplicativos, por isso é muito importante evitar atrasos nesse processo. Para evitar o tempo de inatividade, dois métodos são usados: implantação azul / verde ou atualização sem interrupção. Neste último caso, se você tiver 5 réplicas do aplicativo em execução, elas serão atualizadas seqüencialmente uma após a outra. Esse método funciona muito bem, mas não funciona se você estiver executando versões diferentes do aplicativo ao mesmo tempo durante o processo de implantação. Nesse caso, você pode atualizar a interface do usuário enquanto o back-end funcionará com a versão antiga e o aplicativo deixará de funcionar.Portanto, do ponto de vista da programação, trabalhar nessas condições é bastante difícil.

Esse é um dos motivos pelos quais preferimos usar a implantação azul / verde para automatizar a implantação de nossos aplicativos. Com esse método, você deve garantir que, em um determinado momento, apenas uma versão do aplicativo esteja ativa.

O mecanismo de implantação azul / verde é o seguinte. Obtemos tráfego para nossos aplicativos por meio do ha-proxy, que o direciona para a execução de réplicas de aplicativos da mesma versão.

Quando uma nova implantação é realizada, usamos o Deployer, que é fornecido com novos componentes, e ele implementa a nova versão. A implantação de uma nova versão de um aplicativo significa que um novo conjunto de réplicas está "aumentando", após o qual essas réplicas da nova versão são iniciadas em um novo pod separado. No entanto, o ha-proxy não sabe nada sobre eles e até agora não enviou nenhuma carga de trabalho.

Portanto, antes de tudo, é necessário verificar a integridade de novas versões do health cheking para garantir que as réplicas estejam prontas para atender à carga.



Todos os componentes de implantação devem oferecer suporte a algum tipo de integridade. Pode ser uma verificação HTTP muito simples com uma chamada quando você recebe um código com status 200 ou uma verificação mais profunda na qual você verifica a conexão de réplicas com o banco de dados e outros serviços, a estabilidade das conexões do ambiente dinâmico, se tudo começa e funciona corretamente. Este processo pode ser bastante complicado.



Depois que o sistema verificar que todas as réplicas atualizadas estão operacionais, o Deployer atualizará a configuração e passará a confd correta, que reconfigurará o ha-proxy.



Somente depois disso o tráfego será direcionado para o under com réplicas da nova versão, e a antiga desaparecerá.



Este mecanismo não é um recurso do Kubernetes. O conceito de implantação azul / verde existe há algum tempo e sempre usou um balanceador de carga. Primeiro, você direciona todo o tráfego para a versão antiga do aplicativo e, após a atualização, transfere-o completamente para a nova versão. Este princípio é usado não apenas no Kubernetes.

Agora, apresentarei um novo componente de implantação - o Deployer, que executa uma verificação de integridade, reconfigura os proxies e assim por diante. Este é um conceito que não se aplica ao mundo exterior e existe dentro do Kubernetes. Mostrarei como você pode criar seu próprio conceito de Deployer usando ferramentas de código aberto.

Portanto, a primeira coisa que o Deployer faz é criar um controlador de replicação RC usando a API Kubernetes. Essa API cria pods e serviços para implantação adicional, ou seja, cria um cluster completamente novo para nossos aplicativos. Depois que o RC verificar que as réplicas foram iniciadas, ele verificará sua verificação de integridade. Para fazer isso, o Deployer usa o comando GET / health. Ele lança os componentes de verificação correspondentes e verifica todos os elementos que garantem a operação do cluster.



Depois que todos os pods relataram sua "integridade", o Deployer cria um novo item de configuração - o armazenamento distribuído etcd, usado no Kubernetes, inclusive para armazenar a configuração do balanceador de carga. Nós escrevemos dados no etcd, e uma pequena ferramenta, confd, monitora o etcd para novos dados.

Se ele encontrar alguma alteração na configuração inicial, ele gera um novo arquivo de configurações e o passa para o ha-proxy. Nesse caso, o ha-proxy é reinicializado sem perder nenhuma conexão e soluciona a carga com novos serviços que fornecem a nova versão de nossos aplicativos.



Como você pode ver, apesar da abundância de componentes, não há nada complicado. Você só precisa prestar mais atenção à API e etcd. Quero falar sobre o implantador de código aberto que nós mesmos usamos - este é o Amdatu Kubernetes Deployer.



Esta é uma ferramenta de orquestração de implantação do Kubernetes com os seguintes recursos:

  • Implantação azul / verde
  • configurando um balanceador de carga externo;
  • Gerenciamento do descritor de implantação
  • Gerenciamento de implantação real
  • Verificações de integridade durante a implantação
  • implementação de variáveis ​​de ambiente em pods.

Criado na parte superior da API Kubernetes, este Deployer fornece uma API REST para gerenciar descritores e implantações, além de uma API Websocket para logs de fluxo durante a implantação.

Ele coloca os dados de configuração do balanceador de carga no etcd, para que você não possa usar o ha-proxy com suporte "pronto para uso", mas é fácil usar seu próprio arquivo de configuração do balanceador. O Amdatu Deployer é escrito em Go, assim como o próprio Kubernetes, e licenciado pelo Apache.

Antes de usar esta versão do implementador, usei o seguinte descritor de implementação, que especifica os parâmetros necessários.



Um dos parâmetros importantes desse código é ativar o sinalizador "useHealthCheck". Precisamos indicar que uma verificação de integridade é necessária durante o processo de implantação. Esta opção pode ser desativada quando a implantação usa contêineres de terceiros que não precisam ser verificados. Este descritor também indica o número de réplicas e o URL de front-end que o ha-proxy precisa. No final, está o sinalizador de especificação para o pod podspec, que chama o Kubernetes para obter informações sobre configuração de porta, imagem, etc. Este é um descritor bastante simples no formato JSON.

Outra ferramenta que faz parte do projeto de código aberto Amdatu é o Deploymentctl. Ele possui uma interface de usuário para configurar a implantação, armazena o histórico de implantação e contém webhooks para retornos de chamada de usuários e desenvolvedores de terceiros. Você não pode usar a interface do usuário, pois o próprio Amdatu Deployer é uma API REST, mas essa interface pode facilitar a implantação sem envolver nenhuma API. O Deploymentctl está escrito em OSGi / Vertx usando o Angular 2.

Agora, demonstrarei o acima na tela usando uma gravação pré-criada, para que você não precise esperar. Vamos implantar um aplicativo simples no Go. Não se preocupe, se você não encontrou o Go antes, este é um aplicativo muito simples, portanto você deve entender tudo.



Aqui, criamos um servidor HTTP que responde apenas a / health, para que este aplicativo verifique apenas a verificação de saúde e nada mais. Se a verificação for aprovada, a estrutura JSON mostrada abaixo será chamada. Ele contém a versão do aplicativo que será implantada pelo implementador, a mensagem que você vê na parte superior do arquivo e o tipo de dados lógicos booleanos - independentemente de nosso aplicativo estar funcionando ou não.

Eu trapacei um pouco com a última linha, porque coloquei um valor booleano fixo na parte superior do arquivo, que no futuro me ajudará a implantar até mesmo um aplicativo "não íntegro". Nós vamos lidar com isso mais tarde.

Então vamos começar. Primeiro, verificamos quaisquer pods em execução usando o comando ~ kubectl get pods e, se não houver resposta do URL do front-end, garantimos que nenhuma implantação esteja sendo executada no momento.



Em seguida, na tela, você vê a interface Deploymentctl que mencionei, na qual os parâmetros de implantação são definidos: namespace, nome do aplicativo, versão de implantação, número de réplicas, URL de front-end, nome do contêiner, imagem, limites de recursos, número da porta para verificação de integridade etc. . Os limites de recursos são muito importantes, pois permitem que você use a quantidade máxima possível de "ferro". Você também pode ver o log de implantação do log de implantação aqui.



Se você repetir o comando ~ kubectl get pods agora, poderá ver que o sistema "congela" por 20 segundos, durante os quais a reconfiguração do ha-proxy ocorre. Depois disso, ele inicia em baixo e nossa réplica pode ser vista no log de implantação.



Recortei uma espera de 20 segundos no vídeo e agora você vê na tela que a primeira versão do aplicativo foi implantada. Tudo isso foi feito apenas com a ajuda da interface do usuário.



Agora vamos tentar a segunda versão. Para fazer isso, altero a mensagem do aplicativo com "Olá, Kubernetes!" para “Olá, Deployer!”, o sistema cria essa imagem e a coloca no registro do Docker, após o qual simplesmente clicamos no botão “Deploy” na janela Deploymentctl novamente. Nesse caso, o log de implantação é iniciado automaticamente da mesma maneira que quando a primeira versão do aplicativo foi implantada.



O comando ~ kubectl get pods mostra que 2 versões do aplicativo estão em execução no momento, mas o front-end mostra que ainda estamos executando a versão 1. O



balanceador de carga aguarda a execução da verificação de integridade e redireciona o tráfego para a nova versão. Após 20 segundos, passamos para o curl e vemos que agora implantamos a versão 2 do aplicativo e a primeira é removida.



Foi a implantação de um aplicativo "saudável" - saudável -. Vamos ver o que acontece se, para a nova versão do aplicativo, alterar o valor do parâmetro Healthy de true para false, ou seja, tentarei implantar um aplicativo não íntegro que não passou na verificação de integridade. Isso pode acontecer se, no estágio de desenvolvimento, alguns erros de configuração foram cometidos no aplicativo e eles entraram em produção neste formulário.

Como você pode ver, a implantação segue todas as etapas acima e o ~ kubectl get pods mostra que os dois estão em execução. Mas, diferentemente da implantação anterior, o log mostra o estado do tempo limite. Ou seja, devido ao fato da verificação de integridade não ter passado, a nova versão do aplicativo não pode ser implantada. Como resultado, você vê que o sistema voltou a usar a versão antiga do aplicativo e a nova versão foi simplesmente excluída.



O bom disso é que, mesmo que você tenha um grande número de solicitações simultâneas no aplicativo, elas nem perceberão o tempo de inatividade durante a implementação do procedimento de implantação. Se você testar esse aplicativo usando a estrutura Gatling, que envia o número máximo possível de solicitações, nenhuma delas será descartada. Isso significa que nossos usuários nem notarão atualizações de versão em tempo real. Se falhar, o trabalho continuará na versão antiga; se for bem-sucedido, os usuários mudarão para a nova versão.

Há apenas uma coisa que pode levar à falha - se a verificação de integridade foi bem-sucedida e o aplicativo travou assim que recebeu a carga de trabalho, ou seja, o colapso ocorrerá somente após a conclusão da implantação. Nesse caso, você terá que reverter manualmente para a versão antiga. Então, vimos como usar o Kubernetes com suas ferramentas de código aberto. O processo de implantação será muito mais simples se você incorporar essas ferramentas nos pipelines de criação / implantação de pipelines de criação / implantação. Ao mesmo tempo, para iniciar a implantação, você pode usar a interface do usuário e automatizar totalmente esse processo, aplicando, por exemplo, o compromisso de dominar.



Nosso servidor de compilação do Build Server criará uma imagem do Docker, colará no Docker Hub ou em qualquer outro registro que você usar. O hub do Docker oferece suporte ao webhook, para que possamos iniciar a implantação remota pelo Deployer, como mostrado acima. Assim, você pode automatizar totalmente a implantação do aplicativo na produção potencial.

Vamos para o próximo tópico - dimensionar o cluster Kubernetes. Percebo que o comando kubectl é um comando de dimensionamento. Com a ajuda de outro, você pode aumentar facilmente o número de réplicas em nosso cluster. No entanto, na prática, geralmente queremos aumentar o número de nós, não nós.



Ao mesmo tempo, durante o horário de trabalho, pode ser necessário aumentar e, à noite, reduzir o custo dos serviços da Amazon, diminuir o número de instâncias em execução do aplicativo. Isso não significa que apenas o número de pods será escalado o suficiente, porque mesmo se um dos nós não estiver ocupado, você ainda precisará pagar pela Amazon. Ou seja, junto com o dimensionamento das lareiras, é necessário dimensionar o número de máquinas usadas.

Isso pode ser complicado porque, independentemente de usarmos a Amazon ou outro serviço em nuvem, o Kubernetes não sabe nada sobre o número de máquinas usadas. Falta uma ferramenta que permita dimensionar o sistema no nível dos nós.



Então, teremos que cuidar dos nós e dos pods. Podemos escalar facilmente o lançamento de novos nós usando a API da AWS e as máquinas de grupos de dimensionamento para configurar o número de nós de trabalho do Kubernetes. Você também pode usar cloud-init ou um script semelhante para registrar nós em um cluster Kubernetes.

A nova máquina inicia no grupo Dimensionamento, inicia-se como um nó, registra-se no registro do assistente e inicia o trabalho. Depois disso, você pode aumentar o número de réplicas para uso nos nós resultantes. Reduzir a escala requer mais esforço, pois você precisa garantir que essa etapa não leve à destruição de aplicativos já em execução após desligar as máquinas "desnecessárias". Para evitar esse cenário, você precisa trazer os nós para o status "não programável". Isso significa que o planejador padrão ao planejar pods do DaemonSet ignorará esses nós. O agendador não excluirá nada desses servidores, mas também não lançará novos contêineres lá. O próximo passo é deslocar o nó de drenagem, ou seja, transferir os lares de trabalho dele para outra máquina ou para outros nós com capacidade suficiente para isso.Após verificar se não há mais contêineres nesses nós, você pode removê-los do Kubernetes. Depois disso, para os Kubernetes, eles simplesmente deixam de existir. Em seguida, você precisa usar a API da AWS para desativar nós ou máquinas desnecessários.
Você pode usar o Amdatu Scalerd, outra ferramenta de dimensionamento de código aberto semelhante à API da AWS. Ele fornece uma CLI para adicionar ou remover nós em um cluster. Seu recurso interessante é a capacidade de configurar o planejador usando o seguinte arquivo json.



O código mostrado reduz pela metade a capacidade do cluster à noite. É configurado como o número de réplicas disponíveis e a capacidade desejada do cluster da Amazon. O uso desse agendador reduzirá automaticamente o número de nós à noite e aumentará de manhã, economizando o custo do uso de nós de um serviço em nuvem como a Amazon. Esse recurso não está embutido no Kubernetes, mas o uso do Scalerd permitirá que você dimensione essa plataforma como desejar.

Quero chamar sua atenção para o fato de muitas pessoas me dizerem: "Tudo isso é bom, mas e o meu banco de dados, que geralmente está em estado estático?" Como posso executar algo assim em um ambiente dinâmico como o Kubernetes? Na minha opinião, você não deve fazer isso, não deve tentar organizar a operação do armazém de dados no Kubernetes. Tecnicamente, isso é possível, e existem manuais na Internet sobre esse assunto, mas isso complicará seriamente sua vida.

Sim, o conceito de armazenamento persistente existe no Kubernetes e você pode tentar executar data warehouses como Mongo ou MySQL, mas essa é uma tarefa bastante demorada. Isso se deve ao fato de que os data warehouses não suportam totalmente a interação com um ambiente dinâmico. A maioria dos bancos de dados exige ajuste significativo, incluindo a configuração manual do cluster, não gosta de dimensionamento automático e outras coisas semelhantes.
Portanto, não complique sua vida ao tentar iniciar um data warehouse no Kubernetes. Organize seu trabalho da maneira tradicional usando serviços familiares e apenas dê ao Kubernetes a oportunidade de usá-los.



No final do tópico, quero apresentar a plataforma Cloud RTI baseada no Kubernetes, na qual minha equipe está trabalhando. Ele fornece registro centralizado, aplicativos de monitoramento e clusters e possui muitos outros recursos úteis para você. Ele usa várias ferramentas de código aberto, como o Grafana, para exibir o monitoramento.





A questão foi levantada, por que usar o balanceador de carga ha-proxy com o Kubernetes. Boa pergunta, porque atualmente existem 2 níveis de balanceamento de carga. Os serviços Kubernetes ainda estão localizados em endereços IP virtuais. Você não pode usá-los para portas de host externas, porque se a Amazon reiniciar seu host na nuvem, o endereço mudará. É por isso que colocamos os serviços ha-proxy na frente dos serviços - para criar uma estrutura mais estática para interação de tráfego contínua com o Kubernetes.

Outra boa pergunta é como posso cuidar da alteração do esquema do banco de dados durante a implantação em azul / verde? O fato é que, independentemente do uso do Kubernetes, alterar o esquema do banco de dados é uma tarefa complexa. É necessário garantir a compatibilidade do antigo e do novo esquema, após o qual você pode atualizar o banco de dados e, em seguida, atualizar os aplicativos. Você pode trocar o banco de dados a quente e depois atualizar os aplicativos. Conheço pessoas que baixaram um cluster de banco de dados completamente novo com um novo esquema. Essa é uma opção se você tiver um banco de dados sem restrições como o Mongo, mas, de qualquer forma, essa não é uma tarefa fácil. Se não houver mais perguntas, obrigado por sua atenção!


Um pouco de publicidade :)


Obrigado por ficar com a gente. Você gosta dos nossos artigos? Deseja ver materiais mais interessantes? Ajude-nos fazendo um pedido ou recomendando aos seus amigos o VPS na nuvem para desenvolvedores a partir de US $ 4,99 , um analógico exclusivo de servidores de nível básico que foi inventado por nós para você: Toda a verdade sobre o VPS (KVM) E5-2697 v3 (6 núcleos) 10 GB DDR4 480 GB SSD 1 Gbps de US $ 19 ou como dividir o servidor? (as opções estão disponíveis com RAID1 e RAID10, até 24 núcleos e até 40GB DDR4).

Dell R730xd 2 vezes mais barato no data center Equinix Tier IV em Amsterdã? Somente nós temos 2 TVs Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV a partir de US $ 199 na Holanda!Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - a partir de US $ 99! Leia sobre Como criar um prédio de infraestrutura. classe c usando servidores Dell R730xd E5-2650 v4 que custam 9.000 euros por um centavo?

All Articles