Archives de l’auteur : xavki

Sur les traces de Strace…

J’avance toujours sur la playlist ansible avec la 125ème vidéo dédiée au développement de votre propre module. C’est sympa ansible mais ça fait pas tout. C’est un outil parmi tant d’autres à découvrir et à connaître. Et si vous me suivez régulièrement, j’aime explorer des outils récents et d’autres un peu moins récents… mais tout aussi nécessaire… voir plus.

Strace fait partie de cette classe d’outil sur lequel vous pouvez vous investir durablement et en profondeur. Et cela sans que cette connaissance ne puisse être remise en cause par une nième technologie qui vient mettre au placard ce que vous avez appris.

C’est pour cela qu’apprendre les rudiments du système demeurent et resteront longtemps valables. D’autant plus que celui-ci n’évolue pas si vite et ne va pas disparaitre ou changer complètement du jour au lendemain. C’est donc un placement sûr et durable. Et il faut toujours garder cela en tête… Et comme les vieux langages reprennent de la valeur avec le temps, je suis persuadé que des bases solides en système reprendront de la valeur quand cette compétence se fera plus rare avec l’émergence des clouds et autres couches permettant parfois de réduire les connaissances du système.

J’ai donc décidé de commencer cette formation strace sous forme de playlist. Certains n’y apprendront rien je m’en doute mais ce que je veux c’est initier des réflexes dans l’approche du troubleshooting et du debug. Et à travers celà renforcer et consolider ses bases en système.

Les origines de Strace

J’aime revenir aux sources avant de commencer à apprendre à utiliser une technologie. Cela permet de se mettre dans le bain tranquillement.

Alors Strace commence initialement en 1991 du côté de SunOS avant de rejoindre Linux en 1992. Donc on peut considérer que ce projet a plus de 30 ans !!! c’est magnifique tout de même.

Le site officiel : https://strace.io/

Le dépôt github : https://github.com/strace/strace

Maintenant il est embarqué sur la plupart des distributions Linux. Il faut dire qu’il se base sur un syscall un peu dédié à savoir ptrace (le comble pour un outil qui trace les syscalls).

Mais alors comment résumer un syscall ? Un appel système c’est le moyen de communiquer avec le kernel (noyau), à partir du user mode. Ce dernier c’est ce que nus utilisons au quotidien, là où tourne : les applications, le terminal, votre navigateur….

Un syscall est une fonction avec un objectif bien défini pour utiliser le kernel. Sur linux on compte environ 300 syscalls. D’ailleurs on ne les utilise pas souvent en direct on passe souvent par la LibC. Et pour les trouver rien de plus simple, il suffit de se rendre dans le chapitre 2 du man pour y découvrir leur documentation à commencer par :

man 2 syscall

Eh oui pas besoin d’en faire des tonnes.

Et vous pouvez y retrouver le fameux ptrace :

man 2 ptrace

et notamment la manière de l’utiliser en C :

       #include <sys/ptrace.h>
       long ptrace(enum __ptrace_request request, pid_t pid,
                   void *addr, void *data);

Et là on voit que l’on va travailler principalement avec les PID et donc les processus. Donc strace trace les processus via leurs syscalls.

Tout le monde ne peut pas tracer

On en entend pas souvent parler mais tout le monde ne peut pas tracer. Généralement on passe un petit coup de sudo et on en parle plus mais c’est plus fin que cela tout de même.

Un paramètre du kernel Linux permet de fixer cela dans :

/proc/sys/kernel/yama/ptrace_scope

Avec les valeurs :

0 : même UID
1 : ascendance (sinon élévation de privilèges)
2 : admin seulement
3 : interdit

Donc on peut faire évoluer ce paramètre temporairement avec un :

sudo sysctl -w kernel.yama.ptrace_scope=3

on vient d’interdire temporairement l’utilisation de strace.

Ou encore de manière permanente :

sudo echo 0 > /proc/sys/kernel/yama/ptrace_scope

Car il faut le rappeler strace va nuire à la performance du processus sur lequel il va s’attacher. Oui c’est le terme à employer car vous allez le voir il ne lui lache pas les baskets.

Alors vous pouvez fair votre première trace d’un simple ls par exemple :

strace ls

Et l’output calme un peu au début, voir va en convaincre quelques uns de ne plus le réutiliser. Mais le bon réflexe c’est de se dire que ce n’est rien que des choses qu’il faut débrousailler petits morceaux après petits morceaux. Et chacun de ces morceaux apporte terriblement en connaissance du fonctionnement du système. En effet, pour chacun on peut creuser profondémment les choses.

Quelques options pour débuter tranquillement

Pour ne pas prendre peur, on va commencer par 3 options très simples :

  • s : permet de définir la longueur de la ligne d’output (si on résume). Par défaut à 32, on peut déjà utiliser un 80 voi run 1024 pour vraiment ne rien manquer.
  • p : très important car nous n’allons pas toujours avoir la chance de lancer un process via strace comme nous venons de le faire pour ls. Alors nous allons nous attacher à un processus qui tourne déjà grâce à l’option -p suivie du pid du process (attention aux forks on verra cela après).
  • o : l’output de strace n’est pas si évident que cela à capturer en effet il faut rediriger la sortie stderr vers stdout 2>&1, c’est pas très classe alors avec -o vous pourrez spécifier un fichier de sortie.

Donc une ligne de commande complète pour commencer gentillement serait :

strace -p <pid_du_process> -s 1024 -o strace.log

Voilà pour débuter avec strace. Bien sûr on ne va pas s’arrêter là car on a pratiquement rien découvert mais il faut bien commencer.

N’hésitez pas à rejoindre la chaine pour ne pas manquer les prochaines vidéos.

Les boucles with avec ansible

Continuons sur notre formation ansible. Alors que j’ai tourné la 123ème d’un cours qui sera assez complet sur ansible, je vous propose de continuer progressivement après notre article sur stat et register. Pour les personnes qui souhaitent accéder à ces vidéos sans attendre, elles sont déjà disponibles pour les membres VIP de la chaine xavki qui la soutiennent.

En matière de formation, je pense qu’il faut être progressif et patient. C’est pour cela que je préfère aborder quelques notions au début mais sans brûler les étapes.

Aujourd’hui nous allons nous former à l’utilisation des boucles dans ansible. Les principales sont faciles à retenir car elles commencent par : with_*. La plus répandu étant with_items.

Avant de commencer, il me semble nécessaire de préciser que ansible est en cours d’évolutions dans ce domaine. L’objectif est de basculer à loop et remplacer potentiellement les with_*. Pour le moment nous n’en sommes pas là et les with_* sont plus faciles à aborder et retenir pour commencer. La documentation précise bien que cette migration ne se fait pas rapidement et que with_* possède encore de beaux jours devant lui, on est loin de le voir déprécier.

Les différentes boucles possible avec with

Si loop ne remplace pas encore les with, c’est essentiellement car il en existe de nombreux et que chacun dispose de boucler sur une fonctionnalité particulière :

  • with_items : sur une liste de dictionnaire (ensemble de clefs/valeurs)
  • with_nested : sur une liste de listes
  • with_dict : parcourir un dictionnaire
  • with_fileglob : sur une liste de fichiers de répertoire avec ou sans pattern mais non récursif
  • with_filetree : sur une liste de fichier d’une arborescence (recursif) et avec pattern
  • with_together : permet de croiser 2 listes
  • with_sequence : pour parcourir un range (interval)
  • with_random_choice : tirage aléatoire dans une liste
  • with_first_found : sur le premier élément trouvé d’une liste
  • with_lines : pour parcourir chaque ligne d’un programme (exemple : shell)
  • with_ini : pour parcourir un fichier au format ini
  • with_inventory_hostnames : pour récupérer et parcourir des éléments d’un inventaire

On a donc du choix, mes préférés étant with_items et with_fileglob principalement.

Comment utiliser with_* avec ansible ?

C’est très simple. Les éléments d’entrées sont définis dans le with_* et en sortie sont utilisable par une variable « item ». En cas d’éléments si disposant de plusieurs clefs ont les utilisera avec « item.clef1 », « item.clef2″…

Dans le cas le plus simple nous pouvons commencer par parcourir une simple lite d’éléments :

  - name: boucle création de répertoire
    file:
      path: /tmp/xavki/{{ item }}
      state: directory
      recurse: yes
    with_items:
    - xavki1
    - xavki2
    - xavki3
    - xavki4

Ou encore, dans un playbook, nous pouvons faire un test avec une liste de dictionnaires :

  - name: création de fichiers
    file:
      path: /tmp/xavki/{{ item.dir }}/{{ item.file }}
      state: touch
    with_items:
    - { dir: "xavki1", file: "fichierA"}
    - { dir: "xavki2", file: "fichierB"}
    - { dir: "xavki3", file: "fichierC"}
    - { dir: "xavki4", file: "fichierD"}

Nos clefs sont « dir » et « file » et donc nous allons les utiliser avec item.dir et item.file. Ansible fait le reste pour parcourir la boucle. C’est assez facile pour débuter !!! ou encore en passant par une variable.

  vars:
    fichiers:
    - { dir: "xavki1", file: "fichierA"}
    - { dir: "xavki2", file: "fichierB"}
    - { dir: "xavki3", file: "fichierC"}
    - { dir: "xavki4", file: "fichierD"}
  tasks:
  - name: création de fichiers
    file:
      path: /tmp/xavki/{{ item.dir }}/{{ item.file }}
      state: touch
    with_items:
    - "{{ fichiers }}"

Alors maintenant imaginons que nous souhaitions parcourir les machines composant un groupe de notre inventaire. Le premier réflexe en méconnaissant les boucles serait de faire la chose suivante :

 with_items:
    - "{{ groups['all'] }}"

C’est fonctionnel car on pourra bien récupérer la liste des machines avec la variable « item » de notre with_items. Mais nous l’avons vu , il existe un with dédié à cette tâche with_inventory_hostnames. Ainsi nous pouvons le faire de cette manière :

  - name: création de fichiers
    file:
      path: /tmp/{{ item }}
      state: touch
    with_inventory_hostnames:
    - all

Les boucles un outil indispensable

Clairement nous ne verrons pas d’exemples dans cet article. L’idéal pour manipuler les boucles c’est la pratique d’exemples réels. Cela fera l’objet des TP.

Ainsi les boucles vont nous permettre de définir des variables de types dictionnaires de manière à être en mode descriptif et avoir des blocs qui représentent notre infrastructure. Le with_fileglob nécessite un peu plus de pratique et de recul sur la manière d’organiser un code d’infra as code. Ainsi, nous allons pouvoir nous en servir pour sépcifier un répertoire contenant des usitsateurs : clefs ssh, login… Et une fois cela réalisé il ne restera qu’à récupérer les variables contenues dans ces fichiers. Ce point est l’un de mes préférés sur ansible donc nous n’y couperons pas.

Si vous souhaitez ne pas manquer les prochaines vidéos, vous pouvez vous abonner. Et pour m’aider encore plus vous pouvez éventuellement liker les vidéos.

AWK et sa fonction system tellement pratique

Hello les ami(e)s !!! J’espère que vous allez bien dans cette période difficile à l’approche d’un durcissement de confinement. Difficile de pouvoir reprendre une vie normale alors que nos hôpitaux se remplissent.

Cependant il faut continuer à garder le moral et alles de l’avant. Certes le soleil nous donne un peu plus envie d’aller dehors mais il redonne tout de même une belle dose d’espérance.

Bref aujourd’hui parlons ou reparlons de awk. C’est souvent un outil méconnu ou tout du moins que l’on connaît pour faire des choses très simples et on se limite dans son utilisation grâce aux facilités apportées par la ligne de commandes (pipe etc).

AWK la simplicité à l’état pur

Je vous rappelle que j’avais fait il y a pas loin de 2 ans quelques tutos en guise de formation à awk. Ce petit cours de awk se limite à du petit oneline mais il permet déjà de faire des choses supers sympas je trouve :

  • élimination des doublons
  • compteurs
  • analyse de logs
  • conditions
  • génération de sql

Vous pouvez retrouver tout cela dans la playlist dédiée au scripting saison 1.

Mais parfois avec un petit rien en plus et on peut faire vraiment beaucoup plus. Je ne vous parle pas là de créer un vrai script AWK, multiligne. Non on reste dans le oneline avec encore un gros degré de simplicité.

Alors pour la démo prenons la CLI kubectl pour manipuler les pods. Je pars de cette commande mais vous pouvez partir de tout ce que vous souhaitez, l’idée est de manipuler la CLI.

Donc prenons la liste des pods avec un petit filtre pour afficher qu’une colonne.

kubectl get pods -o wide | awk '{print $6}'

Collectons la colonne des ip des pods (d’où le $6). Et maintenant pour manipuler un peu plus nous pouvons par exemple filtrer sur le statut des pods et leurs ips.

kubectl get pods -o wide | awk '($3 ~ "Running") && ($6 ~ "10.233.64.1.*") { print $6}'

Et notre commande system ?

On combine donc deux conditions. avec && et on applique un ~ pour la recherche sur base de regex.

C’est déjà pas mal mais là on se dit ça serait kool de lister tous les pods et de leur appliquer une commande system.

Concentrons nous juste sur un ping par exemple :

kubectl get pods -o wide | awk '($3 ~ "Running") && ($6 ~ "10.233.64.1.*") {print $1;system("ping -c 1 "$7)}'

Et on oubliera pas l’option -c1 pour ne pas boucler sur ping et ne réaliser qu’un seul ping (on pourrait définir un timeout plus approprié).

Nous avons simplement utilisé la fonction system de awk pour passer une commande… système. Simple est kool. On retrouve finalement ce que sait très bien faire xargs.

Alors avec notre kubectl on peut faire finalement quelque chose d’utile comme par exemple supprimé tous les pods en état evicted :

kubectl get pods -o wide | awk '($3 ~ "Evicted") {print "\n Drop >> "$1;system("kubectl delete pods "$1)}'

Et oui on retrouve là toute la facilité de awk car en plus vous le remarquez, on se permet même d’écrire une ligne avant. On pourrait en écrire une après ou encore faire un compteur pour dire le nombre de pods traités. Simple non ?

Bref AWK dans ce cas de figure permet de faire du personnalisable avec très peu de chose et sa fameuse commande system.

Alors si vous aimez ce genre de choses ou ces thématiques, venez vous joindre à la communauté Xavki. Vous pouvez aussi vous abonner pour ne pas manquer les prochaines vidéos.

L’objectif de la chaine est simple : se former et progresser ensemble

Enfin si vous voulez vous faire la main avec bash et si vous disposez de légères notions avec docker, vous pouvez vous rendre sur cette série de vidéos. Une formation qui vous conduira à réaliser un script bash permettant d’instancier des conteneurs docker avec systemd et ssh.

Un bon moyen de joindre l’utile à l’agréable avec un poil de docker et à la sortie la possiblité d’utiliser des conteneurs comme des machines virtuelles avec un gros gain de temps au provisionning.

Se prendre au jeu de AWK

Enfin si vous avez du temps et que vous êtes du genre curieux. Vous pouvez poursuivre sur le chemin de awk. En scriptant bien sûr et en utilisant des évolutions de ce langage comme le gawk ou encore le mawk. Ce dernier m’a été évoqué en parlant de performance. Il semblerait le plus rapide pour processer de la données réparties sur différents fichiers. Un article fait un petit focus sur les performances du mawk ici.

Cependant après avoir fait quelques tests maisons je ne parviens pas à des resultats explicites pour pouvoir en faire une réelle démonstration.

Toujours sur la performance en matière de processer du fichier text, vous pouvez aussi vous reporter à cet article. Celui-ci fait une analyse comparative entre le nawk, gawk et mawk assez intéressante. Il s’agit de faire un comparatif sur l’utilisation de la mémoire par ses derniers.

Formation SSH, les bases…

Si vous utilisez linux (et potentiellement windows) au quotidien et que vous êtes amenés à travailler avec des serveurs, vous ne pouvez vous passer de ssh. Certes, une bonne automatisation d’infrastructure peut vous permettre de limiter son utilisation mais rare est une journée sans ssh.

Mais finalement qu’est-ce que SSH ? le connait-on vraiment assez ? Voilà ce que je vous propose de découvrir dans la formation SSH. Cet ensemble de tutoriels permet pour les débutants de mieux comprendre leur environnement de travail et pour d’autres peut être de reposer les bases ou encore découvrir des astuces.

Qu’est-ce que SSH ?

C’est trivial mais il faut bien repartir de quelque chose. SSH cela signifie Secure Shell… comme on dit ça casse pas 3 pattes à un canard mais pourtant c’est terriblement utile et efficace.

Il faut voir d’où l’on vient et à quelle époque nous sommes. Dans un passé informatique plus lointain, la communication avec les serveurs se faisait avec des outils non sécurisés ou peu sécurisés comme par exemple telnet ou encore rsh (remote shell). Désormais, on utilise telnet rarement pour des tests simples comme la vérification d’ouverture de ports ou encore le test l’envoi de mail via un serveur smtp.

Ces outils non sécurisés sont de nos jours à éviter voir à bannir. Les pirates informatiques n’ont plus besoin que nous leur ouvrions les portes déjà assez difficiles à maintenir fermées.

Bref la sécurité informatique commence dès l’installation d’un serveur et à tous les niveaux.

Pour cela, SSH se base bien sûr sur de la cryptographie assez poussée. C’est d’ailleurs pour cela que tout le monde l’utilise et que toute brèche ne traîne pas à être patchée. Il se base sur la bonne vieille mais efficace méthode de client/serveur.

SSH a deux objectifs principaux :

  • lutter contre l’interception : c’est à dire qu’une personne qui écoute la communication entre un client et un serveur puisse accéder à ses informations
  • lutter contre l’usurpation : pour éviter que le client se fasse passer le serveur et inversement

Du coup on parle souvent de tunnel SSH avec ce sentiment d’assurer une communication sécurisée entre deux protagonistes avec une isolation totale.

Pour son chiffrement, SSH utilise deux phases :

  • un chiffrement asymétrique : avantage sa sécurité et inconvénient sa rapidité
  • un chiffrement symétrique : avantage sa rapidité et inconvénient la sécurité

Le déroulé d’une communication est la suivante :

Communication SSH :

  1. Client > Serveur : TCP – initie la connexion – poignée de main (handshake) SYNchronize
  1. Serveur > Client : TCP – réponse handshake SYN/ACKnowledge
  1. Client > Serveur : TCP – confirmation handshake ACK
  1. Client > Serveur : SSH – Version serveur
  1. Serveur > Client : SSH – Version client

…initialisation de la clef

  1. Client > Serveur : SSH – requête Diffie Hellman (objectif définir clef symétrique)
  1. Serveur > Client : SSH – envoi de la clef symétrique chiffré par la clef publique asymétrique
  1. Client > Serveur : SSH – début des échanges par le chiffrement de la clef symétrique

L’installation d’un serveur SSH

Dans mon cas je parlerai pour debian mais sur redhat et sa famille, le principe est le même :

sudo apt install openssh-server

sudo systemctl start sshd

Désormais votre serveur écoute avec le port par défaut à savoir le port 22 sur vos interfaces et donc toutes ses ips.

Ensuite, la configuration passe par le fichier /etc/ssh/sshd_config

Sans rentrer dans d’importants détails, voici l’interprétation de différents paramètres (je vous recommande vivement en cas de modification de paramètres ssh de toujours ouvrir 2 sessions en cas d’erreur cela vous permettra de revenir dessus) :

AcceptEnv : fixer les variables d'env pouvant être importées via le client

AllowAgentForwarding : permet de conserver votre clef (ex : rebond)

AllowGroups / DenyGroups : limiter les groupes à se connecter via ssh

AllowUsers / DenyUsers : limiter les users

Banner : ajouter une bannière à la connexion ssh

Password : mettre les deux à no pour disable password

ChallengeResponseAuthentication - RFC 4256 > poser des questions à l'utilisateurs (password..) > plus sécurisé

PasswordAuthentication - RFC 4252 > specific au password

ChrootDirectory : spécifier au chroot pour users/groups (utilisé avec match généralement)

Ciphers : combinaison des algorithmes d'échange

ClientAliveCountMax : le nombre connexion sans réponse avant cloture de la connexion

ClientAliveInterval : durée de la connexion ssh sans activité (envoi une requête si sans réponse = déconnexion)

Compression : defaut yes

DisableForwarding : supprime les fowarding agent, x11...

ExposeAuthInfo : permet d'afficher des informations l'authentification (path du fichier dans SSH_USER_AUTH)

FingerprintHash : type de hash pou rle fingerprint

ForceCommand : commande exécutée à la connexion (bypass les commandes clientes)

GatewayPorts : désactivation du port forwarding possible (no)

HostbasedAcceptedKeyTypes : type de clefs accepté : edcsa, rsa...

HostbasedAuthentication : authentification sur la clef par host (pas par user)

HostKey / HostCertificate : localisation des fichiers de clefs ou certificatss

IPQoS : limitation de service via débit et/ou délai

Kerberos Authentication : activation de l'authentification via kerberos

ListenAddress : interface/ip d'écoute

LoginGraceTime : délai pour s'authentifier (120 secondes par défaut)

LogLevel : niveau de logs

Match : permet de conditionner une liste d'acions sous condition

MaxSessions : connexions permisses par connexion réseau

PermitEmptyPasswords : permettre un password vide

PermitOpen : quel port forwarding est autorisé

PermitRootLogin : autorisé la connexion en tant que root via ssh (défaut prohibit-password)

PermitUserRC : permettre l'utilisation d'un ssh rc (~/.ssh/rc) = similaire à profile

Port : spécifier le port d'écoute du serveur ssh

PrintLastLog : spécifie la denrière connexion réalisé sur le serveur à la connexion suivante

PrintMotd : affichage d'un message d'accueil (similaire à banner)

PubkeyAcceptedKeyTypes : type de clefs publiques autorisées

PubkeyAuthentication : autoriser ou non l'authentification par clef

StrictModes : vérifie les fichiers et directories avant d'accepter la connexion

SyslogFacility : format des logs

UsePAM (Pluggable Authentication Module) : utilisation du module PAM

X11Forwarding : authoriser le forward x11 (serveur graphique)

A savoir qu’une partie de ces paramètres peuvent être spécifiques à certains utilisateurs ou groupes. Attention pour réaliser ce cas d’utilisation vous devez utiliser 2 Match. Le premier pour spécifier votre bloc aux caractéristiques particulières, le second pour revenir à ALL c’est à dire applicable à tous les utilisateurs.

Match User xavki
Banner /etc/banner.txt
X11Forwarding no
Match All

Je le répète si vous modifiez une configuration SSH ouvrez toujours deux sessions. Cela vous évitera de vous couper la patte et en cas d’erreur de revenir en arrière.

Une fois la modification réalisée vous pouvez redémarrer le service systemd qui le gère :

sudo systemctl restart sshd

Ne vous inquiétez pas, le restart maintient les connexions actives.

Connexion avec un client

Là encore très simplement on va utiliser apt notre gestionnaire de paquets :

sudo apt install openssh-client

Ensuite c’est très facile de vous connecter à un serveur ssh. Si celui-ci accepte une connexion avec le mot de passe du user distant vous pouvez tester et que le port ssh (22) accepte les connexions externes (ou au moins la votre) :

ssh myuser@monhost

Bien sûr il n’est pas recommandé d’utiliser le mot de passe pour vous connecter. En général on autorise peu d’utilisateurs à se connecter avec un mot de passe sur un serveur ssh (voir pas du tout).

Nous apprendrons dans un prochain article comment créer ce que l’on appelle une clef ssh qui finalement repose sur deux clefs : publique et privée.

N’hésitez pas à regarder les tutoriels de la chaine xavki ;). Vous pouvez aussi me soutenir en devenant membre de celle-ci ou encore simplement liker et partager ces vidéos.

Se recentrer sur la formation et les tutorials…

Hey ! Bonjour à tous !!

