Comparación adecuada de aplicación, reemplazo y parcheo de Kubernetes

Kubernetes tiene varias opciones para actualizar recursos: aplicar, editar, parchear y reemplazar. Existe confusión sobre qué hace cada uno y cuándo usarlos. Vamos a resolverlo.

Comparación adecuada de aplicación, reemplazo y parcheo de Kubernetes

si buscar en Google se encuentra la frase "kubernetes aplicar vs reemplazar" responder a StackOverflow, lo cual no es correcto. al buscar "kubernetes aplicar vs parche" el primer enlace es la documentación para kubectl patch, que no incluye comparación apply и patch. Este artículo analizará las diferentes opciones, así como el uso adecuado de cada una.

Durante el ciclo de vida de un recurso de Kubernetes (servicio, implementación, ingreso, etc.), a veces es necesario cambiar, agregar o eliminar algunas propiedades de este recurso. Por ejemplo, agregue una nota, aumente o disminuya la cantidad de réplicas.

CLI de Kubernetes

Si ya está trabajando con clústeres de Kubernetes a través de la CLI, ya está familiarizado con apply и edit. Equipo apply lee la especificación de recursos del archivo y realiza una "inserción" en el clúster de Kubernetes, es decir, crea el recurso si no existe y lo actualiza si existe. Equipo edit lee un recurso a través de la API, luego escribe la especificación del recurso en un archivo local, que luego se abre en un editor de texto. Después de editar y guardar el archivo, kubectl enviará los cambios realizados a través de la API, que aplicará cuidadosamente estos cambios al recurso.

No todo el mundo conoce los comandos. patch и replace. Equipo patch le permite cambiar parte de una especificación de recurso, proporcionando solo la parte modificada en la línea de comando. Equipo replace funciona igual que edit, pero todo debe hacerse manualmente: debe descargar la versión actual de la especificación del recurso, por ejemplo, usando kubectl get -o yaml, edítelo y luego use replace para actualizar un recurso de acuerdo con una especificación modificada. Equipo replace no funcionará si se produjo algún cambio entre la lectura y el reemplazo del recurso.

API de Kubernetes

Probablemente estés familiarizado con los métodos. CoreV1().Pods().Update(), replaceNamespacedService o patch_namespaced_deployment, si trabaja con clústeres a través de biblioteca cliente para la API de Kubernetes utilizando algún lenguaje de programación. La biblioteca maneja estos métodos a través de solicitudes HTTP utilizando los métodos PUT и PATCH. En este caso, update и replace uso PUTY patch, no importa lo trivial que sea, utiliza PATCH.

Vale la pena señalar que kubectl También funciona con clústeres a través de API. En otras palabras, kubectles un contenedor en la parte superior de la biblioteca cliente para el lenguaje Go, que proporciona en gran medida la capacidad de proporcionar subcomandos en una forma más compacta y legible además de las capacidades API estándar. Por ejemplo, como ya habrás notado, el método apply no fue mencionado anteriormente en el párrafo anterior. Actualmente (mayo de 2020, aprox. traductor) toda lógica kubectl apply, es decir. crear recursos inexistentes y actualizar los existentes, funciona completamente en el lado del código kubectl. Se están haciendo esfuerzos en transferencia lógica apply en el lado de la API, pero todavía está en versión beta. Escribiré con más detalle a continuación.

Parche por defecto

Mejor usado patch, si desea actualizar el recurso. Así es como funcionan ambas bibliotecas cliente sobre la API de Kubernetes y kubectl (no es sorprendente, ya que es un contenedor para la biblioteca cliente, aprox. traductor).

Trabajar estratégicamente

Todos los equipos kubectl apply, edit и patch usa el método PATCH en solicitudes HTTP para actualizar un recurso existente. Si profundiza en la implementación de comandos con más detalle, todos utilizan el enfoque parcheo de fusión estratégica para actualizar recursos, aunque el comando patch puede utilizar otros enfoques (más sobre esto a continuación). El enfoque de parcheo de fusión estratégica intenta "hacerlo bien" fusionando la especificación proporcionada con la especificación existente. Más específicamente, intenta combinar objetos y matrices, lo que significa que los cambios tienden a ser aditivos. Por ejemplo, ejecutando el comando patch con una nueva variable de entorno en la especificación del contenedor del pod, hace que esa variable de entorno se agregue a las variables de entorno existentes en lugar de sobrescribirlas. Para eliminar usando este enfoque, debe forzar el valor del parámetro a nulo en la especificación proporcionada. cual de los equipos kubectl ¿Es mejor usarlo para actualizar?

Si crea y administra sus recursos usando kubectl apply, al actualizar es mejor usar siempre kubectl applyA kubectl podría gestionar la configuración y realizar un seguimiento adecuado de los cambios solicitados de una aplicación a otra. Ventaja siempre uso apply es que realiza un seguimiento de una especificación aplicada previamente, lo que le permite saber cuándo se eliminan explícitamente las propiedades de la especificación y los elementos de la matriz. Esto le permite utilizar apply para eliminar propiedades y elementos de matriz, mientras que una fusión estratégica normal no funcionará. equipos edit и patch no actualizar notas que kubectl apply utiliza para rastrear sus cambios, por lo que cualquier cambio que se rastrea y se realiza a través de la API de Kubernetes, pero se realiza a través de comandos edit и patch, invisible para comandos posteriores applyes decir, apply no los elimina incluso si no aparecen en la especificación de entrada para apply (La documentación dice que edit и patch realizar actualizaciones de las notas utilizadas apply, pero en la práctica - no).

Si no usas el comando apply, se puede utilizar como editY patch, eligiendo el comando que mejor se adapte al cambio que se está realizando. Al agregar y cambiar propiedades de BOM, ambos enfoques son más o menos iguales. Al eliminar propiedades de especificación o elementos de matriz edit se comporta como un lanzamiento único apply, incluido el seguimiento de cómo era la especificación antes y después de editarla, para que pueda eliminar explícitamente propiedades y elementos de matriz de un recurso. Debe establecer explícitamente el valor de la propiedad en nulo en la especificación para patchpara eliminarlo del recurso. Eliminar un elemento de matriz mediante parches de combinación estratégica es más complejo porque requiere el uso de directivas de combinación. Consulte otros enfoques de actualización a continuación para conocer alternativas más viables.

Para implementar métodos de actualización en la biblioteca cliente que se comporten de manera similar a los comandos anteriores kubectl, debe configurarse en las solicitudes content-type в application/strategic-merge-patch+json. Si desea eliminar propiedades en una especificación, debe establecer explícitamente sus valores en nulos de manera similar. kubectl patch. Si necesita eliminar elementos de la matriz, debe incluir directivas de combinación en la especificación de actualización o utilizar un enfoque diferente para las actualizaciones.

Otros enfoques para las actualizaciones

Kubernetes admite otros dos enfoques de actualización: Parche de fusión JSON и parche JSON. El enfoque de parche de fusión JSON toma una especificación parcial de Kubernetes como entrada y admite la fusión de objetos de manera similar al enfoque de parche de fusión estratégica. La diferencia entre los dos es que solo admite el reemplazo de matrices, incluida la matriz contenedora en la especificación del pod. Esto significa que cuando se utiliza un parche de combinación JSON, debe proporcionar especificaciones completas para todos los contenedores en caso de que cambie alguna propiedad de algún contenedor. Por tanto, este enfoque es útil para eliminar elementos de una matriz en una lista de materiales. En la línea de comando puede seleccionar el parche de combinación JSON usando kubectl patch --type=merge. Cuando trabaje con la API de Kubernetes, debe utilizar el método de solicitud PATCH e instalación content-type в application/merge-patch+json.

El enfoque de parche JSON, en lugar de proporcionar una especificación parcial de un recurso, proporciona los cambios que desea realizar en el recurso como una matriz, en la que cada elemento de la matriz representa una descripción del cambio que se realiza en el recurso. Este enfoque es una forma más flexible y poderosa de expresar los cambios que se están realizando, pero a costa de enumerar los cambios que se están realizando en un formato separado, que no sea de Kubernetes, en lugar de enviar una especificación de recursos parcial. EN kubectl puedes seleccionar el parche JSON usando kubectl patch --type=json. Cuando se utiliza la API de Kubernetes, este enfoque funciona utilizando el método de solicitud. PATCH e instalación content-type в application/json-patch+json.

Necesitamos confianza: use reemplazar

En algunos casos, debe asegurarse de que no se realicen cambios en un recurso entre el momento en que se lee y el momento en que se actualiza. En otras palabras, debe asegurarse de que todos los cambios se realicen atómico. En este caso, para actualizar los recursos debe utilizar replace. Por ejemplo, si tiene un ConfigMap con un contador que se actualiza mediante varias fuentes, debe asegurarse de que dos fuentes no actualicen el contador al mismo tiempo, lo que provocaría que se pierda la actualización. Para demostrarlo, imagine una secuencia de eventos usando el enfoque patch:

  • A y B obtienen el estado actual del recurso de la API
  • Cada uno actualiza localmente la especificación incrementando el contador en uno y también agregando "A" o "B" respectivamente a la nota "actualizado por".
  • Y actualiza el recurso un poco más rápido.
  • B actualiza el recurso

