Home » JSONPath en Kubernetes
Aprendizaje de JSONPath en Kubernetes

JSONPath en Kubernetes

Como parte de mi trabajo diario y también como motivo de preparación para el examen CKA, quise hacer un consolidado de conocimientos entorno a JSONPath en Kubernetes con la herramienta kubectl.

Si te has topado ya con la necesidad de usar JSONPath en Kubernetes, pero no tienes aún claro qué cosa es y cómo aprovecharlo, este artículo es para ti.

Introducción

En el amplio mundo de Kubernetes, administrar y consultar información de manera eficiente muy importante para mantener la operatividad y la salud de nuestros clusters. Por ello, una herramienta fundamental para lograr esto es JSONPath.

JSONPath es un lenguaje de consulta que nos permite extraer y filtrar datos específicos de documentos JSON, que es el formato estándar utilizado por Kubernetes para representar la configuración y el estado de los objetos.

En este post, exploraremos qué es JSONPath, por qué es una herramienta vital en el contexto de Kubernetes y algunas ideas importantes para maximizar su utilidad.

Desde la simplicidad de extraer nombres de pods hasta la complejidad de contar y listar contenedores en estado «Ready», JSONPath se convierte en una herramienta indispensable para cualquier administrador de Kubernetes.

Forma de uso

Listado sencillo de Pods

La herramienta kubectl ya trae integrado el soporte para JSONPath en Kubernetes para los comandos de consulta. Por ejemplo, para listar los Pods de manera simple se hace esto:

kubectl get pods

El formato en el que se muestra de manera predeterminada es este:

Listado de pods de forma predeterminada

En la imagen mostrada se muestran todos los Pods pero con información predeterminada como el nombre, estado, contenedores en estado Ready, número de reinicios y el tiempo de vida.

Listado de Pods filtrados y algunos labels

Pero, ¿qué tal si deseo además mostrar el valor de algunos labels como parte de la salida? Seguramente estas dos opciones podrían ajustarse a este propósito:

kubectl get pods --show-labels

Lo anterior mostrará todos los labels de cada Pod, lo cual puede ser más de lo necesitado. En cambio, esta otra opción parece ser más apropiada para un label específico como una columna adicional del listado:

kubectl get pods -L app.kubernetes.io/name

¿Y qué tal si solo deseo mostrar los Pods con un label y valor específico? Esta es una buena opción:

kubectl get pods -l app.kubernetes.io/name=aws-node

De una u otra forma, las opciones --show-labels, -l y -L nos permitan filtrar y/o formatear la salida de los Pods.

Listado de Pods con filtros más complejos

Pero, ¿y cómo listo los Pods que no están en estado Running? ¿Cómo haces lo anterior solo usando el comando kubectl sin tuberías y/o grep? ¿Cómo muestras el nombre del nodo donde corre cada Pod? ¿Cómo muestras el nombre de la imagen usada por cada contenedor de los Pods? ¿Cómo se hace para listar los contenedores de un Pod que se han reiniciado al menos 1 vez?

Todas estas ya parecen ser operaciones más complejas que requieren el uso de filtros más elaborados y que no se pueden hacer con las opciones mostradas en los ejemplos previos.

Sin embargo, kubectl sí permite hacerlo sin usar herramientas extras como tuberías de shell, grep, jq o similares. Esto es posible gracias al uso de JSONPath en Kubernetes que se usa de este modo:

kubectl get pods -o jsonpath='<expresion-JSONPath>'

La <expresion-JSONPath> (sin incluir los símbolos > y <) es parte del lenguaje que vamos a ver cómo usarlo a través de ejemplos en la siguiente sección.

Importante: Si bien solo he hablado del listado de Pods, el uso de JSONPath se puede hacer sobre cualquier recurso con un comando kubectl get

Documentación sobre JSONPath en Kubernetes

En la siguiente sección se irá explicando de forma práctica las diferentes expresiones de JSONPath. Pero, si se desea una explicación teórica un poco más detallada, se puede recurrir a la documentación de Kubernetes y su sopore de JSONPath (en inglés).

Ejemplos prácticos

1. Análisis de salida en JSON

Antes de intentar manipular la salida de JSON es recomendable familiarizarse con una diferencia básica: elemento único vs varios elementos

¿Qué significa elemento único? Es la consulta de un único objeto de cierto tipo. Por ejemplo el listado de detalles de un Pod en particular.

kubectl get pod nginx -o json | tee nginx-pod.json

¿Cómo son varios elementos? Cuando no escogemos un objeto en particular:

kubectl get pods -o json | tee all-pods.json

Si miras rápidamente ambos archivos (nginx-pod.json y all-pods.json) notarás que son casi iguales en la estructura. Pero si te detienes a observar, verás la diferencia en las primeras líneas:

Comparativa de elemento unico versus varios elementos

La imagen y las áreas remarcadas deberían explicarse por sí solas. Pero si no lo notas, la consulta de varios elementos crea un arreglo o lista llamado items que contiene uno o más elementos de tipo Pod.

Cada item tiene la misma estructura (atributos) que el objeto único mostrado en el primer recuadro de arriba.

Importante:

  • No es lo mismo analizar la salida JSON de un único objeto que la salida de un listado de objetos.
  • Toma un tiempo para analizar los archivos JSON completos y comprender los diferentes atributos disponibles (apiVersion, metadata, spec, etc) y cuáles están anidados o son hijos de otros.
  • Mientras analices la estructura JSON de los objetos de Kubernetes te puede ser de mucha ayuda la consulta de documentación que proveen estos comandos (por ejemplo para Pods):
kubectl explain pod --recursive

kubectl explain pod.spec.template

kubectl explain pod.spec.tolerations
kubectl explain pod.spec.tolerations --recursive

kubectl explain pod.spec.containers
kubectl explain pod.spec.containers.command

2. Mostrar en qué nodo corre un Pod

Para el caso del Pod de nginx sería así:

kubectl get pod nginx -o jsonpath='{.spec.nodeName}'

Similar al anterior, pero mostrando un salto de línea al final:

kubectl get pod nginx -o jsonpath='{.spec.nodeName}{"\n"}'

3. Mostrar el nombre de todos los Pods listados

kubectl get pods -o jsonpath='{.items[*].metadata.name}'

Este ejemplo hace una consulta simple, sin iteración, y de cada uno extrae el atributo .metadata.name, los cuales se muestran separados por espacio en blanco.

4. Iterar sobre todos los Pods y mostrar su nombre

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{end}'

El resultado parece similar al anterior, excepto que no tiene espacios en blanco entre cada elemento.

Pero lo más resaltante aquí es la forma de procesar cada item (Pod) y esto se hace a través de iteración. La forma de iterar es así:

{range .items[*]}<expresion>{end}

{range} crea un bucle cuyos elementos se especifican a su derecha (.items[*]). Luego, sigue una expresión (sin los símbolos > y <) y finalmente se cierra el bucle con {end}

La expresión es {.metadata.name} lo cual hace que por cada item o Pod extraiga el atributo .metadata.name

La salida se puede formatear mejor para que cada item se muestre en una línea diferente, de este modo:

kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'

Ahora la salida ya luce mejor, ¿cierto?

5. Mostrar cuántas veces se reinició un contenedor de un Pod

Digamos que tenemos un Pod con múltiples contenedores dentro. A veces sucede que uno de los contenedores puede fallar y se reinician. Esto se puede consultar con el atributo .status.containerStatuses. Exploremos su contenido con la ayuda de jq:

kubectl get pod nginx -o jsonpath='{.status.containerStatuses}' | jq

Supongamos que el Pod nginx tiene dentro un contenedor de nombre «sidecar» del cual queremos consultar cuántas veces se ha reiniciado. Esto lo hariamos así:

kubectl get pod multi-pod \
  -o jsonpath='{.status.containerStatuses[?(@.name=="sidecar")].restartCount}'

Aquí se hizo uso de un filtro dentro de un arreglo o lista. El arreglo es .status.containerStatuses[] y dentro de él se va a seleccionar solo los elementos cuyo atributo hijo sea .name y con un valor igual a «sidecar». El ? marca el inicio de un filtro, seguido por la expresión de filtro entre paréntesis. El @ hace referencia al elemento actual siendo procesado en el arreglo. Finalmente, luego del filtro del arreglo, se extrae el atributo .restartCount que nos interesa.

6. Mostrar los nodos y sus IPs

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.addresses[?(@.type=="InternalIP")].address}{"\n"}{end}'

Un poco más de iteración de arreglos, mostrando el nombre y la IP de cada nodo separado por TAB

7. Mostrar todos los Pods que no estén en estado Running

kubectl get pods -A -o jsonpath='{range .items[?(@.status.phase != "Running")]}{.metadata.namespace}{"\t"}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'

Se muestra el namespace, nombre de Pod y su estado separados por TAB

8. Mostrar los nodos con capacidad de CPU mayor a cierto umbral

Por ejemplo, mostrar qué nodos tienen al menos «500m» de capacidad de procesamiento disponible.

kubectl get nodes -o jsonpath='{range .items[?(@.status.allocatable.cpu > "500m")]}{.metadata.name} {.status.allocatable.cpu}{"\n"}{end}'

9. Listar los PersistentVolumeClaims y su estado

kubectl get pvc -Ao jsonpath='{range .items[*]}{.metadata.name} --> {.status.phase}{"\n"}{end}'

10. Formatear la salida de Pods con columnas personalizadas

En este último ejemplo hacemos uso de expresiones sencillas de JSONPath en Kubernetes pero para crear columnas personalizadas. Espero que el ejemplo y la imagen se expliquen por sí solas.

kubectl get pods -o custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase,NODENAME:.spec.nodeName,NODEIP:.status.hostIP
Salida personalizada de listado de Pods usando JSONPath en Kubernetes

Conclusión

Hemos revisado una teoría básica de JSONPath en Kubernetes y la importancia de su uso demostrada a través de diferentes ejemplos prácticos de uso.

Como han podido ver, las posibilidades de procesar la información de objetos de Kubernetes desde JSON son muy amplias, pero todo depende de nuestras necesidades y del dominio que tengamos de JSONPath.

Definitivamente, para obtener el máximo potencial de lo aquí aprendido se requiere práctica. Pero, espero que este artículo haya sido lo suficientemente claro y básico para cualquiera que quiera iniciarse en este tema.

Nos encontramos en una próxima oportunidad.

Post navigation

Deja un comentario

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *