Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Plano de control de Kubernetes
sugerencia
Explore las
El plano de control de Kubernetes está formado por el servidor de API de Kubernetes, el administrador del controlador de Kubernetes, el planificador y otros componentes necesarios para que Kubernetes funcione. Los límites de escalabilidad de estos componentes varían según lo que se esté ejecutando en el clúster, pero las áreas que más influyen en la escalabilidad son la versión de Kubernetes, la utilización y el escalado individual de los nodos.
Puedes ejecutar el plano de control del clúster en uno de estos dos modos para cumplir con los diferentes requisitos de carga de trabajo:
-
Modo estándar: de forma predeterminada, todos los clústeres de EKS utilizan el modo estándar. El plano de control se amplía y reduce automáticamente en función de las demandas de carga de trabajo. El modo estándar asigna dinámicamente suficiente capacidad del plano de control y es la opción recomendada para la mayoría de los casos de uso.
-
Modo aprovisionado: si sus cargas de trabajo no pueden tolerar la variabilidad del rendimiento derivada del escalado del plano de control, o si requieren una capacidad muy alta del plano de control, puede usar el modo aprovisionado. Con el modo aprovisionado, puede preasignar la capacidad del plano de control para que esté siempre lista para responder a los requisitos más exigentes. Obtiene un rendimiento constante y predecible.
Con el modo Aprovisionado de EKS, puede elegir entre un conjunto de niveles de escalado (XL, 2XL, 4XL y 8XL). Con cada nivel, obtiene un rendimiento alto y predecible desde el plano de control del clúster. El modo aprovisionado es especialmente valioso para los siguientes casos de uso:
-
Performance-critical cargas de trabajo
-
Large-scale Operaciones de inteligencia artificial y aprendizaje automático
-
Eventos anticipados de alta demanda
-
Entornos que requieren uniformidad en la fase de puesta en escena y la producción
Con el modo aprovisionado, puede preasignar la capacidad del plano de control con antelación y beneficiarse de un acuerdo de nivel de servicio (SLA) mejorado del 99,99%, medido en intervalos de 1 minuto. Para obtener más información sobre el modo aprovisionado de EKS, incluidas las especificaciones de los niveles y los precios, consulte el plano de control aprovisionado de EKS en la guía del usuario de EKS.
Limite la carga de trabajo y las ráfagas de nodos
importante
Para evitar alcanzar los límites de las API en el plano de control, debes limitar los picos de escalamiento que aumentan el tamaño de los clústeres en porcentajes de dos dígitos cada vez (por ejemplo, de 1000 a 1100 nodos o de 4000 a 4500 pods a la vez).
El plano de control de EKS se escalará automáticamente a medida que el clúster crezca, pero la rapidez con la que se escalará tiene límites. Al crear un clúster de EKS por primera vez, el plano de control no podrá escalar inmediatamente a cientos de nodos o miles de pods. Para obtener más información sobre cómo EKS ha realizado mejoras de escalado, consulte esta entrada del blog
La ampliación de aplicaciones de gran tamaño requiere que la infraestructura se adapte y esté completamente lista (por ejemplo, el calentamiento de los balanceadores de carga). Para controlar la velocidad de escalado, asegúrese de escalarlo en función de las métricas correctas para su aplicación. Es posible que el escalado de la CPU y la memoria no prediga con precisión las restricciones de las aplicaciones, y usar métricas personalizadas (por ejemplo, solicitudes por segundo) en el escalador automático de módulos horizontales (HPA) de Kubernetes puede ser una mejor opción de escalado.
Para usar una métrica personalizada, consulta los ejemplos de la documentación de Kubernetes. https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics
Amplíe los nodos y los pods de forma segura
Sustituya las instancias de larga ejecución
La sustitución regular de los nodos ayuda a mantener el clúster en buen estado, ya que evita los cambios en la configuración y los problemas que solo se producen después de un tiempo de actividad prolongado (por ejemplo, pérdidas lentas de memoria). El reemplazo automatizado le proporcionará buenos procesos y prácticas para actualizar los nodos y aplicar parches de seguridad. Si todos los nodos del clúster se sustituyen con regularidad, se necesitará menos esfuerzo para mantener procesos separados para un mantenimiento continuo.
Usa la configuración de tiempo de vida (TTL) de Karpenter para reemplazar las instancias después de que hayan estado ejecutándose durante un período de tiempo específico. Los grupos de nodos autogestionados pueden usar la max-instance-lifetime configuración para alternar los nodos automáticamente. Los grupos de nodos gestionados no disponen actualmente de esta función, pero puedes hacer un seguimiento de la solicitud aquí GitHub
Elimine los nodos infrautilizados
Puedes eliminar nodos cuando no tengan cargas de trabajo en ejecución utilizando el umbral de escalado descendente en el escalador automático de clústeres de Kubernetes con la configuración de aprovisionador --scale-down-utilization-thresholdttlSecondsAfterEmpty
Usa los presupuestos de interrupción de los módulos y el cierre seguro de los nodos.
Para eliminar los pods y los nodos de un clúster de Kubernetes, los controladores deben actualizar varios recursos (p. ej.). EndpointSlices Hacerlo con frecuencia o demasiado rápido puede provocar que el servidor de API se ralentice y que las aplicaciones se interrumpan a medida que los cambios se propaguen a los controladores. https://kubernetes.io/docs/concepts/workloads/pods/disruptions/
Usa Cache cuando ejecutes Kubectl Client-Side
El uso ineficiente del comando kubectl puede añadir carga adicional al servidor de API de Kubernetes. Debes evitar ejecutar scripts o automatizaciones que usen kubectl de forma repetida (por ejemplo, en un bucle for) o ejecutar comandos sin una caché local.
kubectltiene una caché del lado del cliente que almacena en caché la información de detección del clúster para reducir la cantidad de llamadas a la API necesarias. La caché está habilitada de forma predeterminada y se actualiza cada 10 minutos.
Si ejecutas kubectl desde un contenedor o sin una caché del lado del cliente, es posible que te encuentres con problemas de limitación de la API. Se recomienda conservar la caché del clúster montándola para evitar realizar llamadas innecesarias a la --cache-dir API.
Inhabilita la compresión kubectl
Inhabilitar la compresión kubectl en tu archivo kubeconfig puede reducir el uso de la API y de la CPU del cliente. De forma predeterminada, el servidor comprimirá los datos enviados al cliente para optimizar el ancho de banda de la red. Esto aumenta la carga de la CPU en el cliente y el servidor para cada solicitud, y la desactivación de la compresión puede reducir la sobrecarga y la latencia si dispone de un ancho de banda adecuado. Para deshabilitar la compresión, puedes usar la --disable-compression=true marca o configurarla disable-compression: true en tu archivo kubeconfig.
apiVersion: v1
clusters:
- cluster:
server: serverURL
disable-compression: true
name: cluster
Escalador automático de clústeres fragmentados
El escalador automático de clústeres de Kubernetes se ha probado para ampliarlo hasta 1000 nodos.
ClusterAutoscaler-1
autoscalingGroups: - name: eks-core-node-grp-20220823190924690000000011-80c1660e-030d-476d-cb0d-d04d585a8fcb maxSize: 50 minSize: 2 - name: eks-data_m1-20220824130553925600000011-5ec167fa-ca93-8ca4-53a5-003e1ed8d306 maxSize: 450 minSize: 2 - name: eks-data_m2-20220824130733258600000015-aac167fb-8bf7-429d-d032-e195af4e25f5 maxSize: 450 minSize: 2 - name: eks-data_m3-20220824130553914900000003-18c167fa-ca7f-23c9-0fea-f9edefbda002 maxSize: 450 minSize: 2
ClusterAutoscaler-2
autoscalingGroups: - name: eks-data_m4-2022082413055392550000000f-5ec167fa-ca86-6b83-ae9d-1e07ade3e7c4 maxSize: 450 minSize: 2 - name: eks-data_m5-20220824130744542100000017-02c167fb-a1f7-3d9e-a583-43b4975c050c maxSize: 450 minSize: 2 - name: eks-data_m6-2022082413055392430000000d-9cc167fa-ca94-132a-04ad-e43166cef41f maxSize: 450 minSize: 2 - name: eks-data_m7-20220824130553921000000009-96c167fa-ca91-d767-0427-91c879ddf5af maxSize: 450 minSize: 2
Prioridad e imparcialidad de la API
Descripción general de
Para evitar sobrecargarse durante los períodos de aumento de solicitudes, el servidor de API limita el número de solicitudes a bordo que puede tener pendientes en un momento dado. Cuando se supere este límite, el servidor de API comenzará a rechazar las solicitudes y devolverá a los clientes un código de respuesta HTTP 429 en caso de que diga que hay demasiadas solicitudes. Es preferible que el servidor descarte las solicitudes y haga que los clientes vuelvan a intentarlo más tarde, a no establecer límites de número de solicitudes en el servidor y sobrecargar el plano de control, lo que podría provocar una disminución del rendimiento o una falta de disponibilidad.
El mecanismo que utiliza Kubernetes para configurar la forma en que se dividen estas solicitudes entrantes entre distintos tipos de solicitudes se denomina API Priority and Fairness. https://kubernetes.io/docs/concepts/cluster-administration/flow-control/--max-requests-inflight --max-mutating-requests-inflight EKS usa los valores predeterminados de 400 y 200 solicitudes para estos indicadores, lo que permite enviar un total de 600 solicitudes a la vez. Sin embargo, a medida que amplía el plano de control a tamaños más grandes en respuesta al aumento de la utilización y la pérdida de la carga de trabajo, aumenta en consecuencia la cuota de solicitudes durante el vuelo hasta el año 2000 (sujeto a cambios). La APF especifica cómo se subdivide aún más esta cuota de solicitudes a bordo entre los diferentes tipos de solicitudes. Tenga en cuenta que los planos de control de EKS tienen una alta disponibilidad y tienen al menos 2 servidores API registrados en cada clúster. Esto significa que el número total de solicitudes de vuelo que puede gestionar su clúster es el doble (o superior si se amplía más horizontalmente) de la cuota de vuelo establecida por kube-apiserver. Esto equivale a varios miles en los clústeres de EKS más grandes. requests/second
Hay dos tipos de objetos de Kubernetes, denominados PriorityLevelConfigurations y FlowSchemas, que configuran cómo se divide el número total de solicitudes entre los distintos tipos de solicitudes. El servidor de API mantiene estos objetos automáticamente y EKS usa la configuración predeterminada de estos objetos para la versión secundaria de Kubernetes determinada. PriorityLevelConfigurations representan una fracción del número total de solicitudes permitidas. Por ejemplo, a la carga de trabajo más alta PriorityLevelConfiguration se le asignan 98 de un total de 600 solicitudes. La suma de las solicitudes asignadas a todas PriorityLevelConfigurations será igual a 600 (o un poco más de 600, ya que el servidor de API redondeará al alza si a un nivel determinado se le concede una fracción de la solicitud). Para comprobar el PriorityLevelConfigurations estado de tu clúster y el número de solicitudes asignadas a cada uno, puedes ejecutar el siguiente comando. Estos son los valores predeterminados en EKS 1.32:
$ kubectl get --raw /metrics | grep apiserver_flowcontrol_nominal_limit_seats apiserver_flowcontrol_nominal_limit_seats{priority_level="catch-all"} 13 apiserver_flowcontrol_nominal_limit_seats{priority_level="exempt"} 0 apiserver_flowcontrol_nominal_limit_seats{priority_level="global-default"} 49 apiserver_flowcontrol_nominal_limit_seats{priority_level="leader-election"} 25 apiserver_flowcontrol_nominal_limit_seats{priority_level="node-high"} 98 apiserver_flowcontrol_nominal_limit_seats{priority_level="system"} 74 apiserver_flowcontrol_nominal_limit_seats{priority_level="workload-high"} 98 apiserver_flowcontrol_nominal_limit_seats{priority_level="workload-low"} 245
El segundo tipo de objeto es. FlowSchemas Las solicitudes del servidor API con un conjunto determinado de propiedades se clasifican en el mismo grupo FlowSchema. Estas propiedades incluyen el usuario autenticado o los atributos de la solicitud, como el grupo de API, el espacio de nombres o el recurso. A FlowSchema también especifica a qué se debe asignar PriorityLevelConfiguration este tipo de solicitud. Los dos objetos juntos dicen: «Quiero que este tipo de solicitud cuente para este porcentaje de solicitudes a bordo». Cuando una solicitud llegue al servidor de API, comprobará cada una de ellas FlowSchemas hasta que encuentre una que coincida con todas las propiedades requeridas. Si varias solicitudes FlowSchemas coinciden, el servidor de API elegirá la FlowSchema que tenga la menor prioridad coincidente especificada como propiedad en el objeto.
La asignación de FlowSchemas a se PriorityLevelConfigurations puede ver con este comando:
$ kubectl get flowschemas NAME PRIORITYLEVEL MATCHINGPRECEDENCE DISTINGUISHERMETHOD AGE MISSINGPL exempt exempt 1 <none> 7h19m False eks-exempt exempt 2 <none> 7h19m False probes exempt 2 <none> 7h19m False system-leader-election leader-election 100 ByUser 7h19m False endpoint-controller workload-high 150 ByUser 7h19m False workload-leader-election leader-election 200 ByUser 7h19m False system-node-high node-high 400 ByUser 7h19m False system-nodes system 500 ByUser 7h19m False kube-controller-manager workload-high 800 ByNamespace 7h19m False kube-scheduler workload-high 800 ByNamespace 7h19m False kube-system-service-accounts workload-high 900 ByNamespace 7h19m False eks-workload-high workload-high 1000 ByUser 7h14m False service-accounts workload-low 9000 ByUser 7h19m False global-default global-default 9900 ByUser 7h19m False catch-all catch-all 10000 ByUser 7h19m False
PriorityLevelConfigurations puede tener un tipo de cola, rechazo o exención. Para los tipos Queue y Reject, se aplica un límite al número máximo de solicitudes a bordo para ese nivel de prioridad; sin embargo, el comportamiento es diferente cuando se alcanza ese límite. Por ejemplo, los que tienen la carga de trabajo más alta PriorityLevelConfiguration utilizan el tipo Queue y tienen 98 solicitudes disponibles para que las usen los controladores controladores, endpoint-controladores, planificadores, controladores relacionados con eks y desde los pods que se ejecutan en el espacio de nombres del sistema kube. Como se usa el tipo Queue, el servidor de API intentará mantener las solicitudes en la memoria y esperará que el número de solicitudes en vuelo descienda por debajo de 98 antes de que se agote el tiempo de espera de estas solicitudes. Si se agota el tiempo de espera de una solicitud determinada en la cola o si ya hay demasiadas solicitudes en cola, el servidor de API no tiene más remedio que descartar la solicitud y devolver al cliente un 429. Tenga en cuenta que hacer cola puede impedir que una solicitud reciba un 429, pero esto conlleva la desventaja de aumentar la latencia de extremo a extremo de la solicitud.
Pensemos ahora en el comodín FlowSchema que equivale al comodín con el tipo Reject. PriorityLevelConfiguration Si los clientes alcanzan el límite de 13 solicitudes a bordo, el servidor de API no hará cola y descartará las solicitudes al instante con un código de respuesta 429. Por último, las solicitudes asignadas a un PriorityLevelConfiguration tipo de exención nunca recibirán un 429 y siempre se enviarán de forma inmediata. Se usa para solicitudes de alta prioridad, como las solicitudes de healthz o las solicitudes que provienen del grupo system:masters.
Supervisión del APF y de las solicitudes descartadas
Para confirmar si se descarta alguna solicitud debido a la APF, se apiserver_flowcontrol_rejected_requests_total pueden monitorear las métricas del servidor de API para comprobar el impacto FlowSchemas y. PriorityLevelConfigurations Por ejemplo, esta métrica muestra que se FlowSchema descartaron 100 solicitudes de las cuentas de servicio debido a que se agotó el tiempo de espera de las solicitudes en las colas con poca carga de trabajo:
% kubectl get --raw /metrics | grep apiserver_flowcontrol_rejected_requests_total
apiserver_flowcontrol_rejected_requests_total{flow_schema="service-accounts",priority_level="workload-low",reason="time-out"} 100
Para comprobar qué tan cerca PriorityLevelConfiguration está una determinada persona de recibir 429 segundos o de experimentar un aumento de la latencia debido a la puesta en cola, puedes comparar la diferencia entre el límite de simultaneidad y la simultaneidad en uso. En este ejemplo, tenemos un búfer de 100 solicitudes.
% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_nominal_limit_seats.*workload-low' apiserver_flowcontrol_nominal_limit_seats{priority_level="workload-low"} 245 % kubectl get --raw /metrics | grep 'apiserver_flowcontrol_current_executing_seats.*workload-low' apiserver_flowcontrol_current_executing_seats{flow_schema="service-accounts",priority_level="workload-low"} 145
Para comprobar si una determinada solicitud PriorityLevelConfiguration está en cola, pero no necesariamente se han descartado, apiserver_flowcontrol_current_inqueue_requests puedes consultar la métrica de:
% kubectl get --raw /metrics | grep 'apiserver_flowcontrol_current_inqueue_requests.*workload-low'
apiserver_flowcontrol_current_inqueue_requests{flow_schema="service-accounts",priority_level="workload-low"} 10
Otras métricas útiles de Prometheus incluyen:
-
apiserver_flowcontrol_dispatched_requests_total
-
apiserver_flowcontrol_request_execution_seconds
-
apiserver_flowcontrol_request_wait_duration_seconds
Consulta la documentación anterior para obtener una lista completa de las métricas de APF. https://kubernetes.io/docs/concepts/cluster-administration/flow-control/#observability
Prevención de solicitudes canceladas
Evite los 429 cambiando su carga de trabajo
Cuando la APF descarta solicitudes porque una persona PriorityLevelConfiguration sobrepasa el número máximo permitido de solicitudes a bordo, los clientes de la zona afectada FlowSchemas pueden reducir la cantidad de solicitudes que se ejecutan en un momento determinado. Esto se puede lograr reduciendo el número total de solicitudes realizadas durante el período en el que se están produciendo 429 solicitudes. Tenga en cuenta que las solicitudes de larga duración, como las costosas llamadas a listas, son especialmente problemáticas porque cuentan como solicitudes en vuelo durante todo el tiempo que estén ejecutándose. Reducir el número de estas costosas solicitudes u optimizar la latencia de estas llamadas a listas (por ejemplo, reduciendo la cantidad de objetos que se obtienen por solicitud o pasando a utilizar una solicitud de seguimiento) puede ayudar a reducir la simultaneidad total requerida por una carga de trabajo determinada.
Evita los 429 cambiando la configuración de tu APF
aviso
Cambie la configuración de APF predeterminada únicamente si sabe lo que está haciendo. Los ajustes de APF mal configurados pueden provocar la interrupción de las solicitudes del servidor API y una interrupción significativa de la carga de trabajo.
Otro enfoque para evitar la pérdida de solicitudes es cambiar la configuración predeterminada FlowSchemas o PriorityLevelConfigurations instalarlas en los clústeres de EKS. EKS instala la configuración predeterminada anterior para FlowSchemas y PriorityLevelConfigurations para la versión secundaria de Kubernetes determinada. El servidor de API reconciliará automáticamente estos objetos con sus valores predeterminados si se modifican, a menos que la siguiente anotación en los objetos esté configurada como falsa:
metadata:
annotations:
apf.kubernetes.io/autoupdate-spec: "false"
En un nivel superior, la configuración de APF se puede modificar de la siguiente manera:
-
Asigne más capacidad de vuelo a las solicitudes que le interesen.
-
Aísle las solicitudes costosas o no esenciales que pueden reducir la capacidad para otros tipos de solicitudes.
Esto se puede lograr cambiando la configuración predeterminada FlowSchemas PriorityLevelConfigurations o creando nuevos objetos de este tipo. Los operadores pueden aumentar los valores de seguridad de los PriorityLevelConfigurations objetos pertinentes ConcurrencyShares para aumentar la proporción de solicitudes a bordo que se les asignan. Además, la cantidad de solicitudes que se pueden poner en cola en un momento determinado también se puede aumentar si la aplicación puede gestionar la latencia adicional provocada por las solicitudes que se ponen en cola antes de enviarse.
Como alternativa, se pueden crear PriorityLevelConfigurations objetos nuevos FlowSchema y objetos específicos para la carga de trabajo del cliente. Tenga en cuenta que si asigna más seguridad ConcurrencyShares a los existentes PriorityLevelConfigurations o a los nuevos, PriorityLevelConfigurations se reducirá el número de solicitudes que pueden gestionar otros grupos, ya que el límite global se mantendrá en 600 en vuelo por servidor de API.
Al realizar cambios en los valores predeterminados de la APF, se deben supervisar estas métricas en un clúster que no esté en producción para garantizar que los cambios en la configuración no provoquen la aparición de 429 solicitudes no deseadas:
-
La métrica de
apiserver_flowcontrol_rejected_requests_totaldebe supervisarse en todos los casos para garantizar que ningún segmento comience FlowSchemas a rechazar solicitudes. -
Los valores de
apiserver_flowcontrol_nominal_limit_seatsyapiserver_flowcontrol_current_executing_seatsdeben compararse para garantizar que la simultaneidad en uso no corra el riesgo de superar el límite de ese nivel de prioridad.
Un caso de uso habitual para definir una nueva FlowSchema red es el aislamiento. PriorityLevelConfiguration Supongamos que queremos aislar las llamadas a eventos de listas de larga duración de los pods y asignarlas a su propia cantidad de solicitudes. Esto evitará que las solicitudes importantes de los pods que utilizan las cuentas FlowSchema de servicio existentes reciban 429 solicitudes y se queden sin capacidad de solicitud. Recuerde que el número total de solicitudes a bordo es limitado; sin embargo, en este ejemplo se muestra que la configuración de la APF se puede modificar para dividir mejor la capacidad de solicitudes en función de una carga de trabajo determinada:
Ejemplo de FlowSchema objeto para aislar las solicitudes de eventos de la lista:
apiVersion: flowcontrol.apiserver.k8s.io/v1
kind: FlowSchema
metadata:
name: list-events-default-service-accounts
spec:
distinguisherMethod:
type: ByUser
matchingPrecedence: 8000
priorityLevelConfiguration:
name: catch-all
rules:
- resourceRules:
- apiGroups:
- '*'
namespaces:
- default
resources:
- events
verbs:
- list
subjects:
- kind: ServiceAccount
serviceAccount:
name: default
namespace: default
-
Esto FlowSchema captura todas las llamadas a eventos de la lista realizadas por las cuentas de servicio en el espacio de nombres predeterminado.
-
La prioridad correspondiente 8000 es inferior al valor 9000 utilizado por las cuentas de servicio existentes, por FlowSchema lo que estas llamadas a eventos de la lista coincidirán con las cuentas de servicio predeterminadas de la lista de eventos en lugar de con las cuentas de servicio.
-
Estamos usando el comodín PriorityLevelConfiguration para aislar estas solicitudes. Este grupo solo permite utilizar 13 solicitudes a bordo para estas llamadas de eventos de lista de larga duración. Los pods empezarán a recibir 429 en cuanto intenten emitir más de 13 de estas solicitudes simultáneamente.
Recuperar recursos en el servidor de API
Obtener información del servidor de API es un comportamiento esperado en clústeres de cualquier tamaño. A medida que se escala la cantidad de recursos del clúster, la frecuencia de las solicitudes y el volumen de datos pueden convertirse rápidamente en un cuello de botella para el plano de control y provocar latencia y lentitud en la API. En función de la gravedad de la latencia, si no se tiene cuidado, se producirán tiempos de inactividad inesperados.
Los primeros pasos para evitar este tipo de problemas son saber lo que solicita y con qué frecuencia. Esta es una guía para limitar el volumen de consultas en función de las mejores prácticas de escalado. Las sugerencias de esta sección se proporcionan en orden, empezando por las opciones que se sabe que son las que mejor se escalan.
Utilice informadores compartidos
Al crear controladores y automatizaciones que se integren con la API de Kubernetes, con frecuencia necesitarás obtener información de los recursos de Kubernetes. Si sondea estos recursos con regularidad, puede provocar una carga considerable en el servidor de la API.
Si utiliza un informador
Los controladores deben evitar sondear los recursos de todo el clúster sin etiquetas ni selectores de campo, especialmente en clústeres grandes. Cada encuesta sin filtrar requiere que se envíen muchos datos innecesarios desde etcd a través del servidor API para que el cliente los filtre. Al filtrar en función de las etiquetas y los espacios de nombres, puedes reducir la cantidad de trabajo que el servidor de API debe realizar para cumplir con la solicitud y los datos enviados al cliente.
Optimiza el uso de la API de Kubernetes
Al llamar a la API de Kubernetes con controladores personalizados o automatizados, es importante que limites las llamadas solo a los recursos que necesites. Sin límites, puedes provocar una carga innecesaria en el servidor de API, etc.
Se recomienda utilizar el argumento watch siempre que sea posible. Sin argumentos, el comportamiento predeterminado es enumerar los objetos. Para usar watch en lugar de list, puedes añadirlo ?watch=true al final de tu solicitud de API. Por ejemplo, para que todos los pods aparezcan en el espacio de nombres predeterminado con un reloj, usa:
/api/v1/namespaces/default/pods?watch=true
Si estás enumerando objetos, debes limitar el alcance de lo que estás enumerando y la cantidad de datos devueltos. Puede limitar los datos devueltos añadiendo limit=500 argumentos a las solicitudes. El fieldSelector argumento y la /namespace/ ruta pueden resultar útiles para garantizar que las listas tengan un alcance tan limitado como sea necesario. Por ejemplo, para mostrar solo los pods en ejecución en el espacio de nombres predeterminado, usa la siguiente ruta y argumentos de la API.
/api/v1/namespaces/default/pods?fieldSelector=status.phase=Running&limit=500
O haz una lista de todos los pods que se ejecutan con:
/api/v1/pods?fieldSelector=status.phase=Running&limit=500
Otra opción para limitar las llamadas de vigilancia o los objetos de la lista es utilizarla, sobre la resourceVersions que puedes leer más información en la documentación de Kubernetes. resourceVersion argumento, recibirá la versión más reciente disponible, que requiere una lectura de quórum de etcd, que es la lectura más cara y lenta de la base de datos. La versión del recurso depende de los recursos que esté intentando consultar y se puede encontrar en el campo. metadata.resourseVersion Esto también se recomienda en caso de utilizar llamadas de seguimiento y no solo llamadas de lista
Hay una oferta especial resourceVersion=0 disponible que devolverá los resultados de la caché del servidor API. Esto puede reducir la carga de etcd, pero no admite la paginación.
/api/v1/namespaces/default/pods?resourceVersion=0
Se recomienda usar watch con un ResourceVersion establecido como el valor conocido más reciente recibido de su lista o reloj anterior. Esto se gestiona automáticamente en client-go. Pero se sugiere comprobarlo dos veces si está utilizando un cliente k8s en otros idiomas.
/api/v1/namespaces/default/pods?watch=true&resourceVersion=362812295
Si llamas a la API sin ningún argumento, será lo que más recursos consuma para el servidor de API, etc. Esta llamada recogerá todos los pods de todos los espacios de nombres sin paginación ni limitación del alcance y requerirá una lectura de quórum desde etcd.
/api/v1/pods
Prevenga el trueno de los rebaños DaemonSet
A DaemonSet garantiza que todos los nodos (o algunos) ejecuten una copia de un pod. A medida que los nodos se unen al clúster, el controlador del conjunto de demonios crea pods para esos nodos. A medida que los nodos abandonan el clúster, esos pods se recogen como basura. Al eliminar un DaemonSet , se eliminarán los pods que creó.
Algunos usos típicos de un DaemonSet son:
-
Ejecutar un daemon de almacenamiento en clúster en cada nodo
-
Ejecutar un demonio de recopilación de registros en cada nodo
-
Ejecutar un daemon de supervisión de nodos en cada nodo
En clústeres con miles de nodos, crear DaemonSet uno nuevo DaemonSet, actualizar uno o aumentar el número de nodos puede generar una carga elevada en el plano de control. Si los DaemonSet pods emiten costosas solicitudes al servidor de API al iniciar el pod, pueden provocar un uso elevado de recursos en el plano de control debido a la gran cantidad de solicitudes simultáneas.
En condiciones normales de funcionamiento, puede utilizar un RollingUpdate para garantizar el despliegue gradual de los nuevos DaemonSet pods. Con una estrategia de RollingUpdate actualización, tras actualizar una DaemonSet plantilla, el mando elimina los DaemonSet pods antiguos y crea otros nuevos DaemonSet automáticamente de forma controlada. Durante todo el proceso de actualización, se DaemonSet ejecutará como máximo un pod en cada nodo. Puede realizar un despliegue gradual maxUnavailable configurándolo en 1, maxSurge 0 y minReadySeconds 60. Si no especificas una estrategia de actualización, Kubernetes utilizará de forma predeterminada la creación de una RollingUpdate con maxUnavailable 1, maxSurge 0 y 0. minReadySeconds
minReadySeconds: 60 strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 maxUnavailable: 1
A RollingUpdate garantiza el despliegue gradual de nuevos DaemonSet pods si el ya DaemonSet está creado y tiene el número esperado de Ready pods en todos los nodos. En determinadas condiciones que no están contempladas en las estrategias, pueden producirse problemas con una manada RollingUpdate atronadora.
Evita el trueno de los rebaños durante la creación DaemonSet
De forma predeterminada, independientemente de la RollingUpdate configuración, el controlador de demonios del kube-controller-manager creará pods para todos los nodos coincidentes de forma simultánea cuando crees uno nuevo. DaemonSet Para forzar el despliegue gradual de los pods después de crear un, puedes usar un o. DaemonSet NodeSelector NodeAffinity De esta forma, se creará un pod DaemonSet que no tenga ningún nodo y, a continuación, podrás ir actualizando los nodos de forma gradual para que puedan ejecutar un pod desde el DaemonSet a un ritmo controlado. Puedes seguir este enfoque:
-
Añada una etiqueta a todos los nodos para
run-daemonset=false.
kubectl label nodes --all run-daemonset=false
-
Cree la suya DaemonSet con una
NodeAffinityconfiguración que coincida con cualquier nodo sinrun-daemonset=falseetiqueta. Inicialmente, esto hará que no DaemonSet tengas los pods correspondientes.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: run-daemonset
operator: NotIn
values:
- "false"
-
Quita la
run-daemonset=falseetiqueta de los nodos a un ritmo controlado. Puedes usar este script de bash como ejemplo:
#!/bin/bash
nodes=$(kubectl get --raw "/api/v1/nodes" | jq -r '.items | .[].metadata.name')
for node in ${nodes[@]}; do
echo "Removing run-daemonset label from node $node"
kubectl label nodes $node run-daemonset-
sleep 5
done
-
Si lo desea, elimine la
NodeAffinityconfiguración de su DaemonSet objeto. Ten en cuenta que esto también activaráRollingUpdatey reemplazará gradualmente todos los DaemonSet pods existentes porque la DaemonSet plantilla haya cambiado.
Evite el estruendo de manadas en los nodos a gran escala
Al igual que DaemonSet ocurre con la creación, la creación rápida de nuevos nodos puede provocar que un gran número de DaemonSet pods se inicien simultáneamente. Debes crear nuevos nodos a una velocidad controlada para que el controlador cree DaemonSet pods a esta misma velocidad. Si esto no es posible, puedes hacer que los nodos nuevos inicialmente no sean aptos para los existentes DaemonSet mediante el uso NodeAffinity de. A continuación, puedes añadir una etiqueta a los nuevos nodos de forma gradual para que el controlador del conjunto de demonios cree pods a un ritmo controlado. Puedes seguir este enfoque:
-
Añada una etiqueta a todos los nodos existentes para
run-daemonset=true
kubectl label nodes --all run-daemonset=true
-
DaemonSet Actualízala con una
NodeAffinityconfiguración para que coincida con cualquier nodo con unarun-daemonset=trueetiqueta. Ten en cuenta que esto también activaráRollingUpdatey reemplazará gradualmente todos los DaemonSet pods existentes a medida que la DaemonSet plantilla haya cambiado. Debes esperarRollingUpdatea que se complete antes de continuar con el siguiente paso.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: run-daemonset
operator: In
values:
- "true"
-
Crea nuevos nodos en tu clúster. Tenga en cuenta que estos nodos no tendrán la
run-daemonset=trueetiqueta, por lo que no coincidirán con esos nodos. DaemonSet -
Añada la
run-daemonset=trueetiqueta a los nodos nuevos (que actualmente no tienen larun-daemonsetetiqueta) a una velocidad controlada. Puedes usar este script bash como ejemplo:
#!/bin/bash
nodes=$(kubectl get --raw "/api/v1/nodes?labelSelector=%21run-daemonset" | jq -r '.items | .[].metadata.name')
for node in ${nodes[@]}; do
echo "Adding run-daemonset=true label to node $node"
kubectl label nodes $node run-daemonset=true
sleep 5
done
-
Si lo desea, elimine la
NodeAffinityconfiguración de su DaemonSet objeto y elimine larun-daemonsetetiqueta de todos los nodos.
Evite que las actualizaciones generen estruendos DaemonSet
Una RollingUpdate política solo respetará la maxUnavailable configuración de los DaemonSet pods que lo estén. Ready Si a solo DaemonSet tiene NotReady pods o un porcentaje elevado de ellos NotReady y actualizas su plantilla, el controlador del conjunto de demonios creará nuevos pods simultáneamente para todos los pods. NotReady Esto puede provocar problemas con la manada si hay un número importante de manadas (por ejemplo, si las NotReady manadas se estrellan continuamente en bucle o no consiguen captar imágenes).
Para forzar el despliegue gradual de los pods cuando actualizas un pod DaemonSet y ya hayNotReady, puedes cambiar temporalmente la estrategia de actualización de forma intermitente. DaemonSet RollingUpdate OnDelete Después de actualizar una DaemonSet plantilla, el mando crea nuevos pods después de que elimines manualmente los antiguos para que puedas controlar el lanzamiento de los nuevos. OnDelete Puedes seguir este enfoque:
-
Comprueba si tienes alguna
NotReadycápsula en tu DaemonSet. -
De lo contrario, puedes actualizar la DaemonSet plantilla de forma segura y la
RollingUpdateestrategia garantizará una implementación gradual. -
En caso afirmativo, primero debes actualizarla DaemonSet para usar la
OnDeleteestrategia.
updateStrategy: type: OnDelete
-
A continuación, actualiza la DaemonSet plantilla con los cambios necesarios.
-
Tras esta actualización, puedes eliminar los DaemonSet pods antiguos emitiendo solicitudes de eliminación de pods a un ritmo controlado. Puedes usar este script de bash como ejemplo en el que el DaemonSet nombre sea fluentd-elasticsearch en el espacio de nombres del sistema kube:
#!/bin/bash
daemonset_pods=$(kubectl get --raw "/api/v1/namespaces/kube-system/pods?labelSelector=name%3Dfluentd-elasticsearch" | jq -r '.items | .[].metadata.name')
for pod in ${daemonset_pods[@]}; do
echo "Deleting pod $pod"
kubectl delete pod $pod -n kube-system
sleep 5
done
-
Por último, puedes volver a la estrategia anterior. DaemonSet
RollingUpdate