Filtrer les sorties Kubernetes

Dans ce chapitre, nous allons étudier les différentes méthodes de filtrage proposées par le projet Kubernetes.

Introduction

Nous avons vu jusqu'ici, comment récupérer des informations sur vos ressources Kubernetes en utilisant soit la commande :

  • kubectl describe <RESOURCE_TYPE> [RESOURCE NAME] : affiche une description détaillée des ressources sélectionnées, y compris les ressources connexes telles que les événements ou les contrôleurs. Vous pouvez sélectionner un seul objet par son nom, tous les objets de ce type, fournir un préfixe de nom ou un label selector.
  • kubectl get <RESOURCE_TYPE> [RESOURCE NAME] : affiche dans un tableau les informations les plus importantes sur les ressources spécifiées. En spécifiant l'option -o qui prend en compte différents formats de sorties, on peut afficher les sorties de la commande selon le format souhaité.

Cependant, si vous souhaitez afficher ou récupérer quelques informations spécifiques sur vos ressources Kubernetes pour par exemple les réutiliser dans les variables de vos scripts ou bien les réutiliser dans votre propre outil de monitoring, dans ce cas, il va falloir filtrer les sorties de la commande kubectl get vu plus haut. Heureusement, pour nous que l'équipe kubernetes a pensé à nous, car il nous fournisse quelques options pour filtrer les résultats de cette commande. Nous allons donc voir dans ce chapitre les différentes méthodes de filtrage proposées par le projet Kubernetes.

Filtrage

jsonpath

À cet instant, notre but est de récupérer le nom des images des conteneurs de nos pods, en utilisant seulement la commande kubectl get ainsi que ses options. Pour le moment, lançons cette commande sans aucune option afin de lister nos différents pods.

kubectl get pods

Résultat :

apache-server   1/1       Running   0          21s
nginx-server    1/1       Running   0          1m

D'après le résultat, nous avons donc deux pods tournant sur notre cluster. Nous allons à présent, afficher encore plus d'informations sous le format json en exploitant l'option -o :

kubectl get pods -o json

Résultat :

{    "apiVersion": "v1",
    "items": [
    
    ...
    ...

    ],
    "kind": "List",
    "metadata": {
        "resourceVersion": "",
        "selfLink": ""
    }
}

Ensuite, nous allons utiliser la commande grep afin de vérifier si la clé image éxiste :

kubectl get pods -o json | grep -i image

Résultat :

"image": "httpd",
"imagePullPolicy": "IfNotPresent",
"image": "httpd:latest",
"imageID": "docker-pullable://httpd@sha256:ac6594daaa934c4c6ba66c562e96f2fb12f871415a9b7117724c52687080d35d",
"image": "nginx",
"imagePullPolicy": "IfNotPresent",
"image": "nginx:latest",
"imageID": "docker-pullable://nginx@sha256:50cf965a6e08ec5784009d0fccb380fc479826b6e0e65684d9879170a9df8566",

Nous avons bel et bien une clé nommée image que nous allons tenter de récupérer grâce à un format nommé JSONPath. Ce type de format va nous servir pour filter le résultat de notre commande.

On peut remarquer sur le résultat précédent au format json, que la première clé contenant une liste (reconnaissable grâce aux crochets []) se nomme items. Nous allons donc afficher le contenu de cette liste :

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

Résultat :

map[apiVersion:v1 kind:Pod metadata:map[labels:map[run:apache-server] name:apache-server namespace:default 
... image:nginx:latest]] hostIP:172.17.0.79 phase:Running]]

La encore nous avons encore énormément d'informations. Il va falloir donc affiner encore plus nos recherches. Nous allons pour le moment filtrer que le premier pod de notre cluster en remplaçant * par 0 (0 étant le premier index de notre liste) :

kubectl get pods -o jsonpath='{.items[0]'}

Résultat :

map[status:map[containerStatuses:[map[lastState:map[] name:apache-server ready:true restartCount:0 state:map
...
image:httpd imagePullPolicy:IfNotPresent name:apache-server
...

Comme annoncé plus haut, nous allons encore plus affiner nos recherches en recherchant la map (reconnaissable grâce à l'opérateur map) spec :

kubectl get pods -o jsonpath='{.items[0]'.spec}

Résultat :

map[priority:0 restartPolicy:Always terminationGracePeriodSeconds:30 containers:[map[image:httpd imagePullPo
...

Nous remarquons dans le résultat, qu'il existe une autre map nommée containers. Ceci est intéressant car on peut très vite remarquer que la map spec comporte une arborescence identique à celle de notre fichier manifest YAML, qui dans mon cas ressemble à cela :

apiVersion: v1
kind: Pod
metadata:
  labels:
  run: apache-server
  name: apache-server
spec: 
  containers:  
  - image: httpd
    name: apache-server

Nous allons donc suivre alors la même arborescence à savoir spec (type : list) > containers (type : list) > image (type: string) soit :

kubectl get pods -o jsonpath='{.items[0].spec.containers[*].image}'

Résultat :

httpdmaster

Le but est presque atteint, la dernière étape consiste à lister maintenant le nom de l'image des conteneurs de TOUS nos pods. Pour cela, rien de compliqué, il suffit juste de remplacer item[0] par item[*] :

kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'

Résultat :

httpd nginx

Exércice :

Je vais vous complexifier un peu la tâche, on vous donnant un nouvel objectif : "Récupérer les noms des nodes et leur capacité cpu avec un saut à la ligne". Le résultat doit donc ressembler à ceci :

master node01
4      4

Conseil

Pour récupérer la capacité cpu regarder sur la map status

1

2

3

...

Solution !

kubectl get nodes -o jsonpath='{.items[*].metadata.name}{"\n"}{.items[*].status.capacity.cpu}{"\n"}'

Les boucles

Vous pouvez aussi utiliser les opérateurs range et end pour itérer sur des listes. Cette démarche va vous permettre de mieux manipuler les élements de votre liste. Nous allons dans cet exemple réutiliser l'exemple précédent mais cette fois-ci avec les boucles, de façon à afficher le nom des nœuds sur la premiere colonne et la capacité cpu sur la deuxième colonne :

kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.capacity.cpu}{"\n"}{end}'

Résultat :

master  4
node01  4

custom-columns

Le format custom-columns comme son nom l'indique permet d'afficher un tableau en utilisant une liste de colonnes personnalisées séparées par des virgules et contenant comme valeur forme d'une expression JSONPath. Nous allons dans cette-fois-ci afficher sous forme de tableau que le nom d'un Persistent-Volume ainsi que sa capacité de stockage. Ce qui nous donnera la commande ci-dessous :

kubectl get pv -o=custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage

Résultat :

NAME       CAPACITY
pv-log-4   40Mi
pv-log-1   100Mi
pv-log-2   200Mi
pv-log-3   300Mi

sort-by

L'option --sort-by permet de trier vos ressources dans l'ordre croissant, il prend comme valeur la forme d'une expression JSONPath. Nous allons réutiliser l'exemple précedent en rajoutant l'option --sort-by de manière à trier les PVs dans l'ordre croissant selon leur capacité de stockage.

kubectl get pv --sort-by=.spec.capacity.storage  -o=custom-columns=NAME:.metadata.name,CAPACITY:.spec.capacity.storage

Résultat :

NAME       CAPACITY
pv-log-4   40Mi
pv-log-1   100Mi
pv-log-2   200Mi
pv-log-3   300Mi

Espace commentaire

Écrire un commentaire

Rejoignez la discussion

Vous devez être connecté pour poster un message.

26 commentaires

ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

D'ailleurs, pour ceux qui galèrent avec les templates, je vous conseille de toujours tester avec -o json pour voir la structure avant d'écrire le path, ça évite de perdre deux heures sur un .items[*] mal placé.

26/12/2019 à 13:37
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

La limite dépend de ton shell (ARG_MAX). Si c'est trop long, mets ton expression dans un fichier et utilise --template-file.

26/12/2019 à 05:37
gbrunet
Membre
Avatar de gbrunet
gbrunet
Membre

Il y a une limite de caractères pour la commande ? J'ai un jsonpath assez long pour mes PVs.

25/12/2019 à 22:51
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Le timestamp est au format RFC3339. Si l'ordre te semble bizarre, c'est souvent parce que les dates sont identiques à la seconde près et que le tri est instable. C'est normal, ne t'inquiète pas.

25/12/2019 à 14:55
delattre-claude
Membre Actif
Avatar de delattre-claude
delattre-claude
Membre Actif

J'ai essayé de trier par date de création, mais le --sort-by=.metadata.creationTimestamp me sort des résultats bizarres.

25/12/2019 à 10:30
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

C'est le comportement par défaut de Kubernetes quand le champ n'est pas renseigné. Si tu veux du vide, il faut faire un traitement post-commande avec sed 's/<none>//g'.

25/12/2019 à 03:15
sloiseau
Membre Actif
Avatar de sloiseau
sloiseau
Membre Actif

Pourquoi mon jsonpath me renvoie <none> au lieu d'une valeur vide ?

24/12/2019 à 20:34
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Non, c'est une commande shell. Tu dois construire ta chaîne de commande dynamiquement dans ton script bash avant de l'exécuter.

24/12/2019 à 12:54
christiane99
Membre Actif
Avatar de christiane99
christiane99
Membre Actif

Question bête : on peut utiliser des variables d'environnement dans le jsonpath ?

24/12/2019 à 04:56
upineau
Membre Actif
Avatar de upineau
upineau
Membre Actif

Top l'article. J'ai enfin compris comment sortir les images proprement sans passer par 10 grep.

23/12/2019 à 22:18
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Le plus simple c'est de définir tes colonnes et de remplacer l'espace par une virgule en pipe avec sed. kubectl ne gère pas le CSV nativement.

23/12/2019 à 14:22
frey
Membre Actif Rédacteur
Avatar de frey
frey
Membre Actif Rédacteur

Comment je fais si je veux sortir ça en CSV ?

23/12/2019 à 08:25
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

T'as probablement fait une faute de frappe dans le chemin. Vérifie l'arborescence exacte :

kubectl get pods -o custom-columns=NAME:.metadata.name,IP:.status.podIP
23/12/2019 à 02:36
huet-aurore
Membre Actif
Avatar de huet-aurore
huet-aurore
Membre Actif

J'ai un soucis avec custom-columns. J'ai besoin d'afficher l'IP du pod, mais elle est dans status.podIP. Mon résultat est vide.

22/12/2019 à 21:15
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Sur 500 pods ça va, mais au-delà, c'est lourd. Si tu dois scripter ça massivement, passe direct par jq. Tu pipes le JSON dedans, c'est nettement plus rapide.

22/12/2019 à 15:06
alfred98
Membre Actif
Avatar de alfred98
alfred98
Membre Actif

Merci pour l'astuce sur les boucles avec range, ça rend le truc lisible. Par contre, c'est quoi la limite de perf si je fais ça sur 500 pods ?

22/12/2019 à 08:39
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Ne fais pas ça en jsonpath, c'est une usine à gaz. Utilise le -l (label selector) directement dans la commande kubectl get. C'est fait pour ça.

22/12/2019 à 02:51
fmaury
Membre Actif
Avatar de fmaury
fmaury
Membre Actif

Est-ce qu'on peut filtrer sur plusieurs labels avec jsonpath ? J'ai besoin de isoler mes pods prod.

21/12/2019 à 20:47
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Ça trie par valeur réelle si Kubernetes reconnaît l'unité. Par contre, si tu mélanges les types, c'est le bordel assuré. Si tu as des doutes, convertis tout en octets avant de trier.

21/12/2019 à 15:14
simone-begue
Membre Actif
Avatar de simone-begue
simone-begue
Membre Actif

Le --sort-by avec les capacités de stockage, ça trie par ordre alphabétique ou numérique ? Parce que 40Mi, 100Mi, 200Mi, ça marche, mais je me demande si 1Gi va passer avant 500Mi.

21/12/2019 à 08:03
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Ah, PowerShell interprète mal les guillemets imbriqués. Essaie d'échapper les doubles quotes ou utilise des simples quotes pour la chaîne externe :

kubectl get nodes -o jsonpath='{.items[*].metadata.name}{"\n"}{.items[*].status.capacity.cpu}{"\n"}'
21/12/2019 à 01:08
antoine-raymond
Membre Actif
Avatar de antoine-raymond
antoine-raymond
Membre Actif

J'ai testé l'exercice sur les nodes, mais j'ai une erreur de syntaxe avec le "\n". Je suis sur Windows PowerShell, une idée ?

20/12/2019 à 19:55
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

JSONPath est assez limité pour ça. Si le champ manque, il s'arrête. Pour éviter de tout casser, utilise -o custom-columns, c'est beaucoup plus tolérant aux valeurs manquantes.

20/12/2019 à 13:40
madeleine-denis
Membre Actif
Avatar de madeleine-denis
madeleine-denis
Membre Actif

Comment on fait pour gérer les erreurs quand une clé est manquante ? Ça me pète à la gueule dès que le champ n'existe pas sur un pod.

20/12/2019 à 07:30
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

C'est rare que ça vienne de la version. Vérifie que tes pods ont bien des containers définis. Lance juste kubectl get pods -o json et regarde si la clé spec.containers existe bien. Si c'est vide, c'est normal que ton path ne sorte rien.

20/12/2019 à 01:04

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire