Um olhar sóbrio para o Helm 2: "Isso é o que é ..."

Como qualquer outra solução, Helm - o gerenciador de pacotes do Kubernetes - possui prós, contras e escopo. Portanto, ao usá-lo, você deve avaliar corretamente suas expectativas ...


Usamos Helm em nosso arsenal de ferramentas de rolamento contínuo. No momento da redação deste artigo, existem mais de mil aplicativos em nossos clusters e cerca de 4000 instalações desses aplicativos em várias variações. Periodicamente, encontramos problemas, mas, em geral, estamos satisfeitos com a solução, não temos tempo de inatividade nem perda de dados.

O principal motivo para escrever este artigo é fornecer ao usuário uma avaliação objetiva dos principais problemas do Leme 2 sem conclusões definitivas, bem como o desejo de compartilhar experiências e nossas soluções.

[ERRO] Após o lançamento, o estado dos recursos de liberação no cluster não corresponde ao gráfico Helm descrito


Ao trabalhar, o Helm não leva em consideração o estado dos recursos de liberação no cluster. Ao reinstalar, o resultado é determinado apenas pelas configurações atuais e salvas. Portanto, o estado do recurso no cluster e no registro Helm é diferente e o Helm não leva isso em consideração.

Considere como esse problema se manifesta:

  1. O modelo de recurso no gráfico corresponde ao estado X.
  2. O usuário instala o gráfico (o Tiller salva o estado do recurso X).
  3. Em seguida, o usuário altera manualmente o recurso no cluster (o estado muda de X para Y).
  4. Sem fazer nenhuma alteração, ele executa a helm upgrade ... E o recurso ainda está no estado Y, embora o usuário espere X.

E isso não é tudo. Em algum momento, o usuário altera o modelo de recurso no gráfico (novo estado W) - então temos dois cenários após a helm upgrade :

  • A aplicação do patch XW está caindo.
  • Depois de aplicar o patch, o recurso entra no estado Z, que não corresponde ao desejado.

Para evitar esse problema, propõe-se organizar o trabalho com liberações da seguinte maneira: ninguém deve alterar os recursos manualmente , o Helm é a única ferramenta para trabalhar com os recursos da liberação. Idealmente, as alterações de gráfico são versionadas no repositório Git e aplicadas exclusivamente dentro do CD.

Se essa opção não for adequada, você poderá monitorar a sincronização dos estados do recurso de liberação. A sincronização manual pode ser assim:

  1. Nós descobrimos o status dos recursos de liberação através do helm get .
  2. Descubra o status dos recursos no Kubernetes via kubectl get .
  3. Se os recursos forem diferentes, sincronizamos o Helm com o Kubernetes:
    1. Crie uma ramificação separada.
    2. Atualizando manifestos do gráfico. Os modelos devem corresponder aos estados de recurso no Kubernetes.
    3. Realizamos a implantação. Sincronizamos o estado no registro e cluster do Helm.
    4. Depois disso, a ramificação pode ser excluída e continuar o trabalho regular.

Ao aplicar patches usando o kubectl apply , a chamada mesclagem de 3 vias é executada, ou seja, o estado real do recurso atualizado é levado em consideração. Você pode ver o código do algoritmo aqui e ler sobre ele aqui .

No momento da redação deste artigo, os desenvolvedores do Helm estão procurando maneiras de implementar a combinação de três vias no Helm 3. Com o Helm 2, as coisas não são tão boas: a fusão de 3 vias não está planejada para ser implementada, mas existe um PR para corrigir a maneira como os recursos são criados - você pode descobrir detalhes ou até participar como parte da questão relevante .

[BUG] Erro: nenhum RECURSO com o nome NAME encontrado


O problema se manifesta se novos recursos forem criados com êxito quando a distribuição for repetida e a distribuição em si falhar. Novos recursos significam aqueles que não estavam na última instalação do gráfico.

Se a distribuição falhar, a versão será salva no registro marcado como FAILED e, durante a instalação, o Helm dependerá do estado da última versão DEPLOYED , que nesse caso não sabe nada sobre novos recursos. Como resultado, o Helm tenta recriar esses recursos e falha com o erro "nenhum RECURSO com o nome NAME encontrado" (o erro diz o contrário, mas esse é o problema). Parte do problema é que o Helm não leva em consideração o estado dos recursos de liberação no cluster ao criar o patch, conforme descrito na seção anterior.

Por enquanto, a única solução é remover manualmente novos recursos.

Para evitar esse estado, é possível excluir automaticamente novos recursos criados na atualização / reversão atual se o comando finalmente falhar. Após uma longa discussão com os desenvolvedores no Helm, para os comandos de atualização / reversão, foi adicionada a opção --cleanup-on-fail , que ativa a limpeza automática quando a distribuição falha. Nosso PR está em discussão, buscando a melhor solução.

A partir da versão 2.13 do Helm, a opção --atomic aparece nos helm install/upgrade do helm install/upgrade , que ativam a limpeza e a reversão durante uma instalação com falha (para obter mais detalhes, consulte PR ).

[BUG] Erro: relógio fechado antes até o tempo limite


O problema pode ocorrer quando o gancho Helm é executado por muito tempo (por exemplo, durante migrações) - mesmo que os tempos limite especificados para helm install/upgrade do helm install/upgrade e spec.activeDeadlineSeconds tarefa correspondente não sejam excedidos.

Este erro é gerado pelo servidor da API Kubernetes enquanto aguarda a conclusão da tarefa de gancho. O Helm não lida com esse erro e trava imediatamente - em vez de tentar novamente a solicitação de espera.

Como solução, você pode aumentar o tempo limite no servidor api: --min-request-timeout=xxx no arquivo /etc/kubernetes/manifests/kube-apiserver.yaml .

[BUG] Erro: UPGRADE FAILED: "foo" não possui lançamentos implantados


Se a primeira versão através da helm install falhar, a helm upgrade subsequente do helm upgrade retornará um erro semelhante.

Parece que a solução é bastante simples: você precisa executar manualmente a helm delete --purge após uma falha na primeira instalação, mas esta ação manual interrompe a automação do CI / CD. Para não interromper a execução dos comandos manuais, você pode usar os recursos werf para implantar . Ao usar o werf, a versão problemática será recriada automaticamente após a reinstalação.

Além disso, começando com o Helm 2.13, nos helm install e helm upgrade --install basta especificar a opção --atomic e, após uma falha na instalação, a liberação será excluída automaticamente (consulte PR para obter detalhes).

Autorollback


O Helm não possui a opção --autorollback , que, quando --autorollback , lembrará a revisão bem-sucedida atual (será descartada se a última revisão não for bem-sucedida) e, após uma tentativa malsucedida de implantação, reverterá para a revisão salva.

Como é fundamental que o produto funcione sem interrupções, é necessário procurar soluções, a implantação deve ser previsível. Para minimizar a probabilidade de tempo de inatividade do produto, muitas vezes é usada uma abordagem com vários circuitos (por exemplo, preparação, qa e produção), que consiste na implantação sequencial nos circuitos. Com essa abordagem, a maioria dos problemas é corrigida antes de ser lançada no produtivo e, em conjunto com o autorolback, permite obter bons resultados.

Para organizar o autorollback, você pode usar o plug - in helm-monitor , que permite vincular o rollback às métricas do Prometheus. Um bom artigo que descreve essa abordagem está disponível aqui .

Para alguns de nossos projetos, uma abordagem bastante simples é usada:

  1. Antes da implantação, lembramos da revisão atual (acreditamos que, em uma situação normal, se a liberação existir, ela estará necessariamente no estado DEPLOYED):

     export _RELEASE_NAME=myrelease export _LAST_DEPLOYED_RELEASE=$(helm list -adr | \ grep $_RELEASE_NAME | grep DEPLOYED | head -n2 | awk '{print $2}') 
  2. Execute a instalação ou atualização:

     helm install/upgrade ... || export _DEPLOY_FAILED=1 
  3. Verificamos o status da implantação e fazemos reversão para o estado salvo:

     if [ "$_DEPLOY_FAILED" == "1" ] && [ "x$_LAST_DEPLOYED_RELEASE" != "x" ] ; then helm rollback $_RELEASE_NAME $_LAST_DEPLOYED_RELEASE fi 
  4. Encerramos o pipeline com um erro se a implantação não tiver êxito:

     if [ "$_DEPLOY_FAILED" == "1" ] ; then exit 1 ; fi 

Novamente, começando com o Helm versão 2.13, ao chamar o helm upgrade basta especificar a opção --atomic e depois que uma reversão de instalação com falha será executada automaticamente (consulte PR para obter detalhes).

Aguardando a disponibilidade de recursos de liberação e feedback no momento da implementação


Conforme planejado, o Helm deve monitorar a execução dos testes de disponibilidade e disponibilidade correspondentes ao usar a opção --wait :

 --wait if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout 

Esta função não funciona corretamente agora: nem todos os recursos e nem todas as versões da API são suportadas. E o processo de espera declarado em si não satisfaz nossas necessidades.

Como no kubectl wait , não há feedback rápido e não há como regular esse comportamento. Se o lançamento falhar, só o saberemos após um tempo limite . No caso de uma instalação problemática, é necessário concluir o processo de implantação o mais rápido possível, inverter o pipeline de CI / CD, reverter a liberação para a versão de trabalho e prosseguir para a depuração.

Se a versão problemática for revertida e o Helm não retornar nenhuma informação durante o processo de lançamento, o que é a depuração ?! No caso do kubectl wait você pode organizar um processo separado para exibir logs, o que exigirá nomes de recursos de liberação. Como organizar uma solução simples e funcional não está claro imediatamente. Além dos logs de pod, informações úteis podem estar contidas no processo de lançamento, eventos de recursos ...

Nosso utilitário CI / CD werf pode implantar um gráfico Helm e monitorar a disponibilidade de recursos, além de exibir informações relacionadas à implantação. Todos os dados são combinados em um único fluxo e emitidos para o log.

Essa lógica é feita em uma solução separada do kubedog . Usando o utilitário, você pode assinar um recurso e receber eventos e logs, além de aprender sobre lançamentos com falha em tempo hábil. I.e. como solução, depois de chamar helm install/upgrade sem a opção --wait , --wait pode chamar kubedog para cada recurso de release.

Nosso objetivo era criar uma ferramenta que forneça todas as informações necessárias para depuração na saída do pipeline de CI / CD. Leia mais sobre o utilitário em nosso artigo recente .

Talvez no Helm 3 algum dia uma solução semelhante apareça, mas até agora nosso problema está em estado suspenso.

Segurança ao usar o helm init por padrão


Por padrão, quando o helm init é executado, o componente do servidor é instalado no cluster com privilégios semelhantes ao superusuário, o que pode levar a consequências indesejáveis ​​quando acessado por terceiros.

Para garantir a segurança do cluster, é necessário limitar os recursos do Tiller, bem como cuidar da conexão - a segurança da rede pela qual a comunicação entre os componentes do Helm ocorre.

O primeiro pode ser alcançado através do uso do mecanismo RBAC Kubernetes padrão, que limitará as ações do leme, e o segundo - definindo SSL. Leia mais na documentação do Helm: Protegendo sua instalação do Helm .

Acredita-se que a presença do componente do servidor - Tiller - seja um grave erro arquitetônico , literalmente um recurso externo com direitos de superusuário no ecossistema Kubernetes. Em parte, concordamos: a implementação é imperfeita, mas vamos dar uma olhada nisso do outro lado . Se você interromper o processo de implantação e matar o cliente Helm, o sistema não permanecerá em um estado indefinido, ou seja, O Tiller trará o status da liberação para válido. Também é necessário entender que, apesar do Tiller ser abandonado no Helm 3, essas funções de alguma forma serão executadas pelo controlador CRD.

Marciano Go Templates


Os modelos de go têm um grande limite de entrada, mas a tecnologia não tem limitações nos recursos e problemas com o DRY. Os princípios básicos, sintaxe, funções e operadores são discutidos em nosso artigo anterior da série Helm.

Falta de segredos fora da caixa


É conveniente armazenar e manter modelos de código de aplicativo, infraestrutura e distribuição quando eles estão localizados em um único local. E segredos não são excepção.

O Helm não suporta segredos prontos para uso, no entanto, o plug - in helm-secrets está disponível, que é essencialmente uma camada entre sops , o gerenciador de segredos do Mozilla e o Helm.

Ao trabalhar com segredos, usamos nossa própria solução implementada no werf ( documentação sobre segredos ). Dos recursos:

  • Facilidade de implementação.
  • Mantendo um segredo em um arquivo, não apenas no YAML. Conveniente ao armazenar certificados, chaves.
  • Regeneração de segredos com uma nova chave.
  • Lançamento sem uma chave secreta (ao usar o werf). Pode ser útil para os casos em que o desenvolvedor não possui essa chave secreta, mas é necessário iniciar uma implantação em um circuito local ou de teste.

Conclusão


O leme 2 está posicionado como um produto estável, mas ao mesmo tempo há muitos bugs que ficam no limbo (alguns deles duram vários anos!). Em vez de soluções, ou pelo menos patches, todos os esforços são dedicados ao desenvolvimento do Helm 3.

Apesar de o MR e o problema poderem demorar por meses ( aqui está um exemplo de como adicionamos uma before-hook-creation policy de ganchos por vários meses), você ainda pode participar do desenvolvimento do projeto. Toda quinta-feira, ocorre um comício de meia hora de desenvolvedores do Helm, onde você pode aprender sobre as prioridades e orientações atuais da equipe, fazer perguntas e forçar suas próprias práticas recomendadas. Sobre mete e outros canais de comunicação está escrito em detalhes aqui .

A opção de usar ou não o Helm depende de você, é claro. Hoje nós mesmos aderimos a uma posição que, apesar das deficiências, o Helm é uma solução aceitável para a implantação e é útil para toda a comunidade participar do seu desenvolvimento.

PS


Leia também em nosso blog:

Source: https://habr.com/ru/post/pt438814/


All Articles