Comparação adequada de aplicação, substituição e patch do Kubernetes

O Kubernetes possui diversas opções para atualizar recursos: aplicar, editar, corrigir e substituir. Há confusão sobre o que cada um faz e quando usá-los. Vamos descobrir.

Comparação adequada de aplicação, substituição e patch do Kubernetes

Se pesquisar no Google a frase "kubernetes apply vs replace" está localizada responder ao StackOverflow, o que não está correto. Ao pesquisar "kubernetes apply vs patch" o primeiro link é a documentação para kubectl patch, que não inclui comparação apply и patch. Este artigo examinará as diferentes opções, bem como o uso adequado de cada uma delas.

Durante o ciclo de vida de um recurso Kubernetes (serviço, implantação, entrada, etc.), às vezes é necessário alterar, adicionar ou remover algumas propriedades deste recurso. Por exemplo, adicione uma nota, aumente ou diminua o número de réplicas.

CLI do Kubernetes

Se você já trabalha com clusters Kubernetes por meio da CLI, já está familiarizado com apply и edit. Equipe apply lê a especificação do recurso do arquivo e faz um "upsert" para o cluster Kubernetes, ou seja, cria o recurso se ele não existir e o atualiza se existir. Equipe edit lê um recurso por meio da API e, em seguida, grava a especificação do recurso em um arquivo local, que é então aberto em um editor de texto. Depois de editar e salvar o arquivo, kubectl enviará as alterações feitas de volta por meio da API, que aplicará cuidadosamente essas alterações ao recurso.

Nem todo mundo conhece os comandos patch и replace. Equipe patch permite alterar parte de uma especificação de recurso, fornecendo apenas a parte alterada na linha de comando. Equipe replace funciona da mesma forma que edit, mas tudo precisa ser feito manualmente: você precisa baixar a versão atual da especificação do recurso, por exemplo, usando kubectl get -o yaml, edite-o e use replace para atualizar um recurso de acordo com uma especificação alterada. Equipe replace não funcionará se ocorrer alguma alteração entre a leitura e a substituição do recurso.

API do Kubernetes

Você provavelmente está familiarizado com os métodos CoreV1().Pods().Update(), replaceNamespacedService ou patch_namespaced_deployment, se você trabalha com clusters via biblioteca cliente para API Kubernetes usando alguma linguagem de programação. A biblioteca lida com esses métodos por meio de solicitações HTTP usando os métodos PUT и PATCH. Neste caso, update и replace usar PUTE patch, por mais trivial que seja, usa PATCH.

Deve notar-se que kubectl também funciona com clusters via API. Em outras palavras, kubectlé um wrapper no topo da biblioteca cliente para a linguagem Go, que fornece amplamente a capacidade de fornecer subcomandos em um formato mais compacto e legível, além dos recursos padrão da API. Por exemplo, como você já deve ter notado, o método apply não foi mencionado acima no parágrafo anterior. Atualmente (maio de 2020, Aproximadamente. tradutor) toda lógica kubectl apply, ou seja criar recursos inexistentes e atualizar os existentes, funciona inteiramente no lado do código kubectl. Esforços estão sendo feitos na transferência lógica apply para o lado da API, mas ainda está em beta. Escreverei com mais detalhes abaixo.

Patch por padrão

Melhor usado patch, se desejar atualizar o recurso. É assim que ambas as bibliotecas cliente funcionam na API Kubernetes e kubectl (não é surpreendente, já que é um wrapper para a biblioteca cliente, Aproximadamente. tradutor).

Trabalhe estrategicamente

Todas as equipes kubectl apply, edit и patch use o método PATCH em solicitações HTTP para atualizar um recurso existente. Se você se aprofundar na implementação dos comandos com mais detalhes, todos eles usarão a abordagem patch de mesclagem estratégica para atualizar recursos, embora o comando patch pode usar outras abordagens (mais sobre isso abaixo). A abordagem de patch de fusão estratégica tenta "acertar" mesclando a especificação fornecida com a especificação existente. Mais especificamente, ele tenta combinar objetos e arrays, o que significa que as alterações tendem a ser aditivas. Por exemplo, executando o comando patch com uma nova variável de ambiente na especificação do contêiner do pod, faz com que essa variável de ambiente seja adicionada às variáveis ​​de ambiente existentes em vez de substituí-las. Para remover usando essa abordagem, você deve forçar o valor do parâmetro como nulo na especificação fornecida. Qual das equipes kubectl É melhor usar para atualização?

