Comparación adecuada de aplicación, substitución e parche de Kubernetes

Kubernetes ten varias opcións para actualizar recursos: aplicar, editar, parchear e substituír. Hai confusión sobre o que fai cada un e cando usalos. Imos descubrir.

Comparación adecuada de aplicación, substitución e parche de Kubernetes

Se buscar en Google localízase a frase "kubernetes apply vs replace". responder a StackOverflow, que non é correcto. Ao buscar "kubernetes apply vs patch" a primeira ligazón é a documentación para kubectl patch, que non inclúe comparación apply и patch. Neste artigo analizaranse as diferentes opcións, así como o uso adecuado de cada unha.

Durante o ciclo de vida dun recurso de Kubernetes (servizo, implantación, entrada, etc.), ás veces é necesario cambiar, engadir ou eliminar algunhas propiedades deste recurso. Por exemplo, engadir unha nota, aumentar ou diminuír o número de réplicas.

CLI de Kubernetes

Se xa estás a traballar con clústeres de Kubernetes a través da CLI, xa estás familiarizado apply и edit. Equipo apply le a especificación do recurso do ficheiro e fai un "upsert" ao clúster de Kubernetes, é dicir. crea o recurso se non existe e actualízao se existe. Equipo edit le un recurso a través da API, despois escribe a especificación do recurso nun ficheiro local, que se abre nun editor de texto. Despois de editar e gardar o ficheiro, kubectl enviará os cambios feitos de volta a través da API, que aplicará coidadosamente estes cambios ao recurso.

Non todos coñecen os comandos patch и replace. Equipo patch permítelle cambiar parte da especificación dun recurso, proporcionando só a parte modificada na liña de comandos. Equipo replace funciona igual que edit, pero todo hai que facer manualmente: cómpre descargar a versión actual da especificación do recurso, por exemplo, usando kubectl get -o yaml, edítao e utilízao replace para actualizar un recurso segundo unha especificación modificada. Equipo replace non funcionará se se produciu algún cambio entre a lectura e a substitución do recurso.

API de Kubernetes

Probablemente estea familiarizado cos métodos CoreV1().Pods().Update(), replaceNamespacedService ou patch_namespaced_deployment, se traballas con clusters mediante biblioteca cliente para a API de Kubernetes utilizando algunha linguaxe de programación. A biblioteca manexa estes métodos mediante solicitudes HTTP mediante os métodos PUT и PATCH... Onde update и replace usar PUTE patch, por trivial que sexa, usa PATCH.

Debe notarse que kubectl tamén funciona con clusters a través da API. Noutras palabras, kubectlé un envoltorio na parte superior da biblioteca do cliente para a linguaxe Go, que ofrece en gran parte a capacidade de proporcionar subcomandos nunha forma máis compacta e lexible ademais das capacidades estándar da API. Por exemplo, como xa tedes contado, o método apply non foi mencionado anteriormente no parágrafo anterior. Actualmente (maio de 2020, aprox. tradutor) toda lóxica kubectl apply, é dicir. a creación de recursos inexistentes e a actualización dos existentes, funciona totalmente no lado do código kubectl. Estase facendo esforzos sobre transferencia lóxica apply ao lado da API, pero aínda está en versión beta. Vou escribir con máis detalle a continuación.

Parche por defecto

Mellor usado patch, se queres actualizar o recurso. Así funcionan ambas bibliotecas de clientes enriba da API de Kubernetes e kubectl (non é sorprendente, xa que é un envoltorio para a biblioteca do cliente, aprox. tradutor).

Traballar estratexicamente

Todos os equipos kubectl apply, edit и patch use o método PATCH en solicitudes HTTP para actualizar un recurso existente. Se afondas na implementación de comandos con máis detalle, todos usan o enfoque parche de combinación estratéxica para actualizar recursos, aínda que o comando patch pode utilizar outros enfoques (máis sobre isto a continuación). O enfoque de parcheo de combinación estratéxica tenta "facelo ben" fusionando a especificación subministrada coa especificación existente. Máis concretamente, tenta combinar obxectos e matrices, o que significa que os cambios tenden a ser aditivos. Por exemplo, executando o comando patch cunha nova variable de ambiente na especificación do contenedor do pod, fai que esa variable de ambiente se engada ás variables de ambiente existentes en lugar de sobreescribilas. Para eliminar usando este enfoque, debes forzar o valor do parámetro a nulo na especificación proporcionada. Cal dos equipos kubectl É mellor usalo para actualizar?