Como resultado, se pierde la actualización A. ultima operacion patch gana, el contador se incrementa en uno en lugar de dos, y el valor de la nota "actualizada por" termina en "B" y no contiene "A". Comparemos lo anterior con lo que sucede cuando las actualizaciones se realizan utilizando el enfoque replace:

  • A y B obtienen el estado actual del recurso de la API
  • Cada uno actualiza localmente la especificación incrementando el contador en uno y también agregando "A" o "B" respectivamente a la nota "actualizado por".
  • Y actualiza el recurso un poco más rápido.
  • B intenta actualizar el recurso, pero la API rechaza la actualización porque la versión del recurso está en la especificación. replace no coincide con la versión actual del recurso en Kubernetes porque la versión del recurso aumentó mediante la operación de reemplazo de A.

En el caso anterior, B tendrá que volver a buscar el recurso, realizar cambios en el nuevo estado y volver a intentarlo. replace. Esto hará que el contador se incremente en dos y que la nota "actualizado por" incluya "AB" al final.

El ejemplo anterior implica que al ejecutar replace Todo el recurso se reemplaza por completo. Especificación utilizada para replace, no debe ser parcial, ni en partes como en apply, pero completo, incluyendo la adición resourceVersion en los metadatos de la especificación. Si no has habilitado resourceVersion o la versión que proporcione no es actual, el reemplazo será rechazado. Entonces, el mejor enfoque a utilizar es replace – leer el recurso, actualizarlo y reemplazarlo inmediatamente. Usando kubectl, podría verse así:

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

Vale la pena señalar que los siguientes dos comandos, ejecutados secuencialmente, se ejecutarán exitosamente, ya que deployment.yaml no contiene propiedad .metadata.resourceVersion

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

Esto parecería contradecir lo dicho anteriormente, es decir. "agregando resourceVersion en los metadatos de la especificación". ¿Está mal decir eso? No, no lo es, porque si kubectl avisos que no especificaste resourceVersion, lo leerá del recurso y lo agregará a la especificación que usted especificó, y solo entonces lo ejecutará replace. Debido a que esto es potencialmente peligroso si confías en la atomicidad, la magia funciona completamente de lado. kubectl, no debe confiar en él cuando utilice bibliotecas cliente que funcionen con la API. En este caso, tendrá que leer la especificación del recurso actual, actualizarla y luego ejecutar PUT solicitud.

No puedes hacer un parche, nosotros hacemos un reemplazo

A veces es necesario realizar algunos cambios que la API no puede manejar. En estos casos, puede forzar el reemplazo del recurso eliminándolo y volviéndolo a crear. Esto se hace usando kubectl replace --force. La ejecución del comando elimina inmediatamente los recursos y luego los recrea a partir de la especificación proporcionada. No existe un controlador de "reemplazo forzado" en la API y, para hacerlo a través de la API, debe realizar dos operaciones. Primero debe eliminar el recurso configurándolo gracePeriodSeconds a cero (0) y propagationPolicy en “Fondo” y luego vuelva a crear este recurso con la especificación deseada.

Advertencia: este enfoque es potencialmente peligroso y puede conducir a un estado indefinido.

Aplicar en el lado del servidor

Como se mencionó anteriormente, los desarrolladores de Kubernetes están trabajando en implementar la lógica apply de kubectl en la API de Kubernetes. Lógicas apply disponible en Kubernetes 1.18 a través de kubectl apply --server-side o a través de la API utilizando el método PATCH с content-type application/apply-patch+YAML.

Nota: JSON también es YAML válido, por lo que puede enviar la especificación como JSON incluso si content-type voluntad application/apply-patch+yaml.

Además de esa lógica kubectl está disponible para todos a través de API, apply en el lado del servidor, realiza un seguimiento de quién es responsable de los campos de la especificación, permitiendo así un acceso múltiple seguro para su edición sin conflictos. En otras palabras, si apply en el lado del servidor se generalizará, aparecerá una interfaz universal segura de administración de recursos para diferentes clientes, por ejemplo, kubectl, Pulumi o Terraform, GitOps, así como scripts autoescritos utilizando bibliotecas de cliente.

resultados

Espero que esta breve descripción general de las diferentes formas de actualizar recursos en clústeres le haya resultado útil. Es bueno saber que no se trata solo de aplicar versus reemplazar; es posible actualizar un recurso mediante aplicar, editar, parchear o reemplazar. Después de todo, en principio, cada enfoque tiene su propio ámbito de aplicación. Para cambios atómicos, es preferible reemplazar; de lo contrario, debe usar el parche de combinación estratégica mediante aplicar. Como mínimo, espero que comprenda que no puede confiar en Google o StackOerflow cuando busca "aplicar o reemplazar Kubernetes". Al menos hasta que este artículo reemplace la respuesta actual.

Comparación adecuada de aplicación, reemplazo y parcheo de Kubernetes

Fuente: habr.com

Añadir un comentario