Logo
Overview
Un Talos européen de qualité - Part III - Infra réseau

Un Talos européen de qualité - Part III - Infra réseau

October 31, 2025
11 min read
part-03

Objectif 🎯

Dans la section précédente, nous sommes arrivés à une infra physique montée avec un kube joignable, mais en statut node.kubernetes.io/not-ready et node.cloudprovider.kubernetes.io/uninitialized. En effet, il nous reste 2 composants essentiels à installer pour que notre cluster soit pleinement fonctionnel :

  • Un CNI (Container Network Interface) pour gérer le réseau des pods et services. Nous utiliserons cilium qui est un CNI moderne, performant et riche en fonctionnalités.
  • Un CCM (Cloud Controller Manager) pour que Kubernetes puisse interagir avec l’infrastructure Hetzner Cloud et récupérer les metadata pour les nodes. Nous utiliserons hcloud-cloud-controller-manager.

On finalisera l’architecture réseau avec cert-manager pour la gestion des certificats TLS.

Initialisation

L’architecture du projet Terraform cible est le suivant :

ohmytalos-cluster/
├── clusters
│ └── dev-hcloud
│ └── ...
│ └── dev-kube
│ ├── .envrc
│ ├── flux.tf
│ ├── locals.tf
│ ├── module-crds.tf
│ ├── module-database.tf
│ ├── module-delivery.tf
│ ├── module-ingress.tf
│ ├── module-monitoring.tf
│ ├── module-network.tf
│ ├── module-storage.tf
│ ├── terraform.tf
│ └── variables.tf
├── modules
└── hcloud
└── ...
└── kube
└── crds
│ ├── main.tf
│ └── variables.tf
├── database
│ ├── cnpg.tf
│ ├── dragonfly.tf
│ ├── longhorn.tf
│ ├── pgadmin.tf
│ ├── talos.tf
│ └── variables.tf
├── delivery
│ ├── flux.tf
│ ├── kustomization.yaml
│ ├── providers.tf
│ └── variables.tf
├── ingress
│ ├── cert-manager.tf
│ ├── crowdsec.tf
│ ├── haproxy.tf
│ ├── traefik.tf
│ └── variables.tf
├── monitoring
│ ├── alloy.tf
│ ├── grafana.tf
│ ├── loki.tf
│ ├── prometheus.tf
│ ├── tempo.tf
│ └── variables.tf
├── network
│ ├── cert-manager.tf
│ ├── cilium.tf
│ ├── hccm.tf
│ ├── metrics-server.tf
│ └── variables.tf
└── storage
├── cnpg.tf
├── longhorn.tf
└── variables.tf

Il sera donc décomposé en 5 grands modules :

  • module-crds pour les Custom Resource Definitions de base nécessaires aux autres modules
  • module-network pour l’architecture réseau (CNI, CCM, certificats, service mesh)
  • module-storage pour l’architecture de stockage (CSI, opérateurs de bases de données et backup)
  • module-ingress pour la construction de l’ingress public et privé, ainsi que WAF et certificats TLS
  • module-database pour la création de clusters de base de données et définition des backups
  • module-monitoring pour la supervision des métriques, logs et tracing

State

Le plus simple est de stocker l’état Terraform dédié au kube dans le même backend S3, juste à côté du state dédié à la partie hcloud, sous terraform/kube.tfstate. On en profite pour définir les providers kubernetes et helm en leur indiquant la config d’accès kube.

clusters/dev-kube/terraform.tf
backend "s3" {
endpoints = {
s3 = "https://s3.gra.io.cloud.ovh.net"
}
skip_credentials_validation = true
skip_region_validation = true
skip_requesting_account_id = true
skip_s3_checksum = true
region = "gra"
bucket = "ohmytalos-dev"
key = "terraform/kube.tfstate"
encrypt = true
}
}
provider "kubernetes" {
config_path = "~/.kube/config"
}
provider "helm" {
kubernetes = {
config_path = "~/.kube/config"
}
}
Warning (kubernetes secret)

Le state étant inextricablement lié au cluster cible, vous pourriez éventuellement vous dire que l’on pourrait le stocker dans un secret kubernetes en utilisant le backend kubernetes comme suit :

clusters/dev-kube/terraform.tf
terraform {
backend "kubernetes" {
config_path = "~/.kube/config"
secret_suffix = "talos"
}
}
//...

En soi cela peut fonctionner, mais ce n’est clairement pas la bonne façon de procéder, en raison du risque de fuite du state accru (nécessite la mise en place d’RBAC), risque de dépendance circulaire.

CRDs

On commence par créer le module module-crds qui va installer 2 CRDs majeurs que l’on retrouvera sur tous les autres modules :

  • traefik-crds pour les IngressRoute et Middleware
  • prometheus-crds pour les ServiceMonitor et PodMonitor

Créer les 2 fichiers suivants :

clusters/dev-kube/module-crds.tf
module "kube_crds" {
source = "../../modules/kube/crds"
}
modules/kube/crds/main.tf
resource "helm_release" "prometheus_operator_crds" {
repository = "https://prometheus-community.github.io/helm-charts"
chart = "prometheus-operator-crds"
version = "26.0.0"
name = "prometheus-operator-crds"
namespace = "kube-system"
max_history = 2
}
resource "helm_release" "traefik_crds" {
repository = "https://traefik.github.io/charts"
chart = "traefik-crds"
version = "1.14.0"
name = "traefik-crds"
namespace = "kube-system"
max_history = 2
}