J’espère que vous allez bien ? Moi ça va plutôt bien et je vous propose aujourd’hui de faire un petit point sur la chaine et les évènements passés et à venir.

Maîtriser son temps

Vous le savez l’activité de la chaine youtube (et autour de celle-ci) demande plutôt pas mal de temps. En moyenne on peut dire autour de 3,4,5 heures par jour. C’est une charge assez importante en parallèle de mon job et de ma vie de famille.

Et souvent, en tant que devops, j’aime bien prendre du recul. Et en tant que SRE, j’aime bien avoir quelque chose que je maîtrise.

En prenant du recul, voilà ce que j’ai noté comme éléments dans le cadre de cette remise en question :

  • la chaine demande du temps (cqfd)
  • la présence sur les réseaux sociaux demande du temps
  • le forum discord demande également du temps
  • mon plaisir est la production de tutos et l’amélioration de ces formations
  • je ne cherche pas la notoriété ou l’influence
  • je veux garder de la liberté et donc je veux pas chercher du sponsoring
  • les visites venant de discord et de twitter sont très faibles (moins que ce blog)

En outre, j’ai fait le constat que mon temps passé à regarder le forum et le compte twitter n’apportait pas d’éléments à ma veille et n’influençait pas mes projets de production de contenus.

Bref, malgré 6700 followers sur twitter, je me suis dit je supprime le compte. Je préfère la suppression plutôt qu’avoir un compte fantôme (vide sans personne derrière).

Pour le discord je me suis posé pas mal de questions :

  • délégué le forum : j’avoue que ce n’est pas évident. Il faut trouver des gens avec qui on a les mêmes affinités et contrairement à ce que l’on pense ce n’est pas si facile. Chacun a son caractère, moi le premier.
  • supprimer : c’est une fin triste et cela ne me permettra pas de fédérer la communauté autour de la chaine. Néanmoins l’activité sur le forum n’est pas très dense et le taux de participation reste peu élevé (30 personnes tous les jours sur plus de 1500 membres).

Compte tenu de tout cela j’ai choisi de supprimer le forum. Et toujours la même chose, je veux passer du temps à faire du tuto et à former les gens débutants ou moins. Les discussions peuvent sembler intéressantes par discord ou twitter mais finalement l’impact est limité, on touche moins de personnes ramené au temps passé.

Et réduire les tamagotchis…

Je ne sais pas si vous êtes dans la même situation que moi mais nous disposons de beaucoup d’applications sur notre téléphone. Trop à mon goût.

Et bien souvent, toujours en prenant du recul, on constate que ces applis sont de vraies tamagotchis.

Pourquoi ? tout simplement car on est tenté en permanence d’aller regarder si on a rien de nouveau, si on a pas plus de followers, si quelques choses n’a pas bougé… L’inconvénient c’est que ça limite notre concentration sur les choses essentielles et plus utiles. On perd de fait en efficacité.

Les tutoriels en cours et à venir

Parlons un peu des sujets qui intéressent souvent.

Pour ce qui est en cours, je suis en train de terminer la formation ansible. Actuellement la playlist est composée de 120 vidéos. Je pense qu’il en manque encore une vingtaine. Après je ferais une pause sur cette playlist que j’ai commencé en septembre dernier. J’ai vraiment cherché à atteindre un niveau qui me semble proche d’un cours ou d’une formation ansible digne de ce nom. Cela donne au final environ 60h de vidéos assez exhaustive pour donner la capacité à débuter sereinement avec ansible. Seuls les éléments réseaux n’auront pas été évoqués dans cette formation. Un jour peut être un retour dessus.

Il me reste encore à aborder des choses comme : vagrant, collections, développement de modules, debugs…

Autre sujet que j’ai commencé c’est la formation dédiée à Helm. Un formidable outil qui est parfois méconnu. Là encore je vais chercher à me rapprocher du niveau d’un cours sur cette technologie.

Les vidéos de type 2 minutes marchent très bien aussi. On va donc poursuivre un peu avec un axe plus dédié à Linux ou des choses que je ne pourrais pas placer dans une playlist. Donc c’est encourageant.

Dans ce qui est à venir ?

  • saltstack : pas forcément avec un niveau aussi élevé que ansible car je n’ai pas assez de recul dessus
  • couchbase : une superbe base de données nosql et assez polyvalente avec de grosses performances
  • rabbitmq : un classique pour débuter dans le domaine de queues
  • terraform : pour y mettre quelques exemples d’utilisation dans le cloud car je l’ai un peu mise de côté
  • kubernetes : beaucoup de chose encore à voir dans ce domaine (on en finira jamais)
  • GCP : après avoir fait de la découverte de AWS il me semble bien de voir d’autres cloud
  • refaire un peu de packer
  • et de nombreux autres sujets et idées sous réserve de temps

Réduire mon exposition

Globalement, vous l’avez compris je cherche à me recentrer sur la chaine Xavki. Je ne veux pas m’exposer ou en tout cas tenter de le faire à minima. Pour linkedin je n’envisage pas la suppression. Cela serait assez compliqué pour moi.

Je ne cherche pas à être connu, je cherche à ce que les gens qui en ont besoin connaissent la chaine. Je ne cherche pas à faire en sorte que la chaine soit une activité professionnelle. Les recettes dégagées pour la chaine sont soigneusement mis de côté pour un projet à caractère social (du vrai).

Débuter avec Flux sur Kubernetes

Lors d’un précédent article, nous avions découvert l’intérêt de Helm. On peut le résumer à un outil de templating et de packaging dédié à Kubernetes. On dipose d’un bon outil pour industrialiser vos déploiement l’orchestrateur de conteneurs.

Cependant, Helm ne dispose pas de capacités nécessaires pour déployer ses charts ou plus simplement ses déploiements. Il lui faut donc un outil pour l’aider à accomplir une tâche plus complète de CI/CD.

Ainsi, Flux fait partie de ses outils complémentaires à Helm. Cet outil créé par Weave permet de gérer le déploiement à partir d’un dépôt (qu’il vienne de github ou de gitlab…).

Ainsi la combinaison de ces deux outils permet la répartition des tâches suivantes :

  • helm : via les charts, vous pouvez décrire et templatiser les différentes ressources kubernetes pour vos déploiements
  • flux : permet de synchroniser à fréquence régulière des dépôts (pouvant être des charts helm mais pas nécessairement). Flux permet également de gérer les mises à jour d’images (docker).

Flux est donc un outil important pour la mise en oeuvre d’une stratégie de gitops à partir d’un mode pull. En effet, flux, une fois installé, tire les éléments dans le cluster.

Principales fonctions de flux

Les principales fonctionnalités de flux sont les suivantes :

  • scrutation à fréquence régulière d’un dépôt git (5min par défaut)
  • définition de branches ou tags à prendre en compte
  • déployable sous forme d’opérateur dans k8s
  • mise à disposition d’un client fluxctl pour gérer les interactions avec l’opérateur (gestion des version, rollback…)
  • capacité de garbage collector pour nettoyer les ressources n’existants plus dans le dépôt
  • mise à disposition d’un provider terraform pour flux (et pour helm)

Installation de flux

Comme de nombreux outils associés à k8s, flux se base sur le kubeconfig local. Ainsi il peut rapidement et facilement se connecter à un cluster et éventuellement passer sur un autre cluster.

Comment l’installer ? Commençons par installer le client qui pourra ensuite installer l’opérateur pour vous.

Si vous utilisez ubuntu et snap

sudo snap install fluxctl

Sinon vous pouvez installer directement le binaire de cette manière :

wget https://github.com/fluxcd/flux/releases/download/1.21.0/fluxctl_linux_amd64
sudo mv fluxctl_linux_amd64 /usr/local/bin/fluxctl
sudo chmod 755 /usr/local/bin/fluxctl

Maintenant que le client est installé, il est en mesure d’utiliser votre kubeconfig. Vous pouvez donc passer la commande suivante (à adapter à votre situation).

kubectl create ns fluxcd

fluxctl install --git-email=moi@moi.com --git-url=git@gitlab.com:xavki/testflux.git --git-path=workloads --namespace=fluxcd | kubectl apply -f -

Nous créons donc un namespace dédié à flux et nommé fluxcd.

Puis nous lançons la commande fluxctl install en précisant :

  • –git-email : le mail (sans incidence)
  • –git-url : la localisation du dépôt à synchroniser en utilisant une connexion ssh
  • –git-path : le ou les répertoires à synchroniser
  • –namespace : le namespace où l’opérateur sera installé
  • et enfin on pipe la sortie dans un kubectl apply

A partir de cette étape flux est installé et dispose d’une clef privée. Nous devons donc ajouter la clef publique pour donner à flux la permission d’utiliser le dépôt git en question. Vous pouvez récupérer cette clef publique avec cette commande :

fluxctl identity --k8s-fwd-ns fluxcd

Voilà ! Nous venons de faire nos premiers pas et flux est installé. Il commence déjà à synchroniser les fichiers de ressources kubernetes contenues dans ce répertoire.

Si vous souhaitez en savoir plus sur Helm, je vous invite à regarder la formation Helm disponible dans cette playlist.

Stat et Register, indispensables pour commencer avec ansible

Le cours ansible en ligne avance petit à petit car j’ai réalisé un peu plus de 115 vidéos tutoriels pour le moment ( et c’est pas fini 😉 ). Cette formation est disponible en totalité pour les membres vip pour le moment. Mais ces vidéos deviennent disponible publiquement au fur et à mesure des mois et des semaines. Devenir membre permet de soutenir la chaine xavki.

La dernière vidéo publiée s’adresse plutôt aux débutants avec 2 éléments utiles au quotidien dans vos développements ansible : le register et le module stat. J’ai trouvé cela intéressant de les associer car on le fait cela souvent dans la pratique.

Le module stat de ansible

Idéal pour commencer, ce module ansible permet de vérifier notamment l’existence ou non de fichiers ou de répertoires. Mais pas seulement, le module stat s’apparente aux données accessibles via la commande stat sous linux.

Ainsi une commande stat fournie les principales informations fournies par les inodes. On pourrait résumer cela aux metadatas de votre filesystem.

oki@doki ~/playground/centreserver $ ▶ stat deploy.sh
File: deploy.sh
Size: 3710 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 11274196 Links: 1
Access: (0755/-rwxr-xr-x) Uid: (1001/ oki) Gid: (1001)
Access: 2021-03-09 15:49:37.803546224 +0100
Modify: 2021-02-09 18:29:07.371956532 +0100
Change: 2021-02-09 18:29:07.371956532 +0100
Birth: -

Je vous propose donc de créer un fichier avec ansible et lancer dessus le mode stat en deuxième task.

  - name: création d'un fichier
    file:
      path: /tmp/xavki.txt
      state: touch
      owner: xavki

puis lançons le module stat :

  - name: check avec stat
    stat:
      path: /tmp/xavki.txt

Les paramètres de ce module ansible sont :

  • path : chemin du fichier ou répertoire
  • follow : suivre les liens symboliques
  • get_checksum : récupérer la checksum
  • checksum_algorithm : type de checksum (md5, etc)
  • get_mime: récupération du type de données

Mais une fois que l’on a fait cela on ne dispose pas encore des données collectées par le module. Pour cela nous avons besoin d’utiliser le register.

Le register, un ami pour vos modules

Si on devait résumer le register, on pourrait dire qu’il s’agit d’un créateur de variables. Il permet de récupérer les outputs/sorties des modules. En effet de nombreux modules permettent de récupérer des informations lorsqu’ils sont exécutés. Par exemple, le module ec2 de aws va permettre de récupérer toutes les métadatas de l’instance créée.

Pour le module stat de ansible, il va récupérer les informations du fichier ou du répertoire en question.

Pour l’utiliser c’est très simple, il suffit de rajouter register et le nom de la variable créée qui contiendra le contenu de la sortie. Attention à l’indentation avec ansible, il s’agit de mettre le register au même niveau que le nom du module.

Ainsi nous pourrions avoir une succession de tâches suivantes :

  tasks:
  - name: création d'un fichier
    file:
      path: /tmp/xavki.txt
      state: touch
      owner: root
    when: xavki_file is defined
  - name: check avec stat
    stat:
      path: /tmp/xavki.txt
    register: __fichier_xavki
  - name: debug
    debug:
      var: __fichier_xavki

La première pour la création du fichier.

La seconde pour passer un stat sur le fichier xavki.txt avec le register (création de la variable __fichier_xavki).

Et enfin pour visualiser le contenu de la variable obtenue, nous utilisons le module debug.

Bonne pratique : j’ai pour habitude de préfixer ce type de variables par un double underscore. Cela me permet d’une part de les identifier plus rapidement et d’autres part d’utiliser plus rapidement l’autocomplétion (par exemple dans vscode).

Dans le cas de stat, vous pouvez ensuite parcourir le contenu de cette variable ansible. Ainsi pour utiliser la valeur de stat et de la clef « exists » voici comment faire :

__fichier_xavki.stat.exists

Maintenant nous sommes donc en mesure de vérifier l’existence d’un fichier ou d’un répertoire et de conditionner la tache suivante à cela.

  - name: création répertoire xavki
    file:
      path: /tmp/xavki
      state: directory
    when: __fichier_xavki.stat.exists and xavki_file is defined

Mais je vous invite à vérifier le contenu de l’output en totalité et vous verrez que nous disposons des mêmes éléments que si nous avions lancé la commande linux.

Retrouvez les tutoriels ansible ici et abonnez-vous si vous souhaitez ne pas manquer les prochains articles ou vidéos.

Formation et cours complet Helm, c’est parti !!!

Kubernetes est un sujet qui passionne les foules. Je le vois tous les jours avec la playlist k8s. C’est pourquoi j’ai décidé de me centrer sur quelques outils assez courants pour les personnes qui administrent ou utilisent le célèbre orchestrateur de conteneurs. Même si je continue encore la formation ansible, je commence en parallèle une série de tutoriels dédiés à Helm.

Là encore un cours complet pour se former à son rythme que ce soit pour débuter ou aller plus loin. Pour cela on va reprendre toutes les bases pour monter petit à petit en niveau.

Aujourd’hui c’est la première donc du coup on va commencer par poser la première brique à savoir l’introduction à Helm et essayer de répondre à quelques questions : pourquoi ? comment ? intérêts ?…

L’instanciation, une problématique kubernetes

A l’heure actuelle, beaucoup d’entreprises passe à tort ou à raison sur kubernetes. Un bel outil qui permet de lancer des services en décrivant des ressources. L’outil étant assez élaboré, pour lancer une petite application, il est souvent nécessaire d’installer différents objets. En outre nous devons souvent coordonner les objets les uns par rapport aux autres à défaut de variables mutualisées en dehors des configmaps.

Or il est assez courant d’avoir une infrastructure plus ou moins à base de microservices, ces derniers se ressemblant fortement voir appelant de même lignes de codes/images ou nécessitant un déploiement similaire. Mais alors faut-il faire des copier/coller de toutes ces ressources avecs de répertoires et faire évoluer tout cela ensemble avec des difficultés pour modifier dans des manifestes communs plusieurs fois le même élément.

Prenons un exemple avec wordpress, pour créer une instance wordpress, il faut :

  • 2 deployments
  • 1 ingress
  • 2 pvc/pv
  • 2 services…

Créons ensuite une deuxième instance… rebelote et ainsi de suite. Faire cela dans un outil comme kubernetes cela nous fait penser que l’on a loupé quelque chose. Vaut mieux arrêter de travailler et compter les mouches, surtout le jour où il faudra faire évoluer tout ça.

C’est un des points majeurs que Helm permet de corriger.

Helm permet de templatiser des ressources et de stocker toutes les variables définies dans un seul fichier : Values.yaml.

On a donc fait un grand pas.

Mais ce n’est pas le seul intérêt pour Helm

Bien sûr Helm va bien plus loin que cela.

Finalement, une fois que l’on commence à templatiser, on s’aperçoit que l’on dispose de briques cohérentes de ressources. Il ne manque qu’une chose c’est la possibilité de les partager et faciliter leur installation et leur versionning.

