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.
Se 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 PUT
и PATCH
. Neste caso, update
и replace
usar PUT
E 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 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
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 apply
Para 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 apply
Isto é, 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 edit
E 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 patch
para 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: 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
vontadeapplication/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.
Fonte: habr.com