On commence facile, avec l’installation des CRDs via les charts Helm officiels. On indique max_history = 2 pour ne pas garder inutilement un tas d’historiques de versions dans le cluster. Les versions de chart helm seront indiquées en dur, cela ne posera aucun problème à des outils tel que renovate pour maintenir vos versions à jour.

Comme précédemment sur le projet hcloud, préparer le fichier .envrc pour le chargement des secrets pour l’accès au state :

clusters/dev-kube/.envrc
BW_SESSION="$(bw unlock --raw)"
COLLECTION_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ITEMS=$(bw list items --collectionid $COLLECTION_ID --session $BW_SESSION)
bw_field() {
echo "$ITEMS" | jq -r --arg field "$1" --arg name "$2" \
'.[] | select(.name==$name) | .login[$field]'
}
export AWS_ACCESS_KEY=$(bw_field username terraform_state_s3)
export AWS_SECRET_KEY=$(bw_field password terraform_state_s3)
export AWS_SSE_CUSTOMER_KEY=$(bw_field password terraform_state_sse_c)

Enfin lancer la commande terraform init puis terraform apply dans le dossier clusters/dev-kube et confirmer l’installation des CRDs.

Cilium et HCCM

On peut maintenant passer au module module-network pour installer Cilium et le cloud controller manager.

clusters/dev-kube/locals.tf
locals {
cluster_name = "ohmytalos-dev"
internal_domain = "dev.ohmytalos.com"
}
clusters/dev-kube/module-network.tf
module "kube_network" {
source = "../../modules/kube/network"
pod_ipv4_cidr = "10.42.0.0/16"
internal_domain = local.internal_domain
hcloud_token = var.hcloud_token
hcloud_network = local.cluster_name
}
Explanation

Cilium aura besoin de connaître le CIDR utilisé pour les pods pour la création dynamique des routes sur le network hcloud natif.

Nous utiliserons dev.ohmytalos.com comme domaine interne pour les services accessibles uniquement via le réseau privé Tailnet. La génération des certificats TLS, nécessairement via challenge DNS-01, sera gérée par cert-manager plus tard.

Côté hccm, dans le cadre de la création des routes, ce dernier a besoin de connaître le nom du réseau Hetzner Cloud à utiliser, nommé selon le nom du cluster. Un token d’API Hetzner Cloud en écriture est évidemment indispensable pour créer les routes ainsi que le load-balancer dynamiquement plus tard via Traefik.

Le coeur de la config réseau est maintenant en place. Vous pouvez relancer terraform apply dans le dossier clusters/dev-kube pour installer notre duo Cilium et HCCM.

Si tout se passe bien, les noeuds devraient rapidement passer en statut Ready et en statut cloud initialisé. Vous pouvez vérifier cela avec les commandes suivantes (j’utiliserais dorénavant les alias fournis par oh-my-zsh pour kubectl) :

Terminal window
kgno
kdno okami-dev-control-plane-nbg1

Vous devriez apercevoir cette ligne spécifique indiquant que le CCM est bien actif :

# ...
ProviderID: hcloud://xxxxxxxxx # où xxxxxxxxx est l'ID du serveur Hetzner Cloud

Etant donné l’usage du mode natif pour Cilium, vous devriez également voir les routes dynamiques créées sur le réseau Hetzner Cloud, une correspondant à chaque nœud, et permettant la communication entre les pods à travers les différents nœuds via le réseau “physique” Hetzner Cloud :

Routes Hetzner

Vous pouvez maintenant lancer talosctl -n 10.0.0.2 health pour vérifier l’état de santé global du cluster. Tout devrait répondre correctement. Utiliser cilium status pour vérifier que Cilium est bien opérationnel.

Notre cluster kube est dorénavant pleinement fonctionnel et utilisable.

Metrics Server

Nous allons installer metrics-server pour bénéficier de certaines métriques propres à l’usage courant de Kubernetes.

modules/kube/network/metrics-server.tf
resource "helm_release" "metrics_server" {
repository = "https://kubernetes-sigs.github.io/metrics-server"
chart = "metrics-server"
version = "3.13.0"
name = "metrics-server"
namespace = "kube-system"
max_history = 2
set = [
{
name = "metrics.enabled"
value = "true"
},
{
name = "serviceMonitor.enabled"
value = "true"
}
]
depends_on = [
helm_release.hccm
]
}

Ceci vous permettra notamment l’utilisation de k top nodes et k top pods pour voir l’usage CPU/mémoire de vos nœuds et pods. Il est aussi requis les fonctionnalités d’autoscaling qui ne seront pas l’objet de ce guide.

Cert-Manager

Dernière étape réseau, l’installation de cert-manager pour la gestion des certificats TLS. Nous en aurons besoin pour les certificats internes et externes.

modules/kube/network/cert-manager.tf
resource "kubernetes_namespace_v1" "cert_manager" {
metadata {
name = "cert-manager"
}
depends_on = [helm_release.hccm]
}
resource "helm_release" "cert_manager" {
repository = "https://charts.jetstack.io"
chart = "cert-manager"
version = "v1.19.2"
name = "cert-manager"
namespace = kubernetes_namespace_v1.cert_manager.metadata[0].name
max_history = 2
set = [
{
name = "crds.enabled"
value = "true"
},
{
name = "prometheus.servicemonitor.enabled"
value = "true"
}
]
}

Conclusion

Les principaux composants réseau sont maintenant en place. Assurez-vous d’avoir un terraform apply propre avant de continuer, suite à la prochaine section pour l’installation de l’infra de stockage.