Dispositivo Helm e suas armadilhas

Dispositivo Helm e suas armadilhas
Conceito de transportador Typhon, Anton Swanepoel

Meu nome é Dmitry Sugrobov, sou desenvolvedor na "Leroy Merlin". Neste artigo, falarei sobre a importância do Helm, como ele facilita o trabalho com Kubernetes, o que mudou na terceira versão e como usá-lo para atualizar aplicativos em produção sem interrupções.

Este é um resumo inspirado na apresentação da conferência @Kubernetes Conference by Soluções em Nuvem Mail.ru — se você não quiser ler, assista ao vídeo.

Por que no hosting comum a administração do PrestaShop é lenta, e no seu não é?

Por que usamos Kubernetes em produção

"Leroy Merlin" é líder no mercado de varejo DIY na Rússia e Europa. Nossa empresa conta com mais de cem desenvolvedores, 33.000 funcionários internos e um grande número de pessoas que visitam as lojas e o site. Para fazer todos eles felizes, decidimos adotar abordagens padrão na indústria. Desenvolver novos aplicativos usando arquitetura de microsserviços; usar contêineres para isolar ambientes e garantir a entrega correta; e usar Kubernetes para orquestração. O custo do uso de orquestradores está caindo rapidamente: há cada vez mais engenheiros no mercado dominando essa tecnologia, e surgem provedores que oferecem Kubernetes como serviço.

Tudo o que Kubernetes faz, é claro, pode ser feito de outras maneiras, como utilizando scripts com Jenkins e docker-compose, mas por que complicar a vida se existe uma solução pronta e confiável? Portanto, chegamos ao Kubernetes e já o utilizamos em produção há um ano. Agora temos vinte e quatro clusters Kubernetes, o mais antigo deles tem mais de um ano e abriga cerca de duzentos pods.

A maldição do grande número de arquivos YAML no Kubernetes

Para iniciar um microsserviço no Kubernetes, criaremos pelo menos cinco arquivos YAML: para Deployment, Service, Ingress, ConfigMap e Secrets — e os enviaremos para o cluster. Para o próximo aplicativo, escreveremos o mesmo conjunto de arquivos YAML, para o terceiro mais um e assim por diante. Multiplicando o número de documentos pelo número de ambientes, já obtemos centenas de arquivos, sem contar os ambientes dinâmicos.

Dispositivo Helm e suas armadilhas
Adam Reese, mantenedor principal do Helm, introduziu o conceito de "Ciclo de desenvolvimento no Kubernetes", que se parece com isto:

  1. Copiar YAML — copiar arquivo YAML.
  2. Colar YAML — colá-lo.
  3. Corrigir recuos — ajustar os recuos.
  4. Repetir — repetir novamente.

Essa abordagem funciona, mas envolve copiar arquivos YAML muitas vezes. Para alterar esse ciclo, foi criado o Helm.

O que é Helm

Em primeiro lugar, o Helm é — gerenciador de pacotes, ajudando a encontrar e instalar os programas necessários. Para instalar, por exemplo, o MongoDB, não é preciso acessar o site oficial e baixar os binários, basta executar o comando helm install stable/mongodb.

Em segundo lugar, o Helm é um template engine, que parametriza arquivos. Vamos voltar à situação dos arquivos YAML no Kubernetes. É mais fácil escrever o mesmo arquivo YAML, adicionar alguns placeholders, onde o Helm irá inserir os valores. Ou seja, em vez de um grande conjunto de YAMLs, haverá um conjunto de templates, onde os valores necessários serão inseridos no momento certo.

Em terceiro lugar, o Helm é um especialista em implantação. Com ele, é possível instalar, reverter e atualizar aplicativos. Vamos entender como fazer isso.

Dispositivo Helm e suas armadilhas

Como usar o Helm para implantar seus próprios aplicativos

Vamos instalar o cliente Helm no computador, seguindo a documentação oficial documentação. Em seguida, criaremos um conjunto de arquivos YAML. Em vez de especificar valores concretos, deixaremos placeholders, que no futuro o Helm preencherá com as informações. Esse conjunto de arquivos é chamado de Helm chart. É possível enviá-lo para o cliente de linha de comando Helm de três maneiras:

  • especificar a pasta com os templates;
  • empacotar em um arquivo .tar e indicar isso;
  • colocar o template em um repositório remoto e adicionar o link do repositório no cliente do Helm.

Também precisamos de um arquivo com os valores — values.yaml. Os dados desse arquivo serão inseridos no template. Vamos criá-lo também.

Dispositivo Helm e suas armadilhas
Na segunda versão do Helm, há um aplicativo de servidor adicional — Tiller. Ele fica fora do Kubernetes e aguarda solicitações do cliente Helm, e quando acionado, insere os valores necessários no template e envia para o Kubernetes.

Dispositivo Helm e suas armadilhas
O Helm 3 é mais simples: em vez de processar templates no servidor, as informações agora são processadas completamente pelo lado do cliente Helm e enviadas diretamente para a API do Kubernetes. Essa simplificação aumenta a segurança do cluster e facilita o processo de lançamento.

Como tudo isso funciona

Executamos o comando helm install. Vamos especificar o nome da versão do aplicativo, fornecer o caminho para o values.yaml. No final, indicamos o repositório onde o chart está localizado e o nome do chart. Neste exemplo, isso é "lmru" e "bestchart", respectivamente.

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

A execução do comando só é possível uma vez, em execuções subsequentes, em vez de install deveria usar upgrade. Para simplificar, podemos executar o comando upgrade com uma chave adicional --install. Na primeira execução, o Helm enviará um comando para instalar a versão, e posteriormente a atualizará.

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

Armadilhas na implantação de novas versões do aplicativo com Helm

Neste momento da história, estou jogando com a plateia no 'Quem quer ser um milionário', e estamos descobrindo como fazer o Helm atualizar a versão do aplicativo. Assistir vídeo.

Quando estudei o funcionamento do Helm, fiquei surpreso com o comportamento estranho ao tentar atualizar versões de aplicativos em execução. O código do aplicativo foi atualizado, carreguei uma nova imagem no docker registry, enviei o comando para implantação – e nada aconteceu. Abaixo, algumas tentativas não tão bem-sucedidas para atualizar aplicativos. Estudando cada uma delas em detalhes, você começa a entender o funcionamento interno da ferramenta e os motivos desse comportamento não tão óbvio.

Método 1. Não alterar informações desde a última execução

Como diz site oficial Helm, 'os charts do Kubernetes podem ser grandes e complexos, portanto, o Helm tenta não modificar nada desnecessariamente'. Portanto, se você atualizar a versão mais recente da imagem do aplicativo no docker registry e executar o comando helm upgrade, nada irá acontecer. O Helm irá considerar que nada mudou e não será necessário enviar um comando ao Kubernetes para atualizar o aplicativo.

Aqui e adiante, a tag latest é mostrada apenas como um exemplo. Ao especificar essa tag, o Kubernetes fará o download da imagem do docker registry todas as vezes, independentemente do parâmetro imagePullPolicy. O uso de latest em produção não é recomendado e pode causar efeitos colaterais.

Método 2. Atualizar o LABEL na imagem

Conforme mencionado na mesma documentação, 'o Helm atualizará o aplicativo somente se ele mudou desde o último release'. Uma opção lógica para isso seria atualizar a etiqueta LABEL na própria imagem docker. No entanto, o Helm não olha para as imagens de aplicativos e não tem ideia de quaisquer mudanças nelas. Portanto, ao atualizar labels na imagem, o Helm não ficará ciente e o comando de atualização do aplicativo no Kubernetes não será enviado.

Método 3. Usar a chave --force

Dispositivo Helm e suas armadilhas
Vamos consultar os manuais e procurar pela chave necessária. A que mais se encaixa é a chave --force. Apesar do nome sugestivo, o comportamento é diferente do esperado. Em vez de forçar a atualização do aplicativo, seu verdadeiro objetivo é restaurar uma versão do release que está com status FAILED. Se não usar essa chave, será necessário executar os comandos sequencialmente. helm delete && helm install --replace. Em vez disso, é sugerido usar a chave --force, que automatiza a execução sequencial desses comandos. Mais informações neste pull request. Para que o Helm realmente atualize a versão do aplicativo, infelizmente, essa chave não será apropriada.

Método 4. Alterar labels diretamente no Kubernetes

Dispositivo Helm e suas armadilhas
Atualizar label diretamente no cluster usando o comando kubectl edit — é uma má ideia. Essa ação levará a uma inconsistência entre as informações do aplicativo em execução e o que foi inicialmente enviado para o deploy. O comportamento do Helm durante o deploy nesse caso é diferente de sua versão: o Helm 2 não fará nada, enquanto o Helm 3 implantará uma nova versão do aplicativo. Para entender a razão, é necessário compreender como o Helm funciona.

Como funciona o Helm

Para determinar se o aplicativo mudou desde o último release, o Helm pode se basear em:

  • aplicativo em funcionamento no Kubernetes;
  • novo values.yaml e chart atual;
  • informação interna do Helm sobre os releases.

Para os curiosos: onde o Helm armazena informações internas sobre os releases?Ao executar o comando helm history, obteremos todas as informações sobre versões instaladas através do Helm.

Dispositivo Helm e suas armadilhas
Há também informações detalhadas sobre os templates e valores enviados. Podemos solicitá-las:

Dispositivo Helm e suas armadilhas
Na segunda versão do Helm, essas informações estão no mesmo namespace onde o Tiller está em execução (por padrão — kube-system), em um ConfigMap marcado com o rótulo "OWNER=TILLER":

Dispositivo Helm e suas armadilhas
Com o surgimento da terceira versão do Helm, as informações foram transferidas para secrets, mas no mesmo namespace onde o aplicativo está em execução. Isso tornou possível executar simultaneamente vários aplicativos em diferentes namespaces com o mesmo nome de release. Na segunda versão, isso era uma grande dor de cabeça, pois os namespaces são isolados, mas podem influenciar uns aos outros.

Dispositivo Helm e suas armadilhas

No Helm 2, ao tentar entender se é necessária uma atualização, são usados apenas duas fontes de informações: o que lhe foi fornecido atualmente e a informação interna sobre os releases, que está no ConfigMap.

Dispositivo Helm e suas armadilhas
O Helm 3 utiliza a estratégia de mesclagem em três caminhos: além das informações existentes, ele considera também o aplicativo que está rodando no Kubernetes.

Dispositivo Helm e suas armadilhas
Por essa razão, a versão antiga do Helm não fará nada, pois não leva em conta as informações do aplicativo no cluster, enquanto o Helm 3 receberá as mudanças e implantará o novo aplicativo.

Método 5. Usar a chave —recreate-pods

Com a chave --recreate-pods é possível atingir o que originalmente se pretendia conseguir com a chave --force. Os contêineres serão reiniciados e, conforme a política imagePullPolicy: Always para a tag latest (conforme mencionado na nota acima), o Kubernetes fará o download e iniciará a nova versão da imagem. Isso não será feito da melhor maneira: sem considerar o StrategyType do deployment, desligará abruptamente todas as instâncias antigas do aplicativo e iniciará novas. Durante o reinício, o sistema não funcionará, os usuários sentirão os efeitos.

No próprio Kubernetes, um problema similar também existia por muito tempo. E agora, quatro anos após a sua descoberta, Problema, o problema foi corrigido, e a partir da versão 1.15 do Kubernetes, surge a possibilidade de rolling-restart dos pods.

O Helm simplesmente desliga todos os aplicativos e inicia novos contêineres lado a lado. Isso não pode ser feito em produção para evitar a inatividade do aplicativo. Isso é necessário apenas para fins de desenvolvimento e pode ser executado apenas em ambientes de estágio.

Como atualizar a versão do aplicativo usando o Helm?

Vamos alterar os valores enviados ao Helm. Normalmente, esses são os valores que substituem a tag da imagem. No caso de latest, comumente usado para ambientes não produtivos, a informação que pode ser alterada é a anotação, que é inútil para o próprio Kubernetes, mas servirá como um sinal para o Helm de que o aplicativo precisa ser atualizado. Opções para preenchimento do valor da anotação:

  1. Valor aleatório usando a função padrão — {{ randAlphaNum 6 }}.
    Há um detalhe: após cada deploy utilizando um chart com essa variável, o valor da anotação será único, e o Helm acreditará que houve alterações. Assim, estaremos sempre reiniciando o aplicativo, mesmo que não tenhamos mudado sua versão. Isso não é crítico, pois não haverá inatividade, mas ainda assim é inconveniente.
  2. Inserir a data e hora atuais — {{ .Release.Date }}.
    A opção é semelhante ao valor aleatório, mas com uma variável sempre única.
  3. Uma maneira mais correta é usar somas de verificação. Esta é a imagem SHA ou o SHA do último commit no git — {{ .Values.sha }}.
    Elas devem ser calculadas e enviadas ao cliente Helm no lado chamador, por exemplo no Jenkins. Se a aplicação mudar, a soma de verificação também mudará. Portanto, o Helm atualizará a aplicação apenas quando necessário.

Resumindo nossas tentativas

  • O Helm faz alterações da maneira menos invasiva, portanto qualquer mudança no nível da imagem da aplicação no Docker Registry não resultará em uma atualização: após a execução do comando, nada acontecerá.
  • Chave --force é usado para recuperar releases problemáticos e não está relacionado a atualizações forçadas.
  • Chave --recreate-pods atualizará o aplicativo forçadamente, mas o fará de maneira brusca: desligará todos os contêineres abruptamente. Isso prejudicará os usuários, e não é aconselhável fazer isso em produção.
  • Fazer alterações diretamente no cluster Kubernetes usando o comando kubectl edit não é recomendado: isso quebrará a consistência e o comportamento variará dependendo da versão do Helm.
  • Com o lançamento da nova versão do Helm, surgiram muitas nuances. As Issues no repositório do Helm estão descritas de forma clara e ajudarão a entender os detalhes.
  • Adicionar uma anotação modificável ao chart tornará mais flexível. Isso permitirá implantar a aplicação corretamente, sem inatividade.

Uma ideia do tipo "paz mundial", aplicável em todas as áreas da vida: leia as instruções antes de usar, não depois. Apenas sabendo de todas as informações, será possível construir sistemas confiáveis e fazer os usuários felizes.

Outros links sobre o tema:

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

Esta apresentação foi feita pela primeira vez na @Kubernetes Conference by Mail.ru Cloud Solutions. Veja vídeo outras apresentações e inscreva-se para receber atualizações de eventos no Telegram Em torno do Kubernetes no Mail.ru Group.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster