Note (Dernière mise à jour le 26/05/2026)
Guide remis à jour pour Talos v1.13.3 et Kubernetes v1.36.1, ainsi que l’ensemble des charts Helm à date.
Talos devient au fil du temps la solution de choix pour déployer des clusters Kubernetes cloud ou bare metal hautement sécurisés et performants. Zéro SSH, API-REST first, à peine une douzaine de binaires embarqués, support chiffrement complet, cet OS est entièrement construit de manière conteneurisée et bootstrappé depuis le projet stagex, permettant un build entièrement reproductible et théoriquement insensible aux attaques supply-chain. Nous allons ici tenter de mettre en place un cluster kubernetes Talos sur des Cloud Service Providers européens (non GAFAM), le plus proche possible du production-grade, sans coût délirant.
Pour qui et pourquoi ? 🤔
Ce guide s’adresse aux devs à fortes inspirations DevOps/GitOps, principalement européens, adeptes du self-hosting, souhaitant s’affranchir des VPS à la papa et s’extirper de notre dépendance aux GAFAM, notamment :
- De leurs coûts délirants, inhérents aux modèles économiques de ces hyperscalers.
- De leur main mise sur nos données du fait du Cloud Act.
- De leur opacité et aspect vendor-locking, du fait de l’intégration dans leur écosystème propriétaire, alors que l’écosystème standardisé Kubernetes offre de sérieuses alternatives via de puissants opérateurs.
En bref :
- Vous pensez avoir avez fait le tour de Dokploy et/ou de tout ce qui est possible de faire à partir des solutions type Docker Swarm, qui reste toujours parfaitement adapté aux besoins simples.
- Vous souhaitez passer au niveau supérieur, basé sur des solutions Kubernetes et vous rapprochez de ce qui se fait de mieux chez les hyperscalers sans pour autant en subir le coût*.
- Aller plus loin que les solutions classiques type
k3s/kubeadmmontées à l’arrache vite fait sur des Debian abandonnées, et monter votre infra complète entièrement contrôlée en mode GitOps. - Avoir une chaîne de déploiement CI/CD complète, incluant tous les outils d’observabilité nécessaires.
Note (Coûts)
(*) En termes de coûts pour suivre ce guide, nous parlons ici d’un billet de ~65€/mois au minimum pour avoir quelque chose de potable, sinon partez plutôt sur du ~125€/mois pour du production-grade.
Le but ici est donc de se rapprocher raisonnablement et à notre échelle de ces hyperscalers sur le triptyque suivant :
- La sécurité, via Zero Trust, chiffrement des données, mTLS, WAF (nous voulons aussi éviter les solutions de facilité tel que Cloudflare).
- La résilience, via haute disponibilité, backups et Plan de Reprise d’Activité (PRA).
- L’observabilité, à tous les niveaux, métriques, logs, traces.
Le sacrifice en échange ?
- Des efforts et du temps…
- Une plus grande part de responsabilité technique.
Les bénéfices :
- Une maîtrise de la stack logicielle complète, infra incluse, du
buildjusqu’aurun. - Un juste milieu entre les VPS à la papa et les hyperscalers.
- Des coûts 100% maitrisés, aux rapports performances/prix d’un niveau sur lequel aucun CSP ne peut réellement rivaliser.
Et les solutions type OVHcloud ou Scaleway alors ? Très bien, c’est un vrai pas dans la bonne direction, et un excellent compromis entre le GAFAM et le cluster kube tout géré à la main. Si cela répond parfaitement à votre besoin alors nickel, vous pouvez déjà vous arrêter ici !
Mais il reste encore la problématique du coût, que ces Cloud Services Providers ont bien naturellement besoin de marger aux clients du fait du nombre toujours grandissant de services cloud proposés.
Comment ? 🛤️
Ici, ce guide se focalisera sur une seule ressource principale et essentielle : ce bon vieux VPS, mais cuisiné aux petits oignons. Exit les grands CSP multi-services managés, en dehors des S3, DNS, TEM (email transactionnel).
Sur tout ce que j’ai testé, Hetzner Cloud reste le leader incontestable du marché du VPS Cloud européen au rapport performance/prix imbattable, tout en disposant d’une interface UX et API/CLI simple et sans fioritures, uniquement centrée autour des VPS et des volumes. Il ne propose pratiquement aucun autre service managé mis à part le Load Balancer (l’Object Storage n’est d’ailleurs arrivé que très récemment), et c’est à peu près tout ce qu’on lui demande ! Il inclut également un provider terraform simple qui fait super bien son taf sans 15000 ressources à connaître (coucou les providers AWS/AZ).
Comme il est de rigueur, nous n’allons pas mettre tous nos œufs dans le même panier, et utiliserons à ce titre 2 cloud providers différents :
Hetzner Cloud: l’infrastructure principale, VPS / volumes / Load BalancersScaleway: pour la partie DNS, TEM (serveur de mail transactionnel), et S3, qui sera utilisé pour la partie stockage long-terme (logs / traces) et backups. Scaleway propose depuis très récemmentSSE-ONE, un équivalentSSE-KMSassurant le chiffrement automatique côté serveur.
Proposition (Providers)
Pour faciliter le suivi de ce guide, vous devriez avoir un compte actif sur chacun ces 2 services. Seul Hetzner Cloud est réellement indispensable, L’autre étant fonction de vos préférences, qu’il faudra adapter. Mais vous devez à minima avoir un S3, un DNS, et un TEM prêt à l’emploi sous la main.
Les objectifs 🎯
- Monter un cluster Talos fonctionnel européen sécurisé, résiliant, et totalement monitoré.
- Tout en self-hosted ou presque, on maîtrise toute la brique infra logicielle.
- Déploiement 100% GitOps via
Terraform/OpenTofupuisFluxCD - Afin de comprendre et maîtriser chaque étape du processus, l’infra est construite en mode pas à pas, sans raccourci ni utilisation d’outil tout-en-un qui fait tout tel que terraform-hcloud-kubernetes.
Zero Trustde bout en bout, via l’utilisation deTailscale.- Cluster construit avec la notion de worker pools, comme chez tous les providers d’infra cloud proposant du kube managé.
- Chiffrement à tous les niveaux (volumes systèmes et externes, backups, s3, réseau pod à pod, mTLS).
- Intégration de
Ciliumsur la couche réseau physique de l’infra Hetzner. - Intégration cloud (Network, Nodes et Load-Balancer) avec
Hetzner Cloud Controller Manager. - Solution de volumes distribués et backups via
Longhorn. - Du Ingress avec tout l’attirail qui va bien (
cert-manager,Traefik, etCrowdSecen tant que solution WAF incluant analyse comportementale du trafic). - Un Ingress avec endpoint public via Load Balancer et endpoint privé à travers le réseau Tailscale pour l’accès aux outils internes.
- Un cluster primary/replica
PostgreSQLdes familles viaCloudNativePG, avec backup barman cloud sur s3 chiffré. - Un cluster
Dragonfly(équivalent Redis). - Observabilité à tous les niveaux, monitoring complet via
Prometheus/Grafana, logging et tracing distribué viaLokietTempoen passant par le collecteurAlloy. - Mis en place d’une logistique CI/CD via
Gitea ActionetFlux, avec analyse de code viaSonarQube, incluant l’observabilité post-déploiement, au travers d’un exemple de projet .NET API.
Un sacré programme, be brave.
Remark (Tailscale)
Petit aparté sur Tailscale :
- Bien que boîte canadienne à la base, je ne connais pas de réel équivalent européen au niveau en termes de simplicité/efficacité pour mettre en place du Zero Trust.
- Le client Tailscale est installable absolument partout, dont l’extension Talos officielle.
- Toute la partie cliente est en Open Source.
- Le réseau est chiffré de bout en bout via
Wireguard, avec communication pair-à-pair, et les clés privées ne sont pas connues de Tailscale, le site central n’étant qu’un serveur de coordination. - Possibilité d’utiliser à la place headscale pour du self-hosted, mais ce ne sera pas le sujet de ce guide.
- Pour les plus paranos, la feature Tailnet Lock permet même d’empêcher un client de rejoindre le réseau tailnet sans avoir été accepté par un autre client signataire de ce même tailnet. Tout est donc géré côté client et non plus par le serveur de coordination. À ce titre, même un serveur Tailscale compromis ne saurait donc forcer de lui-même un nouveau client malveillant au sein de notre réseau privé tailnet. Le corollaire étant de bien conserver les clés de lock au risque de perdre le contrôle du tailnet définitivement.
Pré-requis 🛠️
Déjà niveau prérequis ça va demander pas mal d’effort avant de commencer quoi que ce soit :
- Un compte Hetzner Cloud.
- Un compte Tailscale et être connecté sur votre tailnet de travail. Activer Tailnet Lock en option pour le maximum de sécurité, sinon activer au moins l’approbation manuelle d’un nouvel appareil.
- Un service S3 avec fonction de chiffrement SSE-C. Un équivalent SSE-KMS en plus sera idéal, car certains services de backup comme barman cloud ne supporte pas le chiffrement client. On utilisera ici Scaleway. Activer le versioning pour être moins vulnérable aux ransomwares.
- Un nom de domaine avec un accès admin au DNS (on partira sur
ohmytalos.ioici). On réservera un sous-domaineint.ohmytalos.iopour l’accès aux outils internes. - Un compte de mail transactionnel, déjà actif et pré-paramétré sur votre nom de domaine, avec SPF/DKIM et tout le bousin. Si vous n’utiliser pas Scaleway pour la partie DNS, il faudra adapter le provider DNS-01 en fonction pour le challenge ACME.
- Un environnement
bash/zshavec une belle brochette d’outils CLI préinstallés suivants :mise,fnox,sops,age,hcloud,talosctl,kubectl,helm,terraform,packer,flux. On n’est pas là pour déconner. L’utilisation debrewou encore mieuxmiseest vivement recommandé pour les installer et mettre à jour facilement. - Outils complémentaires optionnels pour la productivité sur kube :
cilium,cmctl,cnpg(plugin krew),k9s,ktop,kube-capacity,oh-my-zshavec pluginkubectlpour les alias.
Warning (Gestion des secrets)
Pour des raisons de simplifications, nous n’utiliserons pas de secret manager à proprement parler dans ce guide, bien que ce soit la méthode recommandée pour la gestion des secrets dans Kubernetes en production, à des fins d’auditabilité et de possibilité de rotations.
Les secrets terraform seront chiffrés sur git localement via age + fnox, puis chiffrés at rest via etcd (le cas par défaut sur Talos), mais seront donc inévitablement visibles en clair dans le state Terraform (qui sera certe chiffré en SSE-C sur le bucket S3).
Pour la production, si vous êtes déjà chez Scaleway, je recommande Scaleway Secret Manager associé à EOS, pour une gestion centralisée et automatisée des secrets, déchiffrés uniquement au runtime.
Snapshots 💽
Nous allons avoir besoin d’uploader des images Talos prête à l’emploi pour la création à la volée de nos VPS. Un peu comme propose l’outil hcloud-upload-image, mais je préfère utiliser packer pour une approche plus GitOps.
La 1ère chose à faire est d’aller sur le site officiel de Talos Image Factory afin de construire vos images Talos personnalisées. Vous pouvez également créer un fichier de définition des extensions offline comme nous allons le faire ici.
Dans ce guide, nous allons avoir besoin de 2 types d’images :
- Une dédiée pour les control planes, contenant l’extension Tailscale pour accéder à nos nodes en mode zero-trust.
- Une dédiée par défaut pour les workers, sans Tailscale car l’on passera par les control planes pour y accéder, mais avec les extensions nécessaires au bon fonctionnement de Longhorn (iSCSI, util-linux-tools).
Créez-vous un nouveau répertoire projet ohmytalos-cluster puis les 2 fichiers suivants :
customization: systemExtensions: officialExtensions: - siderolabs/tailscalecustomization: systemExtensions: officialExtensions: - siderolabs/iscsi-tools - siderolabs/util-linux-toolsRécupérer les hashs d’identifiant de l’image comme suit :
curl -s -X POST --data-binary @schematic-cp.yaml https://factory.talos.dev/schematics | jq .id# 4a0d65c669d46663f377e7161e50cfd570c401f26fd9e7bda34a0216b6f1922bcurl -s -X POST --data-binary @schematic-wk.yaml https://factory.talos.dev/schematics | jq .id# 613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b62629612452 infos importantes à retenir à partir de ce hash :
- Notre image de première installation qui va nous servir pour la création de notre snapshot https://factory.talos.dev/image/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/v1.13.3/hcloud-amd64.raw.xz
- L’URL de l’image OCI pour les opérations d’upgrade
factory.talos.dev/hcloud-installer/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:v1.13.3
Pour chaque image, il faut prévoir une pour l’archi amd64, et une autre pour arm64, car l’on pourrait très bien imaginer des node pools sous différentes architectures. Rajouter autant de schematics que nécessaire, par exemple une contenant les drivers spécifiques pour des clusters de nodes GPU. On reflète tout cela dans le fichier packer suivant :
packer { required_plugins { hcloud = { source = "github.com/hetznercloud/hcloud" version = "~> 1" } }}
variable "hcloud_token" { type = string default = env("HCLOUD_TOKEN") sensitive = true}
variable "schematic_id" { type = string default = "376567988ad370138ad8b2698212367b8edcb69b5fd68c80be1f2ec7d603b4ba"}
variable "image_name" { type = string default = "default"}
variable "talos_version" { type = string default = "v1.13.3"}
variable "arch" { type = string}
variable "server_location" { type = string default = "nbg1"}
locals { server_types = { amd64 = "cpx22" arm64 = "cax11" } image = "https://factory.talos.dev/image/${var.schematic_id}/${var.talos_version}/hcloud-${var.arch}.raw.xz"}
source "hcloud" "talos" { rescue = "linux64" image = "debian-13" location = var.server_location server_type = local.server_types[var.arch] ssh_username = "root"
snapshot_name = "talos system disk - ${var.image_name} - ${var.arch} - ${var.talos_version}" snapshot_labels = { type = "infra", os = "talos", version = var.talos_version, arch = var.arch, name = var.image_name } token = var.hcloud_token}
build { sources = ["source.hcloud.talos"]
provisioner "shell" { inline = [ "apt-get install -y wget", "wget -O /tmp/talos.raw.xz ${local.image}", "xz -d -c /tmp/talos.raw.xz | dd of=/dev/sda && sync", ] }}Il nous est maintenant possible de construire notre image Talos personnalisée pour chaque architecture. Pour cela, nous allons avoir besoin de préparer notre token API Hcloud secrète dans notre environnement.
1er secret avec fnox et age 🔐
Nous utiliserons fnox pour la gestion de nos secrets locaux, notamment les secrets terraform qui seront chiffrés localement avant d’être poussés sur git. fnox supporte nativement age pour le chiffrement asymétrique, ce qui est idéal pour un cas d’usage simple, et nous allons l’utiliser pour générer notre paire de clés.
# 1. On génère notre clé privée et publique, à conserver précieusement dans votre gestionnaire de mot de passeage-keygen -o ~/.config/fnox/age.txt
# 2. Récupérer la clé publique pour la config de fnoxgrep "public key:" ~/.config/fnox/age.txtCréer le fichier suivant à la racine de votre projet ohmytalos-cluster en y indiquant votre clé publique.
[providers.age]type = "age"recipients = ["age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]Créer un nouveau projet dédié sur Hcloud, générez-y une clé API read/write puis inscrivez-la dans votre environnement.
fnox set HCLOUD_TOKEN "xxxxxxxxxxxxxxxxxxxxx" --provider ageVérifier avec echo $HCLOUD_TOKEN pour vous assurer que la variable d’environnement est correctement définie.
Note (Team workflow)
À chaque intégration d’un nouveau membre d’équipe possédant sa propre clé privé age, il sera nécessaire de rajouter sa clé publique dans ce fichier puis refaire un fnox set sur chaque secret. Commande pratique pour tout rechiffrer :
fnox list | awk '/provider \(age\)/ {print $1}' | while read env_key; do fnox set "$env_key" "$(fnox get "$env_key")" --provider agedoneNous allons maintenant utiliser mise pour automatiser le build de nos images pour nos control planes et workers, créer le fichier suivant pour enregistrer nos tâches de build :
[tasks.install]run = "packer init ."
[tasks.amd64-cp]run = "packer build -var arch=amd64 -var image_name=cp -var schematic_id=4a0d65c669d46663f377e7161e50cfd570c401f26fd9e7bda34a0216b6f1922b ."
[tasks.arm64-cp]run = "packer build -var arch=arm64 -var image_name=cp -var schematic_id=4a0d65c669d46663f377e7161e50cfd570c401f26fd9e7bda34a0216b6f1922b ."
[tasks.build-cp]depends = ["amd64-cp", "arm64-cp"]
[tasks.amd64-wk]run = "packer build -var arch=amd64 -var image_name=wk -var schematic_id=613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245 ."
[tasks.arm64-wk]run = "packer build -var arch=arm64 -var image_name=wk -var schematic_id=613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245 ."
[tasks.build-wk]depends = ["amd64-wk", "arm64-wk"]
[tasks.build]depends = ["amd64-cp", "arm64-cp", "amd64-wk", "arm64-wk"]Note (schematic_id)
Les hash schematic_id sont ceux récupérés précédemment depuis le site Talos Factory depuis l’exemple ci-dessus. Pensez à les modifier si vous avez créé vos propres images personnalisées.
Plus qu’à lancer mise build et c’est parti pour la construction de tous nos snapshots images Talos en parallèle. À la fin de l’opération, vous devriez obtenir 4 snapshots d’image prêt à l’emploi, visible dans l’onglet “Servers/Snapshots” sur Hetzner Cloud ou plus directement côté CLI via hcloud image list -t snapshot. Pour l’utilisation du CLI, pensez à créer puis activer le contexte auparavant via hcloud context create ohmytalos-dev puis hcloud context use ohmytalos-dev, une clé API uniquement en lecture suffira si vous choisissez la voie 100% terraform à la section 2 de ce guide.
Architecture cloud 🏭
Comme toute architecture kube qui se respecte, et à l’image des kubes managés des hyperscalers, notre IaC devra exprimer la notion de node pools, dans lesquels on indiquera les caractéristiques (type de machine par défaut, volumes, talos config, etc.) puis la liste des hosts. Chaque pool sera dédié à un type de workload spécifique. Dans ce guide, nous allons créer 2 node pools :
- Un pool de worker : dédié aux workloads applicatifs, dont les nœuds ferons également office de reverse proxy traefik et seront rattachés à un load balancer Hcloud dédié au trafic public.
- Un pool de stockage : dédié aux workloads type base de données, ainsi que backends de métriques, logs et traces, il sera composé de nœuds avec des volumes rattachés à haute capacité.
Remark (Node pool monitoring)
Afin d’optimiser les coûts, nous mélangeons ici dans les nœuds de storage du workload de base de données et de monitoring. Bien que largement suffisant pour un besoin standard, ce n’est pas forcément idéal en termes de scalabilité.
Au niveau production, il peut rapidement être préférable de mettre en place un pool de monitoring dédié à Prometheus/Loki/Tempo (au moins 2 serveurs pour le côté HA), ce qui permet de bien meilleure flexibilité en termes de dimensionnement horizontal. Vous n’aurez qu’à adapter le guide en fonction.
Côté choix du type de VPS, l’essentiel est de partir sur 4 Go de RAM (minimum requis) pour les control planes (3 fois pour HA), puis 8 Go de RAM pour les 5 workers, répartis sur les 2 node pools. Ensuite, vous aurez principalement le choix entre 2 typologies niveau performance/prix :
| Type VPS | Coût mensuel HT pour un cluster | Avantages |
|---|---|---|
cx23/cx33 | ~60€ | Intel Skylake, option ultra-compétitive pour du kube pas trop dégueux. |
cpx22/cpx32 | ~120€ | AMD Genoa, plus recommandable pour du pro. Deux fois plus cher que la 1ère option, pour ~2.5 fois plus de performance par cœur. |
Il faudra y inclure le load balancer
lb11à 6,57€ HT
En imaginant un cluster de staging utilisant l’option 1, et un cluster de production sur l’option 2, vous arriverez très grossièrement à un coût total mensuel TTC de ~200€ en comptant tout. À ce tarif, vous pouvez être certain d’avoir bien plus de performance sous le capot tout en étant largement 10 fois moins cher qu’un équivalent anémique chez les hyperscalers. Le tout en étant maître de votre infra de A à Z, avec les avantages, mais aussi disons-le, les inconvénients que cela comporte.
Architecture réseau 🌐
Avant de continuer, il est vital de bien poser l’architecture réseau de notre cluster. Il s’agit du système nerveux de Kubernetes, difficile de le changer après coup sans douleur, sinon à part le recréer. Nous allons dédier un subnet pour nos control planes et chaque node pool. Ce qui nous donne l’architecture suivante :
| Adresse IP CIDR | Description | Note |
|---|---|---|
10.0.0.0/10 | Réseau principal | Plage 10.0.0.0 → 10.63.x.x pour tout notre cluster |
10.0.0.0/24 | Sous-réseau control planes | Plage 10.0.0.x pour les control planes |
10.0.1.0/24 | Sous-réseau node pool worker | Plage 10.0.1.x pour les nœuds de workload principal |
10.0.2.0/24 | Sous-réseau node pool storage | Plage 10.0.2.x pour les nœuds de storage / DB |
10.42.0.0/16 | Plage des pods kube | Plage 10.42.x.x pour les pods kube |
10.43.0.0/16 | Plage des services kube | Plage 10.43.x.x pour les services kube |
Warning (Route Controller)
Nous activerons plus tard le route-controller intégré dans hcloud-cloud-controller-manager afin de créer automatiquement les routes “physiques” dans le réseau privé hcloud pour chaque nœud, permettant la communication entre les pods, sans overhead au niveau OS.
La plage utilisée pour chaque route découlera de la plage choisie pour les pods, donc ici nécessairement de type 10.42.x.0/24 (allocation /24 par défaut dans kubernetes/CNI). Dans cette configuration le nombre maximum de nœuds possibles dans le cluster serait de 255, tous pools confondus, avec maximum ~250 pods par nœud (selon les adresses déjà réservées par kube).
Note (Exemples)
Tout découle de l’adresse du réseau principal. On utilise ici 10.0.0.0/10 afin de libérer de la place pour d’autres usages à côté du cluster. Cela laisse la place pour d’autres clusters à côté, par exemple sur 10.64.0.0/10, 10.128.0.0/10 et/ou 10.192.0.0/10. Exemple pour 10.64.0.0/10 :
| Adresse IP CIDR | Description |
|---|---|
10.64.0.0/10 | Réseau principal |
10.64.0.0/24 | Sous-réseau control planes |
10.64.1.0/24 | Sous-réseau node pool worker |
10.64.2.0/24 | Sous-réseau node pool storage |
10.106.0.0/16 | Plage des pods kube |
10.107.0.0/16 | Plage des services kube |
Si vous êtes certain de n’avoir besoin que d’un seul cluster par projet Hcloud, vous pouvez directement partir sur 10.0.0.0/8. Cela donnerai :
| Adresse IP CIDR | Description |
|---|---|
10.0.0.0/8 | Réseau principal |
10.0.0.0/24 | Sous-réseau control planes |
10.0.1.0/24 | Sous-réseau node pool worker |
10.0.2.0/24 | Sous-réseau node pool storage |
10.244.0.0/16 | Plage des pods kube (valeur par défaut) |
10.96.0.0/12 | Plage des services kube (valeur par défaut) |
Côté configuration Talos, il faudra bien préciser la plage des pods et services dans la section cluster.network :
cluster: network: cni: name: none podSubnets: - 10.42.0.0/16 serviceSubnets: - 10.43.0.0/16 proxy: disabled: true externalCloudProvider: enabled: true* Ne faite rien pour le moment, il s’agit juste d’un élément à garder en tête pour la prochaine section du guide.
Warning (CNI)
On désactivera le CNI natif flannel de Talos en indiquant cni.name à none, de même pour le proxy natif de kube. Le tout sera remplacé par Cilium, permettant de bénéficier nativement de eBPF.
On précisera cluster.externalCloudProvider.enabled à true puisque l’on utilisera le CCM externe Hetzner Cloud Controller Manager.
Architecture storage 🗄️
Chiffrement des disques 🔐
Le chiffrement sera effectué à tous les niveaux, non seulement côté Longhorn mais aussi côté système grâce au support de chiffrement natif de Talos via LUKS. Nous utiliserons la config indiquée dans la doc officielle. Il existe trois types de volumes à chiffrer, les 2 volumes système STATE et EPHEMERAL, valable sur tous les nœuds, ainsi que le volume utilisateur longhorn spécifique aux volumes Hetzner que l’on rattachera aux nœuds du pool de stockage. Nous aurons donc besoin de déclarer jusqu’à 3 configurations de volumes dans notre fichier de configuration Talos :
apiVersion: v1alpha1kind: VolumeConfigname: STATEencryption: keys: - nodeID: {} slot: 0---apiVersion: v1alpha1kind: VolumeConfigname: EPHEMERALencryption: keys: - static: passphrase: supersecret slot: 0 lockToSTATE: true---apiVersion: v1alpha1kind: UserVolumeConfigname: longhornencryption: keys: - static: passphrase: supersecret slot: 0 lockToSTATE: true* De même cette partie sera traitée dans la prochaine section.
Nous utilisons des clés statiques en dehors du volume STATE afin de permettre la rotation des clés. Nouveauté de Talos 1.11, nous activons également lockToSTATE pour mixer la clé de chiffrement du volume EPHEMERAL et Longhorn avec un salt propre au volume STATE (utilisation d’une fonction de dérivation au niveau de la clé de déchiffrement). L’intérêt est que ces volumes soient indéchiffrables en cas de perte du volume STATE.
C’est le mode le plus sécurisé possible (en tout cas sur Hetzner Cloud à date), mais le moindre problème ou changement matériel entraînant une éventuelle modification de nodeID peut vous faire perdre l’ensemble des données du nœud. Toutefois l’utilisation de replicas Longhorn limite l’impact de la perte d’un nœud. Comme toujours un vrai backup externe sera toujours d’autant plus indispensable (naturellement chiffré). N’indiquez pas lockToSTATE (false par défaut) si vous préférez garder la possibilité de récupérer vos volumes en cas de perte du volume STATE.
Warning (Chiffrement des disques)
Les VPS disponibles par Hcloud ne supportent ni Secure Boot ni TPM à date. On se limite ici à une pass-phrase statique sur les volumes EPHEMERAL et Longhorn. Cette pass-phrase sera stocké dans le volume STATE lui-même chiffré via une clé unique spécifique au nœud.
Ne pas utiliser de pass-phrase statique sur les volumes STATE, cela rendrait tout le chiffrement inutile. En effet, la partition META, contenant notamment la config de la partition STATE dont la configuration du chiffrement, est forcément en clair.
Paramétrage Longhorn 🛠️
Pour automatiser au mieux la configuration des volumes pour Longhorn lors de son installation plus tard, le mieux est de préconfigurer les nodes en amont, via des labels et annotations spécifiques. Ils seront logiquement différents selon que ce soit un nœud de workload ou un nœud de stockage avec disque externe rattaché. Voici ce qu’on est en droit d’attendre comme labels et annotations pour chaque node pool selon notre schéma d’archi :
machine: nodeLabels: node.longhorn.io/create-default-disk: config nodeAnnotations: node.longhorn.io/default-disks-config: '[{"allowScheduling":true,"name":"system","path":"/var/lib/longhorn","tags":["local"]}]' node.longhorn.io/default-node-tags: '["worker"]'machine: nodeLabels: node.kubernetes.io/exclude-from-external-load-balancers: "true" node.kubernetes.io/role: storage node.longhorn.io/create-default-disk: config nodeAnnotations: node.longhorn.io/default-disks-config: '[{"allowScheduling":true,"name":"system","path":"/var/lib/longhorn","tags":["local"]},{"allowScheduling":true,"name":"volume","path":"/var/mnt/longhorn","tags":["volume"]}]' node.longhorn.io/default-node-tags: '["storage"]'On s’assure que seuls les nœuds workers soient rattachés aux loads balancers via le label node.kubernetes.io/exclude-from-external-load-balancers sur les autres pools.
Le label node.longhorn.io/create-default-disk: config permet de personnaliser la configuration par défaut des disques Longhorn via l’annotation node.longhorn.io/default-disks-config. On indique ici au format json que l’on souhaite un disque system local sur chaque nœud et un disque volume supplémentaire sur les nœuds de stockage. Ce dernier devra être monté au préalable sur /var/mnt/longhorn côté Hcloud.
On précise le tag local vs volume pour différencier les types de disques dans Longhorn, notamment pour l’aspect performance. On veut s’assurer en effet que les workloads à forts besoins en IOPS (base de données, etc) soient bien placés sur les disques locaux, plus performant que les disques externe.
On rajoute enfin node.longhorn.io/default-node-tags pour faciliter le placement des futurs volumes.
Conclusion
Voilà pour la partie préparatif, il est temps de commencer pour de vrai à la prochaine section.