Se você criar e gerenciar seus recursos usando kubectl apply, na hora de atualizar é melhor usar sempre kubectl applyPara kubectl poderia gerenciar a configuração e rastrear adequadamente as alterações solicitadas de aplicativo para aplicativo. Vantagem sempre use apply é que ele acompanha uma especificação aplicada anteriormente, permitindo saber quando as propriedades da especificação e os elementos da matriz são explicitamente removidos. Isso permite que você use apply para remover propriedades e elementos do array, enquanto uma mesclagem estratégica normal não funcionará. Equipes edit и patch não atualize notas que kubectl apply usa para rastrear suas alterações, portanto, quaisquer alterações rastreadas e feitas por meio da API Kubernetes, mas feitas por meio de comandos edit и patch, invisível para comandos subsequentes applyIsto é, apply não os remove mesmo que não apareçam na especificação de entrada para apply (A documentação diz que edit и patch fazer atualizações nas notas usadas apply, mas na prática - não).

Se você não usar o comando apply, pode ser usado como editE patch, escolhendo o comando que melhor se adapta à alteração que está sendo realizada. Ao adicionar e alterar propriedades da BOM, ambas as abordagens são praticamente as mesmas. Ao excluir propriedades de especificação ou elementos de matriz edit se comporta como um lançamento único apply, incluindo o acompanhamento de como era a especificação antes e depois de ser editada, para que você possa remover explicitamente propriedades e elementos de matriz de um recurso. Você precisa definir explicitamente o valor da propriedade como nulo na especificação para patchpara removê-lo do recurso. A remoção de um elemento de array usando patch de mesclagem estratégica é mais complexa porque requer o uso de diretivas de mesclagem. Veja outras abordagens de atualização abaixo para alternativas mais viáveis.

Para implementar métodos de atualização na biblioteca cliente que se comportem de forma semelhante aos comandos acima kubectl, deve ser definido nas solicitações content-type в application/strategic-merge-patch+json. Se você deseja remover propriedades em uma especificação, você precisa definir explicitamente seus valores como nulos de maneira semelhante kubectl patch. Se precisar remover elementos do array, você deve incluir diretivas de mesclagem na especificação de atualização ou usar uma abordagem diferente para atualizações.

Outras abordagens para atualizações

O Kubernetes oferece suporte a duas outras abordagens de atualização: Patch de mesclagem JSON и Correção JSON. A abordagem de patch de mesclagem JSON usa uma especificação parcial do Kubernetes como entrada e oferece suporte à mesclagem de objetos semelhante à abordagem de patch de mesclagem estratégica. A diferença entre os dois é que ele suporta apenas a substituição de array, incluindo o array de contêiner na especificação do pod. Isso significa que, ao usar um patch de mesclagem JSON, você precisa fornecer especificações completas para todos os contêineres, caso alguma propriedade de qualquer contêiner seja alterada. Portanto, esta abordagem é útil para remover elementos de uma matriz em uma lista técnica. Na linha de comando você pode selecionar patch de mesclagem JSON usando kubectl patch --type=merge. Ao trabalhar com a API Kubernetes, você deve usar o método request PATCH e instalação content-type в application/merge-patch+json.

A abordagem de patch JSON, em vez de fornecer uma especificação parcial de um recurso, fornece as alterações que você deseja fazer no recurso como uma matriz, na qual cada elemento da matriz representa uma descrição da alteração que está sendo feita no recurso. Esta abordagem é uma forma mais flexível e poderosa de expressar as alterações que estão sendo feitas, mas ao custo de listar as alterações feitas em um formato separado, não-Kubernetes, em vez de enviar uma especificação parcial de recursos. EM kubectl você pode selecionar o patch JSON usando kubectl patch --type=json. Ao usar a API Kubernetes, esta abordagem funciona usando o método de solicitação PATCH e instalação content-type в application/json-patch+json.

Precisamos de confiança - use substituir

Em alguns casos, você precisa ter certeza de que nenhuma alteração será feita em um recurso entre o momento em que o recurso é lido e quando ele é atualizado. Em outras palavras, você deve certificar-se de que todas as alterações serão atômico. Neste caso, para atualizar recursos você deve usar replace. Por exemplo, se você tiver um ConfigMap com um contador atualizado por diversas fontes, certifique-se de que duas fontes não atualizem o contador ao mesmo tempo, fazendo com que a atualização seja perdida. Para demonstrar, imagine uma sequência de eventos usando a abordagem patch:

  • A e B obtêm o estado atual do recurso da API
  • Cada um atualiza localmente a especificação incrementando o contador em um e também adicionando "A" ou "B" respectivamente à nota "atualizado por"
  • E atualiza o recurso um pouco mais rápido
  • B atualiza o recurso

Como resultado, a atualização A é perdida. Última operação patch vence, o contador é incrementado em um em vez de dois, e o valor da nota "atualizado por" termina com "B" e não contém "A". Vamos comparar o que foi dito acima com o que acontece quando as atualizações são feitas usando a abordagem replace:

  • A e B obtêm o estado atual do recurso da API
  • Cada um atualiza localmente a especificação incrementando o contador em um e também adicionando "A" ou "B" respectivamente à nota "atualizado por"
  • E atualiza o recurso um pouco mais rápido
  • B tenta atualizar o recurso, mas a atualização é rejeitada pela API porque a versão do recurso está na especificação replace não corresponde à versão atual do recurso no Kubernetes porque a versão do recurso foi aumentada pela operação de substituição de A.

No caso acima, B terá que buscar novamente o recurso, fazer alterações no novo estado e tentar novamente replace. Isso fará com que o contador seja incrementado em dois e a nota “atualizado por” inclua “AB” no final.

O exemplo acima implica que ao executar replace Todo o recurso é completamente substituído. Especificação usada para replace, não deve ser parcial ou em partes como em apply, mas completo, incluindo a adição resourceVersion nos metadados de especificação. Se você não ativou resourceVersion ou a versão fornecida não for atual, a substituição será rejeitada. Portanto, a melhor abordagem a ser usada é replace – leia o recurso, atualize-o e substitua-o imediatamente. Usando kubectl, pode ser assim:

$ kubectl get deployment my-deployment -o json 
    | jq '.spec.template.spec.containers[0].env[1].value = "new value"' 
    | kubectl replace -f -

Vale ressaltar que os dois comandos a seguir, executados sequencialmente, serão executados com sucesso, pois deployment.yaml não contém propriedade .metadata.resourceVersion

$ kubectl create -f deployment.yaml
$ kubectl replace -f deployment.yaml

Isso parece contradizer o que foi dito acima, ou seja, "adicionando resourceVersion nos metadados de especificação." É errado dizer isso? Não, não é, porque se kubectl percebe que você não especificou resourceVersion, ele irá lê-lo do recurso e adicioná-lo à especificação que você especificou, e só então executá-lo replace. Como isso é potencialmente perigoso se você confiar na atomicidade, a mágica funciona inteiramente paralelamente kubectl, você não deve confiar nele ao usar bibliotecas cliente que funcionam com a API. Neste caso você terá que ler a especificação do recurso atual, atualizá-la e então executar PUT solicitar.

Você não pode fazer um patch – nós fazemos uma atualização

Às vezes você precisa fazer algumas alterações que não podem ser tratadas pela API. Nestes casos, você pode forçar a substituição do recurso excluindo-o e recriando-o. Isso é feito usando kubectl replace --force. A execução do comando remove imediatamente os recursos e os recria a partir da especificação fornecida. Não há manipulador de "substituição forçada" na API e, para fazer isso por meio da API, você precisa realizar duas operações. Primeiro você precisa excluir o recurso configurando para ele gracePeriodSeconds para zero (0) e propagationPolicy em “Background” e depois recrie este recurso com a especificação desejada.

Aviso: Esta abordagem é potencialmente perigosa e pode levar a um estado indefinido.

Aplicar no lado do servidor

Conforme mencionado acima, os desenvolvedores do Kubernetes estão trabalhando na implementação da lógica apply de kubectl na API Kubernetes. Lógicas apply disponível no Kubernetes 1.18 via kubectl apply --server-side ou através da API usando o método PATCH с content-type application/apply-patch+YAML.

Nota: JSON também é YAML válido, então você pode enviar a especificação como JSON mesmo se content-type vontade application/apply-patch+yaml.

Além dessa lógica kubectl fica disponível para todos via API, apply no lado do servidor, controla quem é o responsável pelos campos da especificação, permitindo assim acesso múltiplo seguro para sua edição sem conflitos. Em outras palavras, se apply no lado do servidor se tornará mais difundido, uma interface universal segura de gerenciamento de recursos aparecerá para diferentes clientes, por exemplo, kubectl, Pulumi ou Terraform, GitOps, bem como scripts auto-escritos usando bibliotecas de clientes.

Resultados de

Espero que esta breve visão geral das diferentes maneiras de atualizar recursos em clusters tenha sido útil para você. É bom saber que não se trata apenas de aplicar versus substituir; é possível atualizar um recurso usando aplicar, editar, corrigir ou substituir. Afinal, em princípio, cada abordagem tem sua área de aplicação. Para mudanças atômicas, substituir é preferível; caso contrário, você deve usar o patch de mesclagem estratégica via apply. No mínimo, espero que você entenda que não pode confiar no Google ou no StackOerflow ao pesquisar "kubernetes apply vs replace". Pelo menos até que este artigo substitua a resposta atual.

Comparação adequada de aplicação, substituição e patch do Kubernetes

Fonte: habr.com

Adicionar um comentário