cli
Journaux liées à cette note :
Quelques outils CoreOS : coreos-installer, graphe de migration et zincati
Cette note fait partie de la série de notes : "J'ai étudié et testé CoreOS et je suis tombé dans un rabbit hole 🙈".
Note précédente : "Fusion de CoreOS et Atomic Project en 2018".
coreos-installer
L'outil coreos-installer est un composant essentiel de Fedora CoreOS. Il propose différentes méthodes pour installer Fedora CoreOS.
La commande coreos-installer download permet de télécharger tout type de version de CoreOS, sous différents formats, par exemple iso, raw, qemu, cloud image, etc (toutes celles présentes dans la page download).
Ensuite, la commande coreos-installer install permet d'installer la version téléchargée vers un disque. Cette commande est par exemple disponible à la fin du boot d'une image ISO. Contrairement à Fedora Silverblue qui propose d'installer la distribution avec Anaconda, l'installation de CoreOS s'effectue en cli via coreos-installer install.
Ensuite, la commande coreos-installer install permet d'installer la version téléchargée sur un disque. Cette commande est notamment accessible après le démarrage d'une image ISO. Contrairement à Fedora Silverblue qui utilise l'installateur graphique Anaconda, CoreOS s'installe exclusivement en cli via coreos-installer install.
Toutefois, coreos-installer permet de préparer une installation automatique. La commande coreos-installer iso customize modifie une image ISO existante pour y intégrer directement une configuration ignition, rendant l'installation entièrement automatisée au démarrage.
Voici un exemple dans mon playground : atomic-os-playground/create-coreos-custom-iso.sh.
coreos-installer pxe permet aussi d'effectuer une configuration automatique par réseau, via PXE, mais je ne l'ai pas testé.
Graphe de migration de versions
Lors de mes tests d'upgrade de CoreOS à partir d'une ancienne release (environ n-10), j'ai constaté que la transition vers la dernière version ne se faisait pas directement mais nécessitait le passage par des versions intermédiaires.
J'ai découvert que CoreOS maintient un graphe qui définit le parcours d'upgrade requis. Certaines versions intermédiaires doivent être installées pour gérer des breaking changes, comme la migration de configurations.
zincati
Un autre composant important de Fedora CoreOS est zincati, le service responsable de l'exécution des mises à jour automatiques.
zincati décide d'effectuer les mises à jour en fonction du seuil de prudence de déploiement (rollout_wariness) et de la stratégie de mise à jour : immediate ou periodic (plage horaire définie dans la semaine).
CoreOS utilisant par défaut la stratégie immediate, zincati détecte automatiquement les nouvelles releases dès le premier démarrage et lance immédiatement leur téléchargement, suivi d'un redémarrage.
Le téléchargement par deltas rend l'upgrade vers la dernière release très rapide.
zincati permet également de coordonner les mises à jour de plusieurs serveurs, fonctionnalité particulièrement utile dans le contexte d'un cluster Kubernetes. Je n'ai pas encore testé cette fonctionnalité.
Note suivante : "composefs, un filesystem spécialement créé pour les besoins des distributions atomic".
Journal du jeudi 24 juillet 2025 à 22:31
Suite à ma note "J'ai découvert ContainerLab, un projet qui permet de simuler des réseaux", j'ai implémenté et publié containerlab-playground.
Mon but était d'utiliser Containerlab pour simuler deux réseaux IPv6 connectés entre eux : 3 serveurs sur le premier réseau et 2 serveurs sur le second.
Comme je l'observe fréquemment depuis quelques mois, Claude Sonnet 4 m'a produit une implémentation qui, en pratique, ne fonctionne pas (voir son contenu dans 2025-07-20_1241).
La note courante reprend principalement en français le contenu du README.md de mon playground .
Voici les instructions que j'ai exécutées pour installer Containerlab sous Fedora :
$ sudo dnf config-manager addrepo --set=baseurl="https://netdevops.fury.site/yum/" && \
$ echo "gpgcheck=0" | sudo tee -a /etc/yum.repos.d/netdevops.fury.site_yum_.repo
$ sudo dnf install containerlab
$ sudo usermod -aG clab_admins stephane && newgrp clab_admins
$ sudo semanage fcontext -a -t textrel_shlib_t $(which containerlab)
$ sudo restorecon $(which containerlab)
Voici les instructions que j'ai exécutées pour installer Containerlab sous Fedora :
$ sudo containerlab deploy
11:27:03 INFO Containerlab started version=0.69.0
11:27:03 INFO Parsing & checking topology file=network-a-b.clab.yaml
11:27:03 INFO Creating docker network name=net-custom IPv4 subnet="" IPv6 subnet=2001:db8:a::0/48 MTU=0
11:27:03 INFO Creating lab directory path=/home/stephane/git/github.com/stephane-klein/containerlab-playground/clab-network-a
11:27:04 INFO Creating container name=vm-b1
11:27:04 INFO Creating container name=vm-a1
11:27:04 INFO Creating container name=vm-a2
11:27:04 INFO Creating container name=vm-a3
11:27:04 INFO Adding host entries path=/etc/hosts
11:27:04 INFO Adding SSH config for nodes path=/etc/ssh/ssh_config.d/clab-network-a.conf
╭──────────────────────┬───────────────────┬─────────┬─────────────────╮
│ Name │ Kind/Image │ State │ IPv4/6 Address │
├──────────────────────┼───────────────────┼─────────┼─────────────────┤
│ clab-network-a-vm-a1 │ linux │ running │ 192.168.0.2 │
│ │ mitchv85/ohv-host │ │ 2001:db8:a:1::1 │
├──────────────────────┼───────────────────┼─────────┼─────────────────┤
│ clab-network-a-vm-a2 │ linux │ running │ 192.168.0.3 │
│ │ mitchv85/ohv-host │ │ 2001:db8:a:1::2 │
├──────────────────────┼───────────────────┼─────────┼─────────────────┤
│ clab-network-a-vm-a3 │ linux │ running │ 192.168.0.4 │
│ │ mitchv85/ohv-host │ │ 2001:db8:a:1::3 │
├──────────────────────┼───────────────────┼─────────┼─────────────────┤
│ clab-network-a-vm-b1 │ linux │ running │ 192.168.0.5 │
│ │ mitchv85/ohv-host │ │ 2001:db8:a:2::5 │
╰──────────────────────┴───────────────────┴─────────┴─────────────────╯
Globalement, j'ai trouvé l'expérience utilisateur de la cli Containerlab très agréable à utiliser :
$ containerlab help
deploy container based lab environments with a user-defined interconnections
USAGE
containerlab [command] [--flags]
COMMANDS
completion [bash|zsh|fish] Generate completion script
config [command] [--flags] Configure a lab
deploy [--flags] Deploy a lab
destroy [--flags] Destroy a lab
exec [--flags] Execute a command on one or multiple containers
generate [--flags] Generate a Clos topology file, based on provided flags
graph [--flags] Generate a topology graph
help [command] [--flags] Help about any command
inspect [command] [--flags] Inspect lab details
redeploy [--flags] Destroy and redeploy a lab
save [--flags] Save containers configuration
tools [command] Various tools your lab might need
version [command] Show containerlab version or upgrade
FLAGS
-d --debug Enable debug mode
-h --help Help for containerlab
--log-level Logging level; one of [trace, debug, info, warning, error, fatal] (info)
--name Lab name
-r --runtime Container runtime
--timeout Timeout for external API requests (e.g. container runtimes), e.g: 30s, 1m, 2m30s (2m0s)
-t --topo Path to the topology definition file, a directory containing one, 'stdin', or a URL
--vars Path to the topology template variables file
-v --version Version for containerlab
J'ai eu quelques difficultés à trouver une image Docker à utiliser qui fournit directement un serveur ssh :
vm-a1:
kind: linux
# image: alpine-ssh
# https://hub.docker.com/r/mitchv85/ohv-host
image: mitchv85/ohv-host
mgmt-ipv6: 2001:db8:a:1::1
Le déploiement de cette image permet de facilement se connecter à l'host en ssh:
$ ssh admin@clab-network-a-vm-a1
admin@vm-a1:~$ exit
Il est possible de facilement lancer une commande sur tous les hosts :
$ sudo containerlab exec -t network-a-b.clab.yaml --cmd 'ip addr'
11:29:52 INFO Parsing & checking topology file=network-a-b.clab.yaml
11:29:52 INFO Executed command node=clab-network-a-vm-a2 command="ip addr"
stdout=
│ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
│ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
│ inet 127.0.0.1/8 scope host lo
│ valid_lft forever preferred_lft forever
│ inet6 ::1/128 scope host
│ valid_lft forever preferred_lft forever
│ 2: eth0@if192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
│ link/ether aa:86:42:84:81:de brd ff:ff:ff:ff:ff:ff link-netnsid 0
│ inet 192.168.0.3/20 brd 192.168.15.255 scope global eth0
│ valid_lft forever preferred_lft forever
│ inet6 2001:db8:a:1::2/48 scope global nodad
│ valid_lft forever preferred_lft forever
│ inet6 fe80::a886:42ff:fe84:81de/64 scope link
│ valid_lft forever preferred_lft forever
11:29:52 INFO Executed command node=clab-network-a-vm-a3 command="ip addr"
stdout=
│ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
│ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
│ inet 127.0.0.1/8 scope host lo
│ valid_lft forever preferred_lft forever
│ inet6 ::1/128 scope host
│ valid_lft forever preferred_lft forever
│ 2: eth0@if193: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
│ link/ether b2:42:6c:2b:d0:9d brd ff:ff:ff:ff:ff:ff link-netnsid 0
│ inet 192.168.0.4/20 brd 192.168.15.255 scope global eth0
│ valid_lft forever preferred_lft forever
│ inet6 2001:db8:a:1::3/48 scope global nodad
│ valid_lft forever preferred_lft forever
│ inet6 fe80::b042:6cff:fe2b:d09d/64 scope link
│ valid_lft forever preferred_lft forever
11:29:52 INFO Executed command node=clab-network-a-vm-a1 command="ip addr"
stdout=
│ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
│ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
│ inet 127.0.0.1/8 scope host lo
│ valid_lft forever preferred_lft forever
│ inet6 ::1/128 scope host
│ valid_lft forever preferred_lft forever
│ 2: eth0@if191: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
│ link/ether 26:9f:87:52:d6:1c brd ff:ff:ff:ff:ff:ff link-netnsid 0
│ inet 192.168.0.2/20 brd 192.168.15.255 scope global eth0
│ valid_lft forever preferred_lft forever
│ inet6 2001:db8:a:1::1/48 scope global nodad
│ valid_lft forever preferred_lft forever
│ inet6 fe80::249f:87ff:fe52:d61c/64 scope link
│ valid_lft forever preferred_lft forever
11:29:52 INFO Executed command node=clab-network-a-vm-b1 command="ip addr"
stdout=
│ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
│ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
│ inet 127.0.0.1/8 scope host lo
│ valid_lft forever preferred_lft forever
│ inet6 ::1/128 scope host
│ valid_lft forever preferred_lft forever
│ 2: eth0@if194: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
│ link/ether e2:81:7b:c7:eb:64 brd ff:ff:ff:ff:ff:ff link-netnsid 0
│ inet 192.168.0.5/20 brd 192.168.15.255 scope global eth0
│ valid_lft forever preferred_lft forever
│ inet6 2001:db8:a:2::5/48 scope global nodad
│ valid_lft forever preferred_lft forever
│ inet6 fe80::e081:7bff:fec7:eb64/64 scope link
│ valid_lft forever preferred_lft forever
Ou alors sur un host en particulier :
$ sudo containerlab exec -t network-a-b.clab.yaml --label clab-node-name=vm-a1 --cmd 'ip addr'
11:02:44 INFO Parsing & checking topology file=network-a-b.clab.yaml
11:02:44 INFO Executed command node=clab-network-a-vm-a1 command="ip addr"
stdout=
│ 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
│ link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
│ inet 127.0.0.1/8 scope host lo
│ valid_lft forever preferred_lft forever
│ inet6 ::1/128 scope host
│ valid_lft forever preferred_lft forever
Par contre, je n'ai pas réussi à atteindre mon objectif 😟.
J'ai l'impression que pour le moment, Containerlab ne permet pas de créer plusieurs réseaux à partir d'un fichier topologie.
Je n'ai pas compris comment définir la longueur du prefix IPv6 des interfaces eth0 au niveau des nodes.
Pour le moment, tous les nodes appartiennent au même sous-réseau 2001:db8:a::0/48, alors que j'aimerais les séparer dans les deux sous-réseaux suivants :
2001:db8:a:12001:db8:a:2
# network-a-b.clab.yaml
...
topology:
nodes:
vm-a1:
kind: linux
# image: alpine-ssh
# https://hub.docker.com/r/mitchv85/ohv-host
image: mitchv85/ohv-host
mgmt-ipv6: 2001:db8:a:1::1
# <== ici je ne sais pas comment définir : 2001:db8:a:1::1/64
...
J'ai découvert l'issue suivante du principal développeur de Containerlab : « Multiple management networks ».
Je pense comprendre que ce que je cherche à faire n'est actuellement pas possible avec Containerlab.
Pour atteindre mon objectif, peut-être que je devrais plutôt m'orienter vers des alternatives mentionnées dans ce billet de blog : Open-source network simulation roundup 2024.
Je viens de poster le message suivant l'espace de discussion GitHub de Containerlab : « Does Containerlab support the creation of topologies with multiple subnets? ».
J'espère que le créateur de Containerlab pourra me suggérer une solution à mon problème, car je n'ai pas réussi à l'identifier dans la documentation 🤷♂️.
Voir la suite de cette note : 2025-09-19_1651.
Journal du mercredi 30 octobre 2024 à 10:21
Je garde trace dans cette notes de deux plugins Asdf / Mise que j'ai utilisé avec succès ces deux derniers jours.
Le premier, pour installer la cli de Hasura : asdf-hasura
$ mise plugin add hasura-cli https://github.com/gurukulkarni/asdf-hasura.git
Contenu de .mise.toml :
[tools]
hasura-cli = "2.43.0"
$ mise install
$ hasura version
INFO hasura cli version=v2.43.0
Le second, pour installer Gitleaks : asdf-gitleaks
$ mise plugin add gitleaks https://github.com/jmcvetta/asdf-gitleaks.git
Contenu de .mise.toml :
[tools]
gitleaks = "8.21.2"
$ mise install
$ gitleaks --version
gitleaks version 8.21.2
Journal du mardi 24 septembre 2024 à 13:07
#JaiLu un excellent article sur NATS : NATS de A à Y du blog Une tasse de café de Quentin Joly.
J'aime beaucoup les fonctionnalités cli de NATS, très pratiques pour faire des démos ou des tests.
J'y ai découvert les requêtes synchrones de NATS : Core NATS - Request-Reply.
À la fin de l'article, j'ai découvert Nex (NATS Execution Engine) :
The NATS Execution Engine (we'll just call it Nex most of the time) is an optional add-on to NATS that overlays your existing NATS infrastructure, giving you the ability to deploy and run workloads.
...
While you can build virtually any kind of application with Nex, the core building blocks are made up of two fundamental types of workloads: services and functions.
...
Nex functions are small and can be deployed either as Javascript functions or as WebAssembly modules.
Je découvre aussi que Nex utilise Firecracker.
Je suis un peu embêté, car je réalise que cela fait 2 ans que j'ai très envie d'utiliser NATS. J'espère ne pas tomber prochainement dans les travers du Resume Driven Development 🙈.
À la suite de la lecture de cet article, j'ai offert un petit café à Quentin Joly.