Se creas e xestionas os teus recursos usando kubectl apply, ao actualizar é mellor usar sempre kubectl applyPara kubectl podería xestionar a configuración e rastrexar correctamente os cambios solicitados dunha aplicación a outra. Vantaxe usar sempre apply é que fai un seguimento dunha especificación aplicada previamente, o que lle permite saber cando se eliminan explícitamente as propiedades da especificación e os elementos da matriz. Isto permítelle usar apply para eliminar propiedades e elementos da matriz, mentres que unha fusión estratéxica normal non funcionará. Equipos edit и patch non actualice as notas que kubectl apply usa para rastrexar os seus cambios, polo que calquera cambio que se faga a través da API de Kubernetes, pero que se realice mediante comandos edit и patch, invisible para comandos posteriores applyÉ dicir, apply non os elimina aínda que non aparezan na especificación de entrada para apply (A documentación di iso edit и patch facer actualizacións das notas utilizadas apply, pero na práctica - non).

Se non usa o comando apply, pódese usar como editE patch, escollendo o comando que mellor se adapte ao cambio que se está a realizar. Ao engadir e cambiar as propiedades da lista de materiales, ambos enfoques son aproximadamente os mesmos. Ao eliminar propiedades de especificación ou elementos da matriz edit compórtase como un lanzamento único apply, incluíndo o seguimento de como era a especificación antes e despois de editarla, para que poida eliminar de forma explícita propiedades e elementos da matriz dun recurso. Debe establecer explícitamente o valor da propiedade como nulo na especificación para patchpara eliminalo do recurso. Eliminar un elemento de matriz mediante parches de combinación estratéxica é máis complexo porque require o uso de directivas de combinación. Consulte outros enfoques de actualización a continuación para obter alternativas máis viables.

Para implementar métodos de actualización na biblioteca cliente que se comporten de xeito similar aos comandos anteriores kubectl, debe establecerse nas solicitudes content-type в application/strategic-merge-patch+json. Se queres eliminar propiedades dunha especificación, debes establecer explícitamente os seus valores como nulos dun xeito similar. kubectl patch. Se precisa eliminar elementos da matriz, debe incluír directivas de combinación na especificación de actualización ou utilizar un enfoque diferente para as actualizacións.

Outros enfoques para as actualizacións

Kubernetes admite outros dous enfoques de actualización: Parche de combinación JSON и Parche JSON. O enfoque de parche de combinación JSON toma unha especificación parcial de Kubernetes como entrada e admite a fusión de obxectos semellante ao enfoque de parche de combinación estratéxica. A diferenza entre os dous é que só admite a substitución de matrices, incluída a matriz de contedores na especificación do pod. Isto significa que cando se utiliza un parche de combinación JSON, cómpre proporcionar especificacións completas para todos os contedores no caso de que cambie algunha propiedade de calquera contenedor. Polo tanto, este enfoque é útil para eliminar elementos dunha matriz nunha lista de materiales. Na liña de comandos pode seleccionar o parche de combinación JSON usando kubectl patch --type=merge. Cando traballes coa API de Kubernetes, debes usar o método de solicitude PATCH e instalación content-type в application/merge-patch+json.

O enfoque do parche JSON, en lugar de proporcionar unha especificación parcial dun recurso, usa proporcionar os cambios que quere facer no recurso como unha matriz, na que cada elemento da matriz representa unha descrición do cambio que se fai no recurso. Este enfoque é un xeito máis flexible e poderoso de expresar os cambios que se están a facer, pero a costa de listar os cambios que se fan nun formato separado que non sexa Kubernetes, en lugar de enviar unha especificación parcial do recurso. EN kubectl pode seleccionar o parche JSON usando kubectl patch --type=json. Cando se utiliza a API de Kubernetes, este enfoque funciona mediante o método de solicitude PATCH e instalación content-type в application/json-patch+json.

Necesitamos confianza: use substituír

Nalgúns casos, cómpre asegurarse de que non se realizan cambios nun recurso entre o momento en que se le e cando se actualiza. Noutras palabras, debes asegurarte de que todos os cambios serán atómico. Neste caso, para actualizar os recursos que debería utilizar replace. Por exemplo, se tes un ConfigMap cun contador actualizado por varias fontes, debes asegurarte de que dúas fontes non actualizan o contador ao mesmo tempo, polo que se perda a actualización. Para demostralo, imaxina unha secuencia de eventos usando o enfoque patch:

  • A e B obteñen o estado actual do recurso da API
  • Cada un actualiza localmente a especificación aumentando o contador nun e tamén engadindo "A" ou "B" respectivamente á nota "actualizada por"
  • E actualiza o recurso un pouco máis rápido
  • B actualiza o recurso

Como resultado, pérdese a actualización A. Última operación patch gaña, o contador increméntase nun en vez de dous, e o valor da nota "actualizada por" remata con "B" e non contén "A". Comparemos o anterior co que ocorre cando se realizan actualizacións mediante o enfoque replace:

  • A e B obteñen o estado actual do recurso da API
  • Cada un actualiza localmente a especificación aumentando o contador nun e tamén engadindo "A" ou "B" respectivamente á nota "actualizada por"
  • E actualiza o recurso un pouco máis rápido
  • B tenta actualizar o recurso, pero a actualización é rexeitada pola API porque a versión do recurso está na especificación replace non coincide coa versión actual do recurso en Kubernetes porque a versión do recurso foi aumentada pola operación de substitución de A.

No caso anterior, B terá que recuperar o recurso, facer cambios no novo estado e tentalo de novo replace. Isto fará que o contador se incremente en dous e que a nota "actualizada por" inclúa "AB" ao final.

O exemplo anterior implica que ao executar replace Todo o recurso está completamente substituído. Especificación utilizada para replace, non debe ser parcial, nin en partes como en apply, pero completo, incluída a adición resourceVersion nos metadatos da especificación. Se non o habilitou resourceVersion ou a versión que proporciona non é actual, a substitución será rexeitada. Polo tanto, o mellor enfoque para usar é replace – le o recurso, actualízao e substitúeo inmediatamente. Usando kubectl, pode verse así:

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

Paga a pena notar que os dous comandos seguintes, executados secuencialmente, executaranse con éxito, xa que deployment.yaml non contén propiedade .metadata.resourceVersion

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

Isto parece contradir o dito anteriormente, é dicir. "engadindo resourceVersion nos metadatos da especificación." É incorrecto dicir iso? Non, non o é, porque se kubectl avisos que non especificaches resourceVersion, lerao desde o recurso e engadirao á especificación que especificaches, e só entón executarao replace. Debido a que isto é potencialmente perigoso se confías na atomicidade, a maxia funciona completamente de lado kubectl, non debe confiar nel cando utilice bibliotecas cliente que funcionan coa API. Neste caso terás que ler a especificación do recurso actual, actualizala e despois executala PUT solicitude.

Non podes facer un parche: facemos un substituto

Ás veces cómpre facer algúns cambios que non se poden xestionar pola API. Nestes casos, pode forzar a substitución do recurso eliminándoo e creándoo de novo. Isto faise usando kubectl replace --force. Executar o comando elimina inmediatamente os recursos e despois recréaos a partir da especificación proporcionada. Non hai un controlador de "substitución forzada" na API e, para facelo a través da API, cómpre realizar dúas operacións. Primeiro cómpre eliminar o recurso configurando para el gracePeriodSeconds a cero (0) e propagationPolicy en "Fondo" e, a continuación, volva crear este recurso coa especificación desexada.

Aviso: este enfoque é potencialmente perigoso e pode levar a un estado indefinido.

Aplicar no lado do servidor

Como se mencionou anteriormente, os desenvolvedores de Kubernetes están a traballar na implementación da lóxica apply de kubectl na API de Kubernetes. Lóxicas apply dispoñible en Kubernetes 1.18 vía kubectl apply --server-side ou a través da API usando o método PATCH с content-type application/apply-patch+YAML.

Nota: JSON tamén é YAML válido, polo que pode enviar a especificación como JSON aínda que content-type vontade application/apply-patch+yaml.

Ademais desa lóxica kubectl está dispoñible para todos a través da API, apply no lado do servidor, fai un seguimento de quen é o responsable dos campos da especificación, permitindo así un acceso múltiple seguro para a súa edición sen conflitos. Noutras palabras, se apply no lado do servidor estenderase máis, aparecerá unha interface de xestión de recursos segura universal para diferentes clientes, por exemplo, kubectl, Pulumi ou Terraform, GitOps, así como scripts autoescritos usando bibliotecas de clientes.

Resultados de

Espero que este breve resumo das diferentes formas de actualizar os recursos en clústeres fose útil para vostede. É bo saber que non é só aplicar versus substituír; é posible actualizar un recurso mediante aplicar, editar, parchear ou substituír. Despois de todo, en principio, cada enfoque ten a súa propia área de aplicación. Para os cambios atómicos, é preferible substituír; se non, deberías usar o parche de combinación estratéxica a través de aplicar. Polo menos, espero que entendas que non podes confiar en Google ou StackOerflow ao buscar "kubernetes apply vs replace". Polo menos ata que este artigo substitúa a resposta actual.

Comparación adecuada de aplicación, substitución e parche de Kubernetes

Fonte: www.habr.com

Engadir un comentario