Solución de problemas de servidor de API y etcd en Azure Kubernetes Services
Esta guía está diseñada para ayudarle a identificar y resolver los problemas poco probables que pueda encontrar en el servidor de API en implementaciones grandes de Microsoft Azure Kubernetes Services (AKS).
Microsoft ha probado la confiabilidad y el rendimiento del servidor de API a una escala de 5000 nodos y 200 000 pods. El clúster que contiene el servidor de API tiene la capacidad de escalar horizontalmente y entregar automáticamente objetivos de nivel de servicio (SLO) de Kubernetes. Si experimenta latencias altas o tiempos de espera, probablemente se deba a que hay una fuga de recursos en el directorio distribuido etc
(etc.) o un cliente infractor tiene llamadas API excesivas.
Requisitos previos
Herramienta kubectl de Kubernetes. Para instalar kubectl mediante la CLI de Azure, ejecute el comando az aks install-cli .
Registros de diagnóstico de AKS (en concreto, eventos de kube-audit) habilitados y enviados a un área de trabajo de Log Analytics. Para determinar si los registros se recopilan mediante el modo de diagnóstico de Azure o específico de recursos, compruebe la hoja Configuración de diagnóstico en el Azure Portal.
Nivel Estándar para clústeres de AKS. Si usa el nivel Gratis, el servidor de API y etcd contienen recursos limitados. Los clústeres de AKS en el nivel Gratis no proporcionan alta disponibilidad. Esta suele ser la causa principal de los problemas de servidor de API y etcd.
Complemento kubectl-aks para ejecutar comandos directamente en nodos de AKS sin usar el plano de control de Kubernetes.
Síntomas
En la tabla siguiente se describen los síntomas comunes de los errores del servidor de API:
Síntoma | Descripción |
---|---|
Tiempos de espera del servidor de API | Tiempos de espera frecuentes que superan las garantías en el ACUERDO de nivel de servicio del servidor de API de AKS. Por ejemplo, kubectl el tiempo de espera de los comandos. |
Latencias altas | Se producen altas latencias que hacen que se produzcan errores en los SLO de Kubernetes. Por ejemplo, el kubectl comando tarda más de 30 segundos en enumerar los pods. |
Pod del servidor de API en CrashLoopbackOff estado o con errores de llamada de webhook |
Compruebe que no tiene ningún webhook de admisión personalizado (como el motor de directivas de Kyverno ) que bloquee las llamadas al servidor de API. |
Lista de comprobación para la solución de problemas
Si experimenta tiempos de latencia elevados, siga estos pasos para identificar el cliente infractor y los tipos de llamadas API que producen errores.
Paso 1: Identificación de los principales agentes de usuario por el número de solicitudes
Para identificar qué clientes generan la mayoría de las solicitudes (y, potencialmente, la mayor parte de la carga del servidor de API), ejecute una consulta similar al código siguiente. En la consulta siguiente se enumeran los 10 agentes de usuario principales por el número de solicitudes de servidor de API enviadas.
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| summarize count() by UserAgent
| top 10 by count_
| project UserAgent, count_
Nota:
Si la consulta no devuelve ningún resultado, es posible que haya seleccionado la tabla incorrecta para consultar los registros de diagnóstico. En el modo específico del recurso, los datos se escriben en tablas individuales en función de la categoría del recurso. Los registros de diagnóstico se escriben en la AKSAudit
tabla. En el modo de diagnóstico de Azure, todos los datos se escriben en la AzureDiagnostics
tabla. Para obtener más información, consulte Registros de recursos de Azure.
Aunque resulta útil saber qué clientes generan el volumen de solicitudes más alto, es posible que el volumen de solicitudes alto por sí solo no sea motivo de preocupación. Un mejor indicador de la carga real que genera cada cliente en el servidor de API es la latencia de respuesta que experimentan.
Paso 2: Identificación y gráfico de la latencia media de las solicitudes de servidor de API por agente de usuario
Para identificar la latencia media de las solicitudes de servidor de API por agente de usuario tal como se traza en un gráfico de tiempo, ejecute la consulta siguiente:
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize avg(latency) by UserAgent, bin(start_time, 5m)
| render timechart
Esta consulta es un seguimiento de la consulta de la sección "Identificar los principales agentes de usuario por el número de solicitudes" . Puede proporcionar más información sobre la carga real generada por cada agente de usuario a lo largo del tiempo.
Sugerencia
Mediante el análisis de estos datos, puede identificar patrones y anomalías que pueden indicar problemas en el clúster o las aplicaciones de AKS. Por ejemplo, es posible que observe que un usuario determinado está experimentando una latencia alta. Este escenario puede indicar el tipo de llamadas API que provocan una carga excesiva en el servidor de API o etc.
Paso 3: Identificación de llamadas API incorrectas para un agente de usuario determinado
Ejecute la consulta siguiente para tabular la latencia del percentil 99 (P99) de las llamadas API en distintos tipos de recursos para un cliente determinado:
AKSAudit
| where TimeGenerated between(now(-1h)..now()) // When you experienced the problem
| extend HttpMethod = Verb
| extend Resource = tostring(ObjectRef.resource)
| where UserAgent == "DUMMYUSERAGENT" // Filter by name of the useragent you are interested in
| where Resource != ""
| extend start_time = RequestReceivedTime
| extend end_time = StageReceivedTime
| extend latency = datetime_diff('millisecond', end_time, start_time)
| summarize p99latency=percentile(latency, 99) by HttpMethod, Resource
| render table
Los resultados de esta consulta pueden ser útiles para identificar los tipos de llamadas API que producen un error en los SLO de Kubernetes ascendentes. En la mayoría de los casos, un cliente infractor podría estar realizando demasiadas LIST
llamadas a un gran conjunto de objetos u objetos demasiado grandes. Desafortunadamente, no hay límites de escalabilidad difíciles disponibles para guiar a los usuarios sobre la escalabilidad del servidor de API. Los límites de escalabilidad del servidor de API o etc. dependen de varios factores que se explican en Umbrales de escalabilidad de Kubernetes.
Causa 1: una regla de red bloquea el tráfico de los nodos de agente al servidor de API
Una regla de red puede bloquear el tráfico entre los nodos del agente y el servidor de API.
Para comprobar si una directiva de red mal configurada está bloqueando la comunicación entre el servidor de API y los nodos del agente, ejecute los siguientes comandos de kubectl-aks :
kubectl aks config import \
--subscription <mySubscriptionID> \
--resource-group <myResourceGroup> \
--cluster-name <myAKSCluster>
kubectl aks check-apiserver-connectivity --node <myNode>
El comando config import recupera la información del conjunto de escalado de máquinas virtuales para todos los nodos del clúster. A continuación, el comando check-apiserver-connectivity usa esta información para comprobar la conectividad de red entre el servidor de API y un nodo especificado, específicamente para su instancia del conjunto de escalado subyacente.
Nota:
Si la salida del check-apiserver-connectivity
comando contiene el Connectivity check: succeeded
mensaje, la conectividad de red no está impedida.
Solución 1: Corrección de la directiva de red para quitar el bloqueo de tráfico
Si la salida del comando indica que se produjo un error de conexión, vuelva a configurar la directiva de red para que no bloquee innecesariamente el tráfico entre los nodos del agente y el servidor de API.
Causa 2: Un cliente infractor filtra objetos etcd y da como resultado una ralentización del etcd
Un problema común es la creación continua de objetos sin eliminar los que no se usan en la base de datos etcd. Esto puede causar problemas de rendimiento cuando etcd se ocupa de demasiados objetos (más de 10 000) de cualquier tipo. Un rápido aumento de los cambios en estos objetos también podría hacer que se supere el tamaño de la base de datos de etcd (4 gigabytes de forma predeterminada).
Para comprobar el uso de la base de datos etcd, vaya a Diagnosticar y resolver problemas en el Azure Portal. Ejecute la herramienta de diagnóstico Etcd Availability Issues buscando "etcd" en el cuadro de búsqueda. La herramienta de diagnóstico muestra el desglose de uso y el tamaño total de la base de datos.
Si solo quiere una manera rápida de ver el tamaño actual de la base de datos de etcd en bytes, ejecute el siguiente comando:
kubectl get --raw /metrics | grep -E "etcd_db_total_size_in_bytes|apiserver_storage_size_bytes|apiserver_storage_db_total_size_in_bytes"
Nota:
El nombre de la métrica del comando anterior es diferente para diferentes versiones de Kubernetes. Para Kubernetes 1.25 y versiones anteriores, use etcd_db_total_size_in_bytes
. Para Kubernetes 1.26 a 1.28, use apiserver_storage_db_total_size_in_bytes
.
Solución 2: Definir cuotas para la creación de objetos, eliminar objetos o limitar la duración del objeto en etcd
Para evitar que etcd alcance la capacidad y provoque un tiempo de inactividad del clúster, puede limitar el número máximo de recursos que se crean. También puede ralentizar el número de revisiones que se generan para las instancias de recursos. Para limitar el número de objetos que se pueden crear, puede definir cuotas de objetos.
Si ha identificado objetos que ya no están en uso pero que están ocupando recursos, considere la posibilidad de eliminarlos. Por ejemplo, puede eliminar trabajos completados para liberar espacio:
kubectl delete jobs --field-selector status.successful=1
Para los objetos que admiten la limpieza automática, puede establecer valores de Tiempo de vida (TTL) para limitar la duración de estos objetos. También puede etiquetar los objetos para que pueda eliminar de forma masiva todos los objetos de un tipo específico mediante selectores de etiquetas. Si establece referencias de propietario entre objetos, los objetos dependientes se eliminan automáticamente después de eliminar el objeto primario.
Causa 3: Un cliente infractor realiza llamadas LIST o PUT excesivas
Si determina que etcd no está sobrecargado con demasiados objetos, un cliente infractor podría estar realizando demasiadas LIST
llamadas o PUT
llamadas al servidor de API.
Solución 3a: Ajuste del patrón de llamada api
Considere la posibilidad de ajustar el patrón de llamada api del cliente para reducir la presión en el plano de control.
Solución 3b: Limitación de un cliente que apabulla el plano de control
Si no puede ajustar el cliente, puede usar la característica Prioridad y equidad de Kubernetes para limitar el cliente. Esta característica puede ayudar a conservar el estado del plano de control y evitar que se produzcan errores en otras aplicaciones.
En el procedimiento siguiente se muestra cómo limitar la API LIST Pods de un cliente infractor establecida en cinco llamadas simultáneas:
Create un objeto FlowSchema que coincida con el patrón de llamada API del cliente infractor:
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 kind: FlowSchema metadata: name: restrict-bad-client spec: priorityLevelConfiguration: name: very-low-priority distinguisherMethod: type: ByUser rules: - resourceRules: - apiGroups: [""] namespaces: ["default"] resources: ["pods"] verbs: ["list"] subjects: - kind: ServiceAccount serviceAccount: name: bad-client-account namespace: default
Create una configuración de prioridad inferior para limitar las llamadas API incorrectas del cliente:
apiVersion: flowcontrol.apiserver.k8s.io/v1beta2 kind: PriorityLevelConfiguration metadata: name: very-low-priority spec: limited: assuredConcurrencyShares: 5 limitResponse: type: Reject type: Limited
Observe la llamada limitada en las métricas del servidor de API.
kubectl get --raw /metrics | grep "restrict-bad-client"
Causa 4: Un webhook personalizado puede provocar un interbloqueo en pods de servidor de API
Un webhook personalizado, como Kyverno, podría estar causando un interbloqueo en los pods del servidor de API.
Compruebe los eventos relacionados con el servidor de API. Es posible que vea mensajes de evento similares al texto siguiente:
Error interno: error al llamar al webhook "mutate.kyverno.svc-fail": failed to call webhook: Post "https://kyverno-system-kyverno-system-svc.kyverno-system.svc:443/mutate/fail?timeout=10s": write unix @->/tunnel-uds/proxysocket: write: broken pipe
En este ejemplo, el webhook de validación está bloqueando la creación de algunos objetos de servidor de API. Dado que este escenario puede producirse durante el tiempo de arranque, no se pueden crear el servidor de API ni los pods de Konnectivity. Por lo tanto, el webhook no puede conectarse a esos pods. Esta secuencia de eventos provoca el interbloqueo y el mensaje de error.
Solución 4: Eliminación de configuraciones de webhook
Para solucionar este problema, elimine las configuraciones de webhook de validación y mutación. Para eliminar estas configuraciones de webhook en Kyverno, consulte el artículo de solución de problemas de Kyverno.
Aviso de declinación de responsabilidades sobre la información de contacto de terceros
Microsoft proporciona información de contacto de otros proveedores para ayudarle a encontrar información adicional sobre este tema. Dicha información de contacto puede cambiar sin notificación previa. Microsoft no garantiza la precisión de esta información de contacto de terceros.
Aviso de declinación de responsabilidades sobre la información de terceros
Los productos de otros fabricantes que se mencionan en este artículo han sido creados por compañías independientes de Microsoft. Microsoft no ofrece ninguna garantía, ya sea implícita o de otro tipo, sobre la confiabilidad o el rendimiento de dichos productos.
Ponte en contacto con nosotros para obtener ayuda
Si tiene preguntas o necesita ayuda, cree una solicitud de soporte o busque consejo en la comunidad de Azure. También puede enviar comentarios sobre el producto con los comentarios de la comunidad de Azure.