Aller au contenu
Conteneurs & Orchestration medium

Incus OS : connecter les nœuds à un tailnet Tailscale

10 min de lecture

logo incus

Administrer un cluster Incus OS suppose d'atteindre ses nœuds sur le réseau. Plutôt que d'exposer l'API ou le SSH (absent ici) sur un réseau public, on rattache chaque nœud à un tailnet Tailscale : un réseau mesh chiffré où les machines se joignent par une IP privée stable 100.x, où qu'elles soient. Ce guide montre comment activer le service Tailscale d'Incus OS entièrement par API, sans shell, vérifier que le mesh est monté, et exposer des routes vers les instances. Public visé : administrateurs d'un cluster Incus OS.

  • Comprendre ce que le service Tailscale d'Incus OS connecte, et ce qu'il ne connecte pas.
  • Générer une clé d'authentification adaptée à un parc de nœuds.
  • Activer et configurer le service par API, sans exposer la clé.
  • Vérifier l'état du mesh (adresses 100.x, pairs en ligne).
  • Exposer des routes ou choisir un control server Headscale.
  • Un cluster Incus OS en service. Voir Incus OS sans interface et Cluster Incus.
  • Un compte Tailscale (ou un control server Headscale publiquement joignable en HTTPS, voir la fin du guide).
  • Un client Incus dont le certificat est approuvé, avec un remote vers chaque nœud.
  • Un accès internet sortant depuis les nœuds, pour joindre le plan de contrôle Tailscale.

Comme pour les mises à jour A/B, toute la configuration passe par l'API REST préfixée par /os, interrogée avec incus query. Le service Tailscale se règle par nœud : chaque commande cible un membre via son remote.

Contrairement au client Ceph, le client Tailscale est déjà embarqué dans l'image Incus OS : il n'y a aucun add-on à installer. Le service est simplement désactivé par défaut. On l'active en écrivant sa configuration, et Incus OS lance le démon tailscaled et exécute le rattachement au réseau.

