O dispositivo Helm e suas armadilhas

O dispositivo Helm e suas armadilhas
Conceito de transportador de carga Typhon, Anton Swanepoel

Meu nome é Dmitry Sugrobov, sou desenvolvedor da Leroy Merlin. Neste artigo vou contar por que o Helm é necessário, como ele simplifica o trabalho com Kubernetes, o que mudou na terceira versão e como usá-lo para atualizar aplicações em produção sem tempo de inatividade.

Este é um resumo baseado em um discurso em uma conferência Conferência @Kubernetes by Soluções em nuvem Mail.ru - se você não quiser ler, assista ao vídeo.

Por que usamos Kubernetes na produção

A Leroy Merlin é líder no mercado de varejo DIY na Rússia e na Europa. Nossa empresa conta com mais de uma centena de desenvolvedores, 33 mil funcionários internos e um grande número de visitantes de hipermercados e do site. Para deixar todos felizes, decidimos seguir as abordagens padrão da indústria. Desenvolver novas aplicações utilizando arquitetura de microsserviços; utilizar contêineres para isolar ambientes e garantir a entrega adequada; e use o Kubernetes para orquestração. O preço do uso de orquestradores está se tornando rapidamente mais barato: o número de engenheiros proficientes na tecnologia está crescendo no mercado e estão aparecendo provedores que oferecem Kubernetes como serviço.

Tudo o que o Kubernetes faz, é claro, pode ser feito de outras maneiras, por exemplo, cobrindo alguns scripts Jenkins e docker-compose, mas por que complicar a vida se existe uma solução pronta e confiável? É por isso que viemos para o Kubernetes e já o usamos em produção há um ano. Atualmente temos vinte e quatro clusters Kubernetes, o mais antigo dos quais tem mais de um ano, com cerca de duzentos pods.

A maldição dos grandes arquivos YAML no Kubernetes

Para lançar um microsserviço no Kubernetes, criaremos pelo menos cinco arquivos YAML: para Deployment, Service, Ingress, ConfigMap, Secrets - e os enviaremos para o cluster. Para a próxima aplicação escreveremos o mesmo pacote de batentes, na terceira escreveremos outro e assim por diante. Se multiplicarmos a quantidade de documentos pela quantidade de ambientes, já obteremos centenas de arquivos, e isso ainda sem levar em conta os ambientes dinâmicos.

O dispositivo Helm e suas armadilhas
Adam Reese, principal mantenedor do Helm, introduziu o conceito de "Ciclo de Desenvolvimento em Kubernetes", que se parece com isto:

  1. Copiar YAML - copia um arquivo YAML.
  2. Cole YAML - cole-o.
  3. Corrigir recuos - corrige recuos.
  4. Repita - repita novamente.

A opção funciona, mas você precisa copiar os arquivos YAML várias vezes. Para mudar esse ciclo, o Helm foi inventado.

O que é Helm

Em primeiro lugar, Helm - gerenciador de pacotes, que ajuda você a encontrar e instalar os programas necessários. Para instalar, por exemplo, o MongoDB, você não precisa ir ao site oficial e baixar binários, basta executar o comando helm install stable/mongodb.

Em segundo lugar, Helm - mecanismo de modelo, ajuda a parametrizar arquivos. Vamos voltar à situação dos arquivos YAML no Kubernetes. É mais fácil escrever o mesmo arquivo YAML, adicionar alguns espaços reservados a ele, nos quais o Helm substituirá os valores. Ou seja, em vez de um grande conjunto de andaimes, haverá um conjunto de templates nos quais os valores necessários serão substituídos no momento certo.

Em terceiro lugar, Helm - mestre de implantação. Com ele você pode instalar, reverter e atualizar aplicativos. Vamos descobrir como fazer isso.

O dispositivo Helm e suas armadilhas

Como usar o Helm para implantar seus próprios aplicativos

Vamos instalar o cliente Helm no seu computador, seguindo o procedimento oficial instruções. A seguir, criaremos um conjunto de arquivos YAML. Em vez de especificar valores específicos, deixaremos espaços reservados, que o Helm preencherá com informações no futuro. Um conjunto desses arquivos é chamado de gráfico Helm. Ele pode ser enviado ao cliente do console Helm de três maneiras:

  • indique uma pasta com modelos;
  • compactar o arquivo em um .tar e apontar para ele;
  • coloque o modelo em um repositório remoto e adicione um link para o repositório no cliente Helm.

Você também precisa de um arquivo com valores - valores.yaml. Os dados daí serão inseridos no modelo. Vamos criá-lo também.

O dispositivo Helm e suas armadilhas
A segunda versão do Helm possui um aplicativo de servidor adicional - Tiller. Ele fica fora do Kubernetes e aguarda solicitações do cliente Helm e, quando chamado, substitui os valores necessários no modelo e os envia para o Kubernetes.

O dispositivo Helm e suas armadilhas
O Helm 3 é mais simples: em vez de processar modelos no servidor, as informações agora são processadas inteiramente no lado do cliente Helm e enviadas diretamente para a API Kubernetes. Esta simplificação melhora a segurança do cluster e facilita o esquema de implementação.

Como tudo funciona

Execute o comando helm install. Vamos indicar o nome da versão do aplicativo e fornecer o caminho para valores.yaml. Ao final indicaremos o repositório onde o gráfico está localizado e o nome do gráfico. No exemplo, são “lmru” e “bestchart”, respectivamente.

helm install --name bestapp --values values.yaml lmru/bestchart

O comando pode ser executado apenas uma vez, quando executado novamente install precisa usar upgrade. Para simplificar, em vez de dois comandos, você pode executar o comando upgrade com chave adicional --install. Quando executado pela primeira vez, o Helm enviará um comando para instalar a versão e irá atualizá-la no futuro.

helm upgrade --install bestapp --values values.yaml lmru/bestchart

Armadilhas da implantação de novas versões de um aplicativo com Helm

Neste ponto da história, estou jogando Quem Quer Ser Milionário com o público e estamos descobrindo como fazer com que Helm atualize a versão do aplicativo. Assista o vídeo.

Quando eu estava aprendendo como o Helm funciona, fiquei surpreso com um comportamento estranho ao tentar atualizar versões de aplicativos em execução. Atualizei o código do aplicativo, carreguei uma nova imagem no registro do Docker, enviei o comando de implantação - e nada aconteceu. Abaixo estão algumas maneiras não totalmente bem-sucedidas de atualizar aplicativos. Ao estudar cada um deles com mais detalhes, você começa a entender a estrutura interna do instrumento e os motivos desse comportamento nada óbvio.

Método 1. Não altere as informações desde o último lançamento

Como diz o ditado site oficial Helm, “Os gráficos do Kubernetes podem ser grandes e complexos, então Helm tenta não mexer muito em nada.” Portanto, se você atualizar a versão mais recente da imagem do aplicativo no registro do Docker e executar o comando helm upgrade, então nada acontecerá. Helm pensará que nada mudou e não há necessidade de enviar um comando ao Kubernetes para atualizar o aplicativo.

Aqui e abaixo, a tag mais recente é mostrada apenas como exemplo. Quando você especifica essa tag, o Kubernetes sempre fará download da imagem do registro do docker, independentemente do parâmetro imagePullPolicy. Usar o que há de mais recente em produção é indesejável e causa efeitos colaterais.

Método 2. Atualizar LABEL na imagem

Como está escrito no mesmo documentação, “O Helm só atualizará um aplicativo se ele tiver sido alterado desde o último lançamento.” Uma opção lógica para isso parece ser atualizar o LABEL na própria imagem do docker. No entanto, Helm não analisa as imagens do aplicativo e não tem ideia de quaisquer alterações nelas. Conseqüentemente, ao atualizar os rótulos na imagem, o Helm não saberá sobre eles e o comando de atualização do aplicativo não será enviado ao Kubernetes.

Método 3: use uma chave --force

O dispositivo Helm e suas armadilhas
Vamos consultar os manuais e procurar a chave necessária. A chave faz mais sentido --force. Apesar do nome óbvio, o comportamento é diferente do esperado. Em vez de forçar uma atualização de aplicativo, seu verdadeiro objetivo é restaurar uma versão que esteja com status FAILED. Se você não usar esta chave, você precisará executar os comandos sequencialmente helm delete && helm install --replace. Sugere-se usar a chave em vez disso --force, que automatiza a execução sequencial desses comandos. Mais informações neste solicitação pull. Para dizer ao Helm para atualizar a versão do aplicativo, infelizmente, esta chave não funcionará.

Método 4. Alterar rótulos diretamente no Kubernetes

O dispositivo Helm e suas armadilhas
Atualizando rótulo diretamente no cluster usando o comando kubectl edit - péssima ideia. Esta ação levará à inconsistência de informações entre o aplicativo em execução e aquele que foi originalmente enviado para implantação. O comportamento do Helm durante a implantação neste caso difere de sua versão: o Helm 2 não fará nada e o Helm 3 implantará a nova versão do aplicativo. Para entender o porquê, você precisa entender como o Helm funciona.

Como funciona o Helm?

Para determinar se um aplicativo foi alterado desde sua última versão, o Helm pode usar:

  • executando aplicativo em Kubernetes;
  • novos valores.yaml e gráfico atual;
  • Informações de lançamento interno do Helm.

Para os mais curiosos: onde o Helm armazena informações internas sobre lançamentos?Ao executar o comando helm history, obteremos todas as informações sobre as versões instaladas usando Helm.

O dispositivo Helm e suas armadilhas
Também há informações detalhadas sobre os modelos e valores enviados. Podemos solicitá-lo:

O dispositivo Helm e suas armadilhas
Na segunda versão do Helm, essas informações estão localizadas no mesmo namespace onde o Tiller está rodando (kube-system por padrão), no ConfigMap, marcado com o rótulo “OWNER=TILLER”:

O dispositivo Helm e suas armadilhas
Quando a terceira versão do Helm apareceu, as informações foram movidas para segredos e para o mesmo namespace onde o aplicativo estava sendo executado. Graças a isso, tornou-se possível executar vários aplicativos simultaneamente em diferentes namespaces com o mesmo nome de lançamento. Na segunda versão, era uma grande dor de cabeça quando os namespaces eram isolados, mas podiam influenciar uns aos outros.

O dispositivo Helm e suas armadilhas

O segundo Helm, ao tentar entender se uma atualização é necessária, utiliza apenas duas fontes de informação: o que é fornecido agora, e informações internas sobre lançamentos, que ficam no ConfigMap.

O dispositivo Helm e suas armadilhas
O terceiro Helm usa uma estratégia de mesclagem de três vias: além dessas informações, ele também leva em consideração a aplicação que está sendo executada no momento no Kubernetes.

O dispositivo Helm e suas armadilhas
Por esse motivo, a versão antiga do Helm não fará nada, pois não leva em consideração as informações da aplicação no cluster, mas o Helm 3 receberá as alterações e enviará a nova aplicação para implantação.

Método 5. Use a opção --recreate-pods

Com uma chave --recreate-pods você pode alcançar o que planejou originalmente com a chave --force. Os contêineres serão reiniciados e, de acordo com a política imagePullPolicy: Always para a tag mais recente (mais sobre isso na nota de rodapé acima), o Kubernetes baixará e lançará uma nova versão da imagem. Isso não será feito da melhor maneira: sem levar em conta o StrategyType de implantação, ele desligará abruptamente todas as instâncias antigas do aplicativo e começará a lançar novas. Durante a reinicialização, o sistema não funcionará, os usuários sofrerão.

No próprio Kubernetes, um problema semelhante também existe há muito tempo. E agora, 4 anos após a inauguração Questão, o problema foi corrigido e, a partir da versão 1.15 do Kubernetes, a capacidade de reiniciar pods aparece.

Helm simplesmente desliga todos os aplicativos e lança novos contêineres próximos. Você não pode fazer isso em produção, para não causar tempo de inatividade do aplicativo. Isso só é necessário para necessidades de desenvolvimento e só pode ser executado em ambientes de estágio.

Como atualizar a versão do aplicativo usando Helm?

Alteraremos os valores enviados ao Helm. Normalmente, esses são valores substituídos no lugar da tag da imagem. No caso do mais recente, que costuma ser utilizado para ambientes improdutivos, a informação mutável é uma anotação, inútil para o próprio Kubernetes, e para o Helm servirá como um sinal da necessidade de atualização da aplicação. Opções para preenchimento do valor da anotação:

  1. Valor aleatório usando a função padrão - {{ randAlphaNum 6 }}.
    Há uma ressalva: após cada implantação usando um gráfico com tal variável, o valor da anotação será único e o Helm assumirá que há alterações. Acontece que sempre iremos reiniciar o aplicativo, mesmo que não tenhamos alterado sua versão. Isso não é crítico, pois não haverá tempo de inatividade, mas ainda assim é desagradável.
  2. Colar atual data e hora - {{ .Release.Date }}.
    Uma variante é semelhante a um valor aleatório com uma variável permanentemente única.
  3. Uma maneira mais correta é usar somas de verificação. Este é o SHA da imagem ou o SHA do último commit no git - {{ .Values.sha }}.
    Eles precisarão ser contados e enviados ao cliente Helm do lado da chamada, por exemplo, no Jenkins. Se o aplicativo tiver sido alterado, a soma de verificação será alterada. Portanto, o Helm só atualizará o aplicativo quando necessário.

Vamos resumir nossas tentativas

  • O Helm faz alterações da maneira menos invasiva, portanto, qualquer alteração no nível da imagem do aplicativo no Docker Registry não resultará em uma atualização: nada acontecerá após a execução do comando.
  • Ключ --force usado para restaurar versões problemáticas e não está associado a atualizações forçadas.
  • Ключ --recreate-pods atualizará os aplicativos à força, mas fará isso de forma vândala: desligará abruptamente todos os contêineres. Os usuários sofrerão com isso; você não deve fazer isso na produção.
  • Faça alterações diretamente no cluster Kubernetes usando o comando kubectl edit não faça isso: quebraremos a consistência e o comportamento será diferente dependendo da versão do Helm.
  • Com o lançamento da nova versão do Helm, muitas nuances surgiram. Os problemas no repositório Helm são descritos em linguagem clara e ajudarão você a entender os detalhes.
  • Adicionar uma anotação editável a um gráfico o tornará mais flexível. Isso permitirá que você implemente o aplicativo corretamente, sem tempo de inatividade.

Um pensamento de “paz mundial” que funciona em todas as áreas da vida: leia as instruções antes de usar, não depois. Somente com informações completas será possível construir sistemas confiáveis ​​e deixar os usuários satisfeitos.

Outros links relacionados:

  1. Conheça o Capacete 3
  2. Site oficial do Helm
  3. Repositório Helm no GitHub
  4. 25 ferramentas úteis do Kubernetes: implantação e gerenciamento

Este relatório foi apresentado pela primeira vez em Conferência @Kubernetes por Mail.ru Cloud Solutions. Olhar vídeo outras apresentações e inscreva-se para anúncios de eventos no Telegram Sobre Kubernetes no Grupo Mail.ru.

Fonte: habr.com

Adicionar um comentário