Du coup, imaginons que Helm puisse être un gestionnaire de paquets façon apt, yum ou autres. Avec des dépôts distants, cela peut permettre de partager ces packages que l’on appelle simplement des Charts.

Et comme tous les packages, Helm permet de versionner tout cela pour garder des briques cohérentes, éviter les bugs et faciliter l’installation des objets kubernetes. Intéressant n’est-ce pas ?

Ajoutons à cela que Helm a su évoluer d’une version 2 un peu plus complexe vers une version 3 qui permet de se connecter facilement à votre cluster kubernetes.

Conclusion sur Helm

Bref se former à Helm ou l’adopter c’est un bon point pour votre carrière car vous serez peut être amené à le rencontrer et pourquoi pas le tester pour le faire entrer dans votre société. Donc suivre une formation Helm est certainement un bon investissement de votre temps.

Nous en reparlerons plus tard mais un dépôt Helm peut se limiter à un dépôt git assez épuré.

Ainsi vous pourrez trouver des intérêts :

  • meilleures capacités d’itération
  • amélioration du travail en équipe pour vos déploiements
  • utilisation de charts déjà développées par la communauté

Après ne nous cachons pas qu’il faut une petite période d’adaptation. Mais comme vous êtes là c’est que vous voulez apprendre à utiliser Helm et vous former donc je ne me fais pas de soucis pour vous.

Se former est une approche importante pour adopter ou devenir devops. Et n’oubliez pas de vous abonner à la chaine xavki 😉

Formation Ansible : créer un utilisateur avec le module user

Petit à petit, nous allons rentrer dans l’utilisation de ansible. En effet, il me semble logique de ne pas brûler les étapes pour apprendre mais surtout comprendre l’outil et ses principes.

Ansible est de plus en plus au coeur des orchestrations dans un esprit de devops. Il permet à partir de choses simples et descriptives de configurer et déployer des infrastructures mais aussi des applicatifs.

Dans cet article dédié à la formation à ansible, je vous propose de découvrir le module user. C’est un peu une base car il permet comme son nom l’indique de créer des users… et l’installation de serveurs ne se fait pas sans créer d’utilisateurs.

Ce module se base principalement sur les commandes : useradd, userdel, usermod…

Comme je le rappelle dans cette page, il prend de nombreux paramètres. Vous povuez aussi vous rapprocher de la documentation en anglais et plus complète du site de ansible.

Débutons par la mise en place et le premier run du module user

Le cas le plus simple pour commencer est de se créer un utiliseurs de démo. Pour cela il vous faut quelques serveurs (je vous invite à regarder mon article précédent pour vous créer des conteneurs docker similaires à des VM).

Ensuite bien sûr vous devez disposer aussi d’un inventaire et d’un playbook mais maintenant vous commencez à connaître.

Pour créer un user sans droits ni contraintes particulières, nous pouvons commencer par cette tâche.

- name: création de xavki
  user:
    name: xavki
    state: present
    password: "{{ 'password' | password_hash('sha512') }}"  

Nous utilisons bien « user » et lui passons 3 paramètres :

  • le nom : celui de l’utilisateur que nous voulons créer
  • le statut : est-ce que l’on souhaite qu’il soit créé ou supprimé (present/absent en anglais pour ansible)
  • le password : petite particularité c’est que celui-ci ne peut pas être complètement en clair (en théorie il ne doit pas l’être du tout mais nous n’avons pas encore vu dans cette formation ansible-vault). Donc nous utilisons le filtre jinja password_hash et lui précisons que nous voulons un hash de type sha512.

Et bien sûr nous lançons notre playbook :

ansible-playbook -i 00_inventory.yml playbook.yml

Ajoutons quelques paramètres pour mieux configurer notre utilisateur

Bien c’est un premier pas et vous pouvez vérifier cela en vous connectant sur une machine distante avec une simple commande comme :

id xavki

Mais admettons que nous souhaitions ajouter ce user à un groupe existant. On parle bien ici de l’ajouter et non pas d’écraser son groupe. Dans notre exemple, ajoutons-le au groupe sudo pour plus de liberté ;).

- name: création de xavki
  user:
    name: xavki
    state: present
    groups: sudo
    append: yes
    password: "{{ 'password' | password_hash('sha512') }}"  

On ajoute donc le paramètre group et le paramètre append à yes. Ce dernier assure que nous ajoutions bien le groupe au user et pas l’écrasement de son appartenance aux autres groupes.

Cependant, nous aimons associer une clef ssh à un utilisteur. Pour cela ansible permet différentes situations. Ici nous allons l’ajouter et voir le retour de la tâche de création user grâce à un debug.

  - name: création du user xavki
    user:
      name: xavki
      state: present
      generate_ssh_key: yes
      uid: 1200
      groups: sudo
      append: yes
      password: "{{ 'password' | password_hash('sha512') }}"
    register: mavar
  - name: debug
    debug:
      msg: "{{ mavar }}"

Et vous pouvez constater dans la sortie que l’on peut récupérer les éléments relatifs à la clef SSH.

Et nous pouvons bien lui ajouter un shell on retrouve les options de useradd en ligne de commande.

  - name: création du user xavki
    user:
      name: xavki
      state: present
      shell: /sbin/nologin
      generate_ssh_key: yes
      uid: 1200
      groups: sudo
      append: yes
      password: "{{ 'password' | password_hash('sha512') }}"
      password_lock: yes

Remarquez que là nous ajoutons un password_lock. Cela permet de conserver l’utilisateur tout en l’empêchant de se connecter.

Et enfin, vous l’avez deviné, nous allons supprimer cet utilisateur en passant simplement le nom et le status « absent ».

  - name: création du user xavki
    user:
      name: xavki
      state: absent

Et voilà nous venons de nous former à l’utilisation du module user de ansible.

Formation prometheus/grafana, promql suite

Lors de l’article précédent, nous avions découvert l’installation de la stack prometheus/grafana. Continuons pour découvrir aujourd’hui quelques rudiments du promql. Vous pouvez vous rendre sur cette page si vous souhaitez consulter toute cette formation prometheus/grafana gratuite.

Nous avions vu le principe de label dans prometheus à travers le langage promql. Ainsi, chaque ligne de métriques dispose d’autant de cardinalités qu’elles disposent de labels différents. Par exemple, si la métrique node_load_5 prend un label instance et un label datacenter, nous avons autant de cette métrique que d’instance pour l’ensemble des datacenters. C’est pourquoi certaines métriques peuvent être très lourdes en matière de traitement des métriques (des load-balancers par exemple). Et lorsque l’on utilise ces métriques il est nécessaires de les filtrer pour les exploiter.

Pour filtrer les métriques, il suffit de placer des requêtes sur les labels de la métrique en question. Par exemple sur le datacenter ou l’instance spécifiquement.

Ainsi on pourra utiliser des expressions régulières de cette manière :

node_network_receive_bytes_total{device=="eth0"}
node_network_receive_bytes_total{device=~"eth.+"}
node_network_receive_bytes_total{device=~"eth0|lo"}
node_network_receive_bytes_total{device!~"eth0|lo"}

Ainsi :

  • Le premier cas s’attache à une équivalence stricte.
  • Le second à une regex qui permettra de rappatrier toutes les métriques node_network_receive_bytes_total mais dont le label device commence par « eth » et est suivi d’au moins un caractère ou plus.
  • Le troisième dans le cas où pour la même métrique on souhaite rappartier soit les devices « eth0 » ou « lo ».
  • Enfin la différence en appliquant une regex.

D’autres opérations : le BY

Commençons par le regroupement grâce à l’opérateur « by » qui permet de faire l’équivalent de « GROUP BY » en SQL. Ainsi sur certaines fonctions comme les sommes, les comptages… vous pourrez regrouper ce calcul par un ou plusieurs labels. Par exemple pour compter le nombre de lignes de la métrique node_cpu_seconds_total par cpu, nous procéderons de la sorte :

count(node_cpu_seconds_total) by (cpu)

Ce qui nous permet, après avoir engendré un résultat d’une ligne par cpu, la possibilité de calculer le nombre de CPU :

count(count(node_cpu_seconds_total) by (cpu))

Et donc pour compter cela par serveur, il faudra ajouter le label « instance » à notre calcul

count(count(node_cpu_seconds_total) by (cpu,instance)) by (instance)

On compte donc dans un premier temps le nombre de ligne par cpu unqiuement pour regrouper cette métrique disposant de plusieurs lignes. Puis on compte le nombre de fois où l’on retrouve cette ligne regroupée pour avoir le nombre de cpu par instance.

Le facteur temps : offset et vector

Parmi les principaux éléments de temps importants dans prometheus, il en existe 2 :

  • le vector : c’est la plage de temps sur laquelle certains calculs vont être réalisés (une somme, une moyenne, une dérivée…)
  • l’offset : il s’agit du point de référence auquel vous souhaitez réaliser le calcul. Par exemple, il peut être intéressant de se placer 24h en arrière pour comparer avec les métriques actuelles…

Le range vector est intéressant pour les calculs mais aussi pour commencer pour voir le nombre de valeur sur lesquels on réalise un calcul. Ainsi si on passe un range vector de 3m à partir de maintenant sur une métrique on l’écrit comme ceci :

node_cpu_seconds_total[3m]

Cette requête va vous permettre d’afficher toutes les valeurs de la métrique node_cpu_seconds au cours de 3 dernières minutes. Plus le scrape est fréquent et plus vous avez de valeurs.

Les valeurs de cette requête sont classées par timestamp en format epoch. Vous pouvez néanmoins les convertir en format « humain » grâce à la commande date :

date -d "@1574340307.27"

Ainsi, pour calcculer une moyenne au cours des 3 dernières minutes, vous pouvez le faire de cette manière :

avg_over_time(node_cpu_seconds_total[3m])

Pour les offset, il suffit d’ajouter le mot offset. Prenons un exemple. Nous voulons comparer le nombre de requêtes actuelles avec celui d’il y a 5 minutes. Comme nous avons besoin de 2 courbes, nous allons faire deux requêtes.

La première qui collecte l’information sur le moment :

sum(http_requests_total)by (code)

Ensuite la seconde en demandant un offset placé 5 minutes en arrière :

sum(http_requests_total offset 5m)by (code)

Simple non ?

Les opérateurs

Dans les éléments simples à connaître pour débuter avec prometheus, il y a les opérateurs. Il s’agit de simple test conditionnels.

Par exemple, nous voulons savoir si une métrique est supérieur à 0.

Ainsi parmi les résultats, comme pour les labels, prometheus ne retournera que les métriques correspondantes. Et bien cûr cela peut se faire sur des résultats de fonctions (calculs).

Et on pourra aussi combiner les tests. Voici la liste des opérateurs promql disponibles :

    == (equal)
    != (not-equal)
    > (greater-than)
    < (less-than)
    >= (greater-or-equal)
    <= (less-or-equal)
    and (intersection)
    or (union)
    unless (complement)

Je vous propose un exemple simple :

node_load1 > 1.0 and node_load1<1.6

Dans ce cas nous retenons uniquement les métriques node_load inférieures à 1.6 et supérieure à 1.0. nous aurions aussi pu l’écrire de la manière suivante :

node_load1 > 1.0 <1.6

J’espère que cet article vous permettra de débuter le promql tranquillement et vous lèvera quelques doutes. N’hésitez pas à consulter les tutoriels prometheus/grafana sur la chaine xavki.

Un script bash et docker pour vous aider à développer des rôles ansible

Ce script n’a presque pas pris une ride depuis ces premiers pas sur le chaine youtube. Eh oui c’était la première vidéo de la chaine xavki. Je l’ai légèrement toiletté et j’ai bien sûr mis à jour l’image docker avec une version plus récente de Debian (10).

Il m’est très utilise pour mes formations ansible.

Lorsque j’ai créé ce script, j’avais besoin de tester régulièrement les rôles que je développais. J’utilisais déjà un peu vagrant et je trouvais que lancer une machine virtuelle demandais du temps. Et comme pour bien développer du ansible, il me semble très important de tout casser pour tout refaire, je me suis réorienté vers des conteneurs docker. Après coup, LXD/LXC serait encore plus optimal, ces conteneurs étant des conteneurs systèmes.

Bref, à l’époque j’ai creusé et cherchais comment avoir des conteneurs avec SSH et systemD. Finalement cela n’est pas très compliqué après avoir installé systemd, il suffit de supprimer quelques répertoires et de monter ceux de la machine en dessous.

Cependant attention, cela signifie aussi de lancer ces conteneurs en privileged. Donc tout cela cumulé, rend ce concept très défaillant d’un point de vue sécurité et non sécurisable. Il faut donc l’utiliser et supprimer les conteneurs après utilisation. En tout cas c’est ce que je recommande fortement.

Le Dockerfile d’une Debian avec SSH et SystemD

Je vous propose donc le Dockerfile suivant :

FROM debian:10

ENV container docker
ENV LC_ALL C
ENV DEBIAN_FRONTEND noninteractive

RUN echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/sources.list

RUN apt-get update \
    && apt-get install -y --no-install-recommends systemd python3 sudo bash net-tools openssh-server openssh-client vim git\
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -i 's/#PermitRootLogin/PermitRootLogin/' /etc/ssh/sshd_config
RUN rm -f /lib/systemd/system/multi-user.target.wants/* \
    /etc/systemd/system/*.wants/* \
    /lib/systemd/system/local-fs.target.wants/* \
    /lib/systemd/system/sockets.target.wants/*udev* \
    /lib/systemd/system/sockets.target.wants/*initctl* \
    /lib/systemd/system/sysinit.target.wants/systemd-tmpfiles-setup* \
    /lib/systemd/system/systemd-update-utmp*

RUN ln -s /lib/systemd/system /sbin/init
RUN systemctl set-default multi-user.target
RUN sed -i 's#root:\*#root:sa3tHJ3/KuYvI#' /etc/shadow
ENV init /lib/systemd/systemd
VOLUME [ "/sys/fs/cgroup" ]

ENTRYPOINT ["/lib/systemd/systemd"]

Plusieurs remarques donc :

  • on installe ssh et systemd
  • on permet le root login avec ssh
  • on supprime de nombreux liens systemd car notre conteneur ne dispose pas de son propre matériel
  • on définit un passsowr pour root (« password » par défaut)
  • on prévoit de monter /sysS
  • on lance en entrypoint : systemd (donc ssh n’est pas lancé en l’état)

Lancer un conteneur avec SSH/SystemD

Voici comment lancer avec un simple docker run un conteneur avec cette image

Là encore rien de très compliqué :

docker run -d --cap-add NET_ADMIN --cap-add SYS_ADMIN --publish-all=true -v /srv/data:/srv/html -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name <nom_contneeur> -h <nom_conteneur> priximmo/debian_systemd:v1.0

On permet une élévation de privilège de notre conteneur sur notre hosts sur les capabilities NET_ADMIN et SYS_ADMIN.

On publie tous les ports pour pouvoir utiliser les applicatifs sur l’ip du conteneur sans se poser de question.

On monte un répertoire d’échange entre le host et le conteneur pour /srv/data.

On monte en lecture seul /sys/fs/cgroup.

Maintenant on automatise le lancement des conteneurs avec un script bash

L’enjeu est tout de même de pouvoir créer à la volée des conteneurs. Et d’essayer de gagner du temps dans le développement ansible. Au passage, bien sûr, ce script est utilisable dans d’autres cas d’utilisation (testing, dev…).

Voici le script que je vous propose et que vous pourrez personnaliser et compléter à votre goût.

#!/bin/bash

############################################################
#
#  Description : déploiement à la volée de conteneur docker
#
#  Auteur : Xavier
#
#  Date : 28/12/2018 - V2.0
#
###########################################################


# Functions #########################################################

help(){
echo "

Options :
		- --create : lancer des conteneurs

		- --drop : supprimer les conteneurs créer par le deploy.sh
	
		- --infos : caractéristiques des conteneurs (ip, nom, user...)

		- --start : redémarrage des conteneurs

		- --ansible : déploiement arborescence ansible

"

}

createNodes() {
	# définition du nombre de conteneur
	nb_machine=1
	[ "$1" != "" ] && nb_machine=$1
	# setting min/max
	min=1
	max=0

	# récupération de idmax
	idmax=`docker ps -a --format '{{ .Names}}' | awk -F "-" -v user="$USER" '$0 ~ user"-debian" {print $3}' | sort -r |head -1`
	# redéfinition de min et max
	min=$(($idmax + 1))
	max=$(($idmax + $nb_machine))

	# lancement des conteneurs
	for i in $(seq $min $max);do
		docker run -tid --privileged --publish-all=true -v /srv/data:/srv/html -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name $USER-debian-$i -h $USER-debian-$i priximmo/buster-systemd-ssh
		docker exec -ti $USER-debian-$i /bin/sh -c "useradd -m -p sa3tHJ3/KuYvI $USER"
		docker exec -ti $USER-debian-$i /bin/sh -c "mkdir  ${HOME}/.ssh && chmod 700 ${HOME}/.ssh && chown $USER:$USER $HOME/.ssh"
	docker cp $HOME/.ssh/id_rsa.pub $USER-debian-$i:$HOME/.ssh/authorized_keys
	docker exec -ti $USER-debian-$i /bin/sh -c "chmod 600 ${HOME}/.ssh/authorized_keys && chown $USER:$USER $HOME/.ssh/authorized_keys"
		docker exec -ti $USER-debian-$i /bin/sh -c "echo '$USER   ALL=(ALL) NOPASSWD: ALL'>>/etc/sudoers"
		docker exec -ti $USER-debian-$i /bin/sh -c "service ssh start"
		echo "Conteneur $USER-debian-$i créé"
	done
	infosNodes	

}

dropNodes(){
	echo "Suppression des conteneurs..."
	docker rm -f $(docker ps -a | grep $USER-debian | awk '{print $1}')
	echo "Fin de la suppression"
}

startNodes(){
	echo ""
	docker start $(docker ps -a | grep $USER-debian | awk '{print $1}')
  for conteneur in $(docker ps -a | grep $USER-debian | awk '{print $1}');do
		docker exec -ti $conteneur /bin/sh -c "service ssh start"
  done
	echo ""
}


createAnsible(){
	echo ""
  	ANSIBLE_DIR="ansible_dir"
  	mkdir -p $ANSIBLE_DIR
  	echo "all:" > $ANSIBLE_DIR/00_inventory.yml
	echo "  vars:" >> $ANSIBLE_DIR/00_inventory.yml
    echo "    ansible_python_interpreter: /usr/bin/python3" >> $ANSIBLE_DIR/00_inventory.yml
  echo "  hosts:" >> $ANSIBLE_DIR/00_inventory.yml
  for conteneur in $(docker ps -a | grep $USER-debian | awk '{print $1}');do      
    docker inspect -f '    {{.NetworkSettings.IPAddress }}:' $conteneur >> $ANSIBLE_DIR/00_inventory.yml
  done
  mkdir -p $ANSIBLE_DIR/host_vars
  mkdir -p $ANSIBLE_DIR/group_vars
	echo ""
}

infosNodes(){
	echo ""
	echo "Informations des conteneurs : "
	echo ""
	for conteneur in $(docker ps -a | grep $USER-debian | awk '{print $1}');do      
		docker inspect -f '   => {{.Name}} - {{.NetworkSettings.IPAddress }}' $conteneur
	done
	echo ""
}



# Let's Go !!! ###################################################################""

#si option --create
if [ "$1" == "--create" ];then
	createNodes $2

# si option --drop
elif [ "$1" == "--drop" ];then
	dropNodes

# si option --start
elif [ "$1" == "--start" ];then
	startNodes

# si option --ansible
elif [ "$1" == "--ansible" ];then
	createAnsible

# si option --infos
elif [ "$1" == "--infos" ];then
	infosNodes

# si aucune option affichage de l'aide
else
	help

fi

Plusieurs options sont prévues :

  • –create : la création de conteneurs en ajoutant à cette option un nombre pour indiquer le nombre de docker souhaités
  • –drop : pour supprimer les conteneurs lancés avec ce script
  • –start : en cas d’arrêt et de relance de votre machine, les conteneurs seront stoppés, cette options permet de les relancer à la volée
  • –ansilbe : créé un répertoire dédié aux développements ansible avec notamment un inventory déjà rempli et complété par les ip de chacun des conteneurs
  • –infos : pour lister les ip des conteneurs créés

Bien sûr on organise tout cela avec des fonctions bash. La plus fournie étant la fonction de création qui notamment :

  • créé un user du même nom du user qui lance le script
  • lui définit un password par défaut à « password »
  • lui copie votre clef publique dans le authorized_keys
  • lance ssh (cf dans notre dockerfile on ne lançait que systemd et pas sshd)

Voilà, j’ai déjà eu pas mal de retour positifs ou de gens qui ont customisé ce script. Certains ont ajouté d’autres OS également. A vous de voir et de vous faire plaisir en personnalisant tout cela et en l’adaptant au mieux à votre cas d’utilisation.

Tout le code source est ici.

Kubectl quelques commandes utiles pour commencer

Pour débuter avec kubernetes, il faut aimer la ligne de commande et on peut y prendre un certain plaisir au fur et à mesure du temps. D’ailleurs, je ne saurais trop vous recommander si vous débuter de ne pas avoir recours aux alias et autres tools qui facilitent l’utilisation ou by-pass la CLI.

Eh oui personnellement je considère qu’il faut passer un peu de temps avec cette cli avant de passer aux tools. D’ailleurs, il y a tellement de tools qu’il vaut mieux se contenter de quelques uns (kubectx, kubens, k9s…).

Commençons

Pour débuter, nous avons bien retenu que pour lister tout objet/ressource dans kubernetes il faut utiliser kubectl get. Maintenant vous pouvez lister tous les objets de bases en utilisant :

kubectl get all

Et pour aller plus loin et récupérer tous les objets communs pour tous les namespaces :

kubectl get all –all-namespaces

Mais comment connaît les ressources justement ?

kubectl api-resources -o wide

Remarquez le -o wide qui permet d’avoir le maximum d’informations sur chacun des objets. On peut utiliser assez souvent cette option, par exemple sur les pods etc.

Et pour connaître l’état des composants principaux de votre cluster (etcd, kubelet etc), vous pouvez réaliser un :

kubectl get componentstatuses

Debugger pour un débutant ?

Débuguer dans un cluster kubernetes demande d’avoir des réflexes. Je vous en livre quelques uns pour commencer et petit à petit vous trouverez vos automatismes.

Là encore la ligne de commande est votre meilleure amie. Bien sûr tout commence par un :

kubectl get pods

Puis une fois le pod identifié, on va pouvoir d’une part regarder l’état de l’objet en question et ses caractéristiques :

kubectl describe pods <id_du_pod>

Et si finalement l’erreur mentionnée dans les events du bas de la page vous laisse penser qu’il s’agit d’un problème applicatif, vous pouvez vous référez aux logs du pods.

Si celui ne possède qu’un conteneur :

kubectl logs -f <id-pod>

Mais si vous voulez obtenir les logs d’un conteneur spécifiquement :

kubectl logs <id_pod> <nom_conteneur>

Et pour avoir les logs de tous les conteneurs fusionnés :

kubectl logs <id_pod> --all-containers

Vous pouvez également lister les évènements d’un pod :

kubectl get events <id_pod>

Et pour identifier le contenu du manifest du pod :

kubectl edit pod <id_pod>

Mais souvent il vous faudra revenir à l’objet qui a créé le pod à savoir un deployment, un statefulset ou un cronjob et vous pourrez visualiser aussi son manifest avec la commande edit :

kubectl edit deployment <nom_deployment>

Et pour récupérer le yaml du déploiement dans un fichier au format yaml :

kubectl get deployment <nom_deployment> -o yaml > monfichier.yaml

Mais si vous avez un doute sur la rédaction d’un objet/ressource utilisez explain. Par exemple pour la documentation sur les pods

kubectl explain pod

kubectl explain pod.spec

Si vous lez souhaitez, vous pouvez suivre ma chaine youtube et voir les vidéos relative à cette formation kubernetes gratuite ici.