Point essentiel à saisir avant de commencer : le service connecte le nœud (l'hôte Incus OS) au tailnet, pas les instances qu'il héberge. Un conteneur ou une machine virtuelle ne reçoit pas d'adresse Tailscale du simple fait que son hôte est connecté. Pour rendre des instances joignables, on passe par des routes annoncées (subnet router), abordées plus bas.

Le rattachement non interactif d'un nœud demande une clé d'authentification (auth key). Depuis la console Tailscale, dans les réglages de clés, générez une clé avec les options adaptées à un parc :

  • Reusable : une seule clé sert à tous les nœuds du cluster.
  • Ephemeral : un nœud déconnecté est retiré automatiquement du tailnet, ce qui évite les entrées fantômes après un test ou un déclassement.
  • Expiration courte : limitez la fenêtre pendant laquelle la clé est valable.

La clé se présente sous la forme tskey-auth-.... C'est un secret : elle donne le droit d'inscrire des machines dans votre réseau. Ne la stockez pas en clair et ne la laissez pas traîner dans un historique de commandes.

La configuration s'écrit avec un PUT sur services/tailscale. Pour ne pas exposer la clé, saisissez-la en lecture masquée, écrivez un fichier temporaire à permissions serrées, puis effacez-le. Commencez par un seul nœud afin de valider avant de généraliser :

Fenêtre de terminal
umask 077
read -rsp 'Auth key Tailscale: ' TSKEY; echo
cat > /tmp/ts.json <<JSON
{"config":{"enabled":true,"auth_key":"$TSKEY","accept_routes":false,"accept_dns":false,"login_server":""}}
JSON
unset TSKEY
incus query -X PUT "node1:/os/1.0/services/tailscale" -d "$(cat /tmp/ts.json)"

Un login_server vide désigne le plan de contrôle Tailscale par défaut, servi en HTTPS avec un certificat public valide. En réponse, Incus OS lance tailscaled et exécute l'équivalent d'un tailscale up avec la clé fournie. Le champ accept_routes à false signifie que le nœud n'importe pas les routes annoncées par les autres pairs ; accept_dns à false laisse la résolution DNS locale du nœud intacte.

Le rattachement prend quelques secondes. Interrogez ensuite l'état du service. Attention, la lecture renvoie aussi config.auth_key en clair : pour partager une sortie, filtrez sur la partie state.

Fenêtre de terminal
incus query "node1:/os/1.0/services/tailscale"

La section state doit afficher un backend actif et une adresse Tailscale :

{
"state": {
"backend_state": "Running",
"version": "1.100.0",
"tailnet_name": "votre-compte",
"self": {
"host_name": "node1",
"dns_name": "node1.votre-tailnet.ts.net.",
"tailscale_ips": ["100.113.80.118", "fd7a:115c:a1e0::fc35:5077"]
},
"health": []
}
}

Un backend_state à Running et une adresse en 100.x confirment que le nœud a rejoint le tailnet. Le champ self.dns_name donne le nom MagicDNS par lequel le nœud est désormais joignable depuis vos autres machines Tailscale.

Une fois le premier nœud validé, appliquez la même configuration aux autres membres, puis effacez le fichier contenant la clé :

Fenêtre de terminal
for n in node2 node3; do
incus query -X PUT "$n:/os/1.0/services/tailscale" -d "$(cat /tmp/ts.json)"
done
shred -u /tmp/ts.json 2>/dev/null || rm -f /tmp/ts.json

Chaque nœud reçoit sa propre adresse 100.x et voit les autres comme pairs. Vous pouvez lister les pairs vus par un nœud dans state.peer : les autres membres du cluster doivent y figurer avec online à true. Le mesh est alors complet : les nœuds communiquent entre eux par le tunnel chiffré, indépendamment de leur emplacement réseau.

Sur une flotte gérée par Operations Center, on n'édite pas chaque nœud un par un : la console proxifie la configuration des services de chaque serveur. On lit ou modifie le service Tailscale d'un membre par son CLI :

Fenêtre de terminal
operations-center provisioning server os service show IncusOS01:tailscale
operations-center provisioning server os service edit IncusOS01:tailscale

L'édition reçoit le même objet de configuration que l'API directe (enabled, auth_key, advertised_routes...) et l'applique au nœud visé. C'est le canal centralisé à privilégier dès qu'un parc est enrôlé, la configuration par incus query restant utile pour un nœud isolé ou un cluster non géré. Cette partie de l'API reste marquée expérimentale dans les versions actuelles.

Puisque le service connecte l'hôte et non les instances, rendre un conteneur ou une VM joignable depuis le tailnet demande d'annoncer son sous-réseau. On déclare les routes que le nœud propose avec advertised_routes, et on autorise les autres nœuds à les emprunter avec accept_routes :

Fenêtre de terminal
incus query -X PUT "node1:/os/1.0/services/tailscale" \
-d '{"config":{"enabled":true,"auth_key":"tskey-auth-...","advertised_routes":["10.167.207.0/24"],"accept_routes":true}}'

Le sous-réseau des instances devient alors routable pour les membres du tailnet qui acceptent les routes, après approbation de la route côté administration Tailscale. Le service expose aussi serve_enabled, serve_port et serve_service pour publier l'API Incus via Tailscale Serve, une option à réserver aux cas où l'on veut un accès HTTPS direct à l'interface.

Le champ login_server accepte l'URL d'un control server Headscale, l'implémentation libre et auto-hébergée du plan de contrôle Tailscale. La configuration est identique, on ajoute simplement l'URL et une clé générée côté Headscale (headscale preauthkeys create).

SymptômeCause probableSolution
backend_state reste vide ou NeedsLoginClé invalide, expirée ou déjà consomméeGénérer une clé reusable et non expirée, réappliquer le PUT
Le nœud n'obtient pas d'adresse 100.xPas d'accès internet sortant vers le plan de contrôleVérifier la route par défaut et le DNS du nœud
Échec avec un login_server HeadscaleURL en HTTP ou certificat non valideExposer Headscale en HTTPS avec un certificat de confiance
Les instances restent injoignablesLe service connecte l'hôte, pas les instancesDéclarer advertised_routes et approuver la route côté Tailscale
  • Le client Tailscale est embarqué dans Incus OS : aucun add-on, on active juste le service.
  • Toute la configuration passe par PUT /os/1.0/services/tailscale, par nœud.
  • Le service connecte le nœud, pas les instances : pour elles, utiliser advertised_routes.
  • Utilisez une clé reusable et ephemeral pour un parc, et effacez le fichier qui la contient.
  • La lecture d'état renvoie la clé en clair : filtrez sur state avant de partager une sortie.
  • Headscale est possible via login_server, mais exige un certificat HTTPS publiquement valide.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn