Introduction
Une Graine est une plateforme de tests, d’exploration et de partage entre passionnés et anciens collègues.
Rien n’est parfait et tout nous pousse vers toujours plus de compréhension, de maîtrise, d’expertise dans différents domaines et contextes.
Les choix sont très souvents expliqués ou même documentés.
Ce book est commun et chacun est libre de l’éditer. Il est généré à l’aide de mdBook.
Projet Graine
Les sources du projet Graine sont disponibles ici.
Vous pouvez lire l’ensemble des pages suivantes si vous souhaitez vous servir des sources pour vos propres besoins, ou par plaisir 🤓
Providers
Une Graine est hébergé sur les datacenters européens du provider Hetzner et utilise les services de 1Password, Gandi, Posteo et Let’s Encrypt.
Ces choix sont expliqués dans les pages suivantes.
1Password
Ce service est utilisé pour:
- stocker des secrets
- alimenter les données sensibles IaC
- alimenter les objets
Secretsdu cluster via l’opérateur1Password Connect
Le coût pour un compte individuel est de 38,16€ TTC par an.
Choix
1Password est retenu comme gestionnaire de secrets pour les raisons suivantes:
Les +
- expérience globale:
- génération de mot de passe / passphrase complexe
- ACL sur les coffres
- le CLI est utile sur plusieurs niveaux (local et CI/CD par exemple)
- le coût annuel du premier forfait est bien plus raisonnable comparé à d’autres solutions
- expérience personnelle
- gestion des MFA
- intégration avec le navigateur
- expérience professionelle
- facilite l’expérience local
- possibilité de n’avoir aucuns secrets stockés en local (dans un dotenv par exemple)
- intégration kubernetes simple et performante
Les -
- pas de relation entre les objets
- on peut les référencer mais l’injection ne prend pas encore en charge les références
- la recherche n’est pas précise
- si vous cherchez un secret par un mot ou un ensemble de mots stricts, il n’est pas certain que vous trouviez une correspondance
- il est donc nécessaire d’utiliser toutes les fonctions d’un objet, comme les tags, et d’établir règle de nommage précise pour retrouver un secret
Autres solutions testées
Les deux premières solutions ici sont différentes dans le sens où nous avons déployé les solutions afin de les tester, contrairement à 1Password où nous n’utilisations que l’opérateur. De plus, la question se pose d’utiliser ces solutions sur le même cluster où les secrets seront injectés…
Vault = non !
- Vault
- l’installation n’est pas vraiment simple
- la sécurité non plus
- les ressources nécessaires sont à prendre en considération, surtout en haute disponibilité (recommandé)
- l’injection des secrets devient vite compliqué
OpenBao = non plus !
- OpenBao
- Bao est un fork de Vault, faisant suite au rachat d’HashiCorp par IBM et la modification des licences. Il n’y a que peu de différence avec Vault, même dans sa version 2.0.
Pulumi ESC = presque oui !
- Pulumi ESC
- les solutions Pulumi sont plutôt intéressantes et stables
- l’intégration avec Kubernetes est simple et l’injection des secrets l’est tout autant
- son utilisation sur un compte gratuit est possible avec quelques limites toutefois difficile à identifier dans l’immédiat puisque la documentation est pauvre sur les différences avec le premier forfait payant (40$/mo !)
Hetzner
Hetzner est un provider Allemand dont les datacenters Européens sont situés sur les sites de Nuremberg (NBG), Falkenstein (FSN) et Helsinki (HEL).
En dehors d’un coût très faible, Hetzner est très stable, est certifié ISO 27001:2022, ISO 14001:2015 et bien d’autres. Enfin, Hetzner propose des VPS et des Serveurs dédiés type ARM (Ampere) d’une grande performance.
Le coût mensuel de la plateforme - composée de 5 VPS, 2 Load Balancer, 5 Primary IP , 4 Volumes et 1 zone DNS - est de moins de 50€ TTC, soit le prix moyen d’un VPS ARM chez Scaleway.
Choix
Le choix du provider s’est fait selon les critères suivants:
- architecture ARM
- stabilité reconue
- datacenter bas carbone
- tarifs
- feedback
| Provider | ARM | Localisation | Stable | Bas carbone | Tarifs |
|---|---|---|---|---|---|
| AWS | Oui | Europe | Moyen | Non | Élevé |
| Oui | Europe | Oui | Non | Très Élevé | |
| Azure | Oui | France | Oui | Non | Élevé |
| OVH | Non | - | Non | Non | Bas |
| Hetzner | Oui | Europe | Oui | Oui | Bas |
| Scaleway | Oui | France | Non | Oui | Élevé |
Feedbacks:
- AWS: Les services managés sont top. Docs et configurations plutôt lourdes. Très opaque sur consommation énergétique.
- Google: On se perd dans trop de docummentation multi-niveaux et configurations parfois lourdes. Surconsommation d’eau pour refroidir leur datacenter (étiquette low-carbon mensongère)
- Azure: Deux ans d’expérience, deux ans de sueurs. Très opaque sur consommation énergétique.
- Hetzner: Plusieurs feedback de scale-up et grands saas. Focus sur la fourniture de Bare Metal et VPS pour une grande stabilité. Transparent sur sa consommation énergétique. D’un point de vue production entreprise: Plus d’un an avec ce provider et seulement 1 incident mineur de moins de 30 minutes.
- Scaleway: Deux ans d’expérience. 1 incident mineur par mois et 1 incident majeur par trimestre en moyenne. Plutôt transparent sur sa consommation énergétique.
Bien qu’Hetzner ne soit pas présent en france, le provider répond à un nombre suffisant de critères.
Posteo
Posteo est un service mail Allemand.
C’est un serive mail payant dont le coût est de 12€ TTC par an.
Choix
Le choix d’utiliser Posteo repose sur divers critères dont les plus importants sont les suivants:
- Chiffrement complet
- Électricité 100% verte
- 2FA
- Protection des données, aucun traçage ni publicité
- Création de token pour l’utilisation du protocole SMTP
- 2 alias gratuits
Autre solutions
Note
Si vous n’envisagez pas l’envoi de notifications mail, le provider mail n’est pas nécessaire !
Gandi
Gandi est utilisé comme registrar pour le domaine une-graine.fr.
Choix
Le service d’enregistrement de nom de domaine est utilisé par Mathieu depuis plus de 20 ans sans qu’il n’y ait eu d’incident. Il paraît donc naturel de leur faire à nouveau confiance.
Autres solutions
Let’s Encrypt
Let’s Encrypt est une Authorité de Certification.
Libre d’une quelconque interface et de compte, nous nous en servons générer des certificats TLS et ainsi proposer une navigation sécurisée.
Les certificats de Let’s Encrypt ont une durée de vie de 3 mois.
Nous utilisons l’outil Cert Manager afin d’automatiser la génération et le renouvellement des certificats.
Choix
Le choix de Let’s Encrypt s’est fait pour deux raisons:
- gratuité du service
- pas de compte nécessaire
- intégration simple avec Cert Manager et le solver
dns01 - pas d’enregistrements DNS ACME poluants
Autre solution
Peu de veille sur d’autres solutions.
Une seule autre solution éprouvée: ZeroSSL
Après plus de 3 ans d’utilisation en milieu professionnel, son seul intérêt est la possibilité de générer des certificats d’1 an et une certaine stabilité.
De plus, son offre gratuite est très limité.
Prérequis
L’ensemble des projets repose sur divers outils ou services.
1Password, Hetzner, Posteo et Gandi demandent quelques actions manuelles, expliquées dans les pages suivantes.
La page Recommandation est dédiée à 1Password pour une bonne organisation et gestion des secrets.
Recommandation
1Password
Vous le verrez pas la suite, nous faisons régulièrement appel à 1Password.
Lors des précédentes expériences avec le CLI et l’opérateur, l’approche était d’utiliser les UID des coffres et des objets.
C’est une bonne pratique dans le sens où ces UID ne changent pas.
En revanche, ça devient compliqué lorsque l’on utilise plusieurs coffres et que nous cherchons plusieurs objets, pour des dizaines de services et d’environnements.
Avant
{{op://b359a4160b93b562f5e356988/b7b3741739d732b5ed371d5b3/SECRET}}
{{op://b359a4160b93b562f5e356988/f3c1b48438b2489fb89fcae30/SECRET}}
{{op://071f644d5b1b58014541b8d98/61b24431093fe1d8519ceaaf9/SECRET}}
ou encore, pour les objets OnePasswordItem Kubernetes:
vaults/b359a4160b93b562f5e356988/items/b7b3741739d732b5ed371d5b3
vaults/b359a4160b93b562f5e356988/items/f3c1b48438b2489fb89fcae30
vaults/071f644d5b1b58014541b8d98/items/61b24431093fe1d8519ceaaf9
Après
Pour redonner un peu de lisibilité, une règle de nommage est appliquée sous la forme suivante:
- le nom du coffre et des objets est en minuscule, sans espaces, underscore autorisé
- les objets suivent les règles de nommage suivantes:
context_service_targetcontext_service
- le context peut avoir les valeurs:
- iac: objet utilisée uniquement par
graine-cluster - gitops: objet utilisée uniquement par
graine-gitops - shared: objet pouvant être utilisée par de multiple sources (dev, gitops, iac)
- iac: objet utilisée uniquement par
Ainsi, nous obtenons:
{{op://graine/iac_csi_volumes_passphrase/VOLUMES_PASSPHRASE}}
{{op://graine/iac_forgejo_smtp/SMTP_ADDRESS}}
{{op://graine/iac_forgejo_smtp/SMTP_PORT}}
{{op://graine/iac_hetzner_token/HETZNER_TOKEN}}
{{op://graine/iac_lets_encrypt/EMAIL}}
{{op://graine/iac_op_connect/OP_CONNET_TOKEN}}
{{op://graine/shared_forge_registry/ACCESS_KEY}}
{{op://graine/shared_forge_registry/EMAIL}}
{{op://graine/shared_service_token/TOKEN}}
vaults/graine/items/gitops_harbor_cache
vaults/graine/items/gitops_harbor_database
vaults/graine/items/shared_forge_registry
vaults/graine/items/shared_service_token
Note
ces règles peuvent encore évoluées !
1Password - Compte & Ops
La création d’un compte est nécessaire.
Créez un coffre
Il est préférable de créer un coffre dédié au projet. Par exemple, pour ce projet, nous utilisons le coffre graine qui ne contient que les secrets du projet.
Vous pouvez créer le coffre en passant par l’application web ou en passant par l’application lourde.
Créez un connecteur
-
Sur l’interface web, dirigez-vous vers
DéveloppeurpuisServeurs de connexion -
Cliquez un
Nouveau serveur de connexion -
Saisissez le nom de l’environnement cible puis sélectionnez le coffre précédemment créé, en
lectureuniquement
-
Cliquez sur
Ajouter un environnement -
Saisissez un nom de token, son expiration et de nouveau, sélectionnez le coffre précédemment créé, toujours en lecture uniquement

-
Cliquez sur
Émettre le jeton -
Sur l’étape suivante, enregistrez le fichier JSON ainsi que le token dans votre coffre dédié

-
Vous avez maintenant 2 objets dans votre coffre contenant le JSON et le token

OP CLI
- Installez le CLI 1Password
- Si vous utilisez le client lourd et que vous souhaitez récupérer les UID, activez l’option suivante

Hetzner - Compte & Ops
La création d’un compte est nécessaire.
Informations et limites
Comme la majorité des providers (AWS fait exception), les VPS d’Hetzner sont limités à 16 volumes attachés.
De plus, il vous faudra une ancienneté d’un mois avant de pouvoir lever les limites et restrictions suivantes:
| VPS | Volumes | Snapshots | Floating IP | Primary IP | L.B. | DNS |
|---|---|---|---|---|---|---|
| 5 | 1024 Go | 30 | 10 | 5 | 5 | 25 |
Passé un mois et sans incident sur votre compte, une simple demande au support permet d’augmenter ces limites.
SSH Keys
- Générez une clé SSH dédiée
ssh-keygen -t ed25519 -C "your_email@example.com" -f $HOME/.ssh/hetzner_ed25519 - Créez un objet dans votre coffre 1Password et ajouter la clé publique et privée
- Connectez-vous à la console Cloud Hetzner
- Cliquez sur
Security - Dans la section
SSH Keys, ajoutez votre clé SSH publique
Note: Le nom que vous donnez à cette clé est importante et nécessaire lors de l’initialisation d’un VPS.
API Token
- Connectez-vous à la console Cloud Hetzner
- Cliquez sur
Security - Dans la section
API Tokens, créez un token en lecture + écriture - Créez un objet dans votre coffre 1Password contenant ce token
DNS Zones
- Connectez-vous à la console Cloud Hetzner
- Cliquez sur
DNS - Cliquez sur
Add DNS Zone - Saisissez votre nom de domaine
- Sélectionnez
Create an empty zone - Cliquez sur
Add DNS zone
La zone est alors créée en quelques secondes et contient les enregistrements NS et SOA
Cette zone sera automatiquement alimentée par le projet graine-cluster/hetzner-base suivant vos besoins.
Notes
L’ajout de la clé SSH ainsi que la création de la zone DNS peuvent être incluent dans le projet graine-cluster/hetzner-base.
🚧 En cours de tests !
Gandi
Que ce soit Gandi ou un autre registrar, le plus important est d’avoir la possibilité de configurer les Serveurs de noms.
La liste est la suivante:
helium.ns.hetzner.de
hydrogen.ns.hetzner.com
oxygen.ns.hetzner.com
Exemple avec Gandi:

Posteo
Si vous souhaitez utiliser Posteo et afin de pouvoir utiliser le protocole SMTP, il est nécéssaire de créer un mot de passe d’application.
Pour cela:
- connectez-vous à votre compte Posteo
- allez dans les
Paramètres - allez dans
Mot de passe et sécurité - en bas de la page, dans le bloc
Mots de passe d'application (mots de passe d'appareils)- cliquez sur
Créer un mot de passe d'application - saisissez une
Description - sauvegardez le mot de passe généré par Posteo dans 1Password
- saisissez le mot de passe vous permettant de vous connecter à votre compte
- validez la création
- cliquez sur
Lorsque vous souhaiterez utiliser le protocole SMTP de Posteo, les informations seront les suivantes:
- serveur:
posteo.de - port:
465ou587, en fonction du chiffrement souhaité - login: votre identifiant de connexion ou un alias
- mot de passe: le mot de passe d’application que vous venez de générer
Graine Cluster
Le cluster d’Une Graine est déployé suivant la topologie HA Stacked
Il se compose de:
- 3 control plane CAX11 sur les sites NBG, FSN et HEL
- 2 worker CAX21 sur le site NBG
- 1 worker CAX21 sur le site FSN (soon)
- 2 load balancer LB11 sur le site NBG
Organisation des sources
hetzner-infrastructure ne contient que l’IaC concernant l’infrastructure et l’initialisation du cluster en utilisant principalement le provider tofu/terraform hetznercloud/hcloud.
hetzner-base ne contient que l’IaC concernant le socle applicatif du cluster.
Les services et les applications sont quant à eux uniquement gérés par ArgoCD via le projet graine-gitops
Prérequis
Pour initier le cluster, il vous faudra:
Hetzner Infrastructure
Prenez le temps de lire les points suivants 😉
Note
On ajoute
NodeRestrictionetPodNodeSelectorau plugin Admission Control ce qui nous donnera la possibilité de restreindre un Namespace à utiliser un worker ou un pool de worker.Le runtime utilisé est Containerd
Prérequis
Vous devez créer 4 objets dans votre coffre 1Password dédié.
Objets
iac_kubeconfig
- desc: Fichier kubeconfig
- type: fichier
- clés: laisser l’objet vide, il sera alimenté à l’initialisation du cluster
iac_hetzner_token
- desc: Token Hetzner
- type: string
- clés:
HETZNER_TOKEN: valeur du token
iac_ssh_keys
- desc: Clé SSH publique et privée
- type: fichier(s)
- clés:
argocd_ed25519argocd_ed25519.pub
iac_vps_sshd_port
- desc: Port SSH personnalisé
- type: string
- clés:
VPS_SSH_PORT: une valeur autre que22
Fichier(s) objet
Le fichier graine_ssh_key.dist doit être modifié selon:
- le nom de votre coffre
- le nom de l’objet si modifié
- le nom de la clé SSH privée
Vous pouvez également renommer ce fichier, il vous faudra alors modifier La ligne 16 et 17 de Taskfile.
Terraform tfvars dist
Ici nous allons nous attarder sur le fichier de distribution tfvars dont le contenu est le suivant:
#######################
# YOU CAN EDIT #
#######################
control_plane = [
{
name = "control-plane-nbg"
# 10.0.1.0/24 range
private_ip = "10.0.1.10"
location = "nbg1"
model = "cax11"
image = "ubuntu-24.04"
# place is_main where you want the main control plane
is_main = true
},
{
name = "control-plane-fsn"
# 10.0.1.0/24 range
private_ip = "10.0.1.11"
location = "fsn1"
model = "cax11"
image = "ubuntu-24.04"
},
{
name = "control-plane-hel"
# 10.0.1.0/24 range
private_ip = "10.0.1.12"
location = "hel1"
model = "cax11"
image = "ubuntu-24.04"
}
]
node = [
# Pool Graine
{
name = "terre"
# 10.0.1.0/24 range
private_ip = "10.0.1.20"
location = "nbg1"
model = "cax21"
image = "ubuntu-24.04"
pool = "graine"
},
{
name = "eau"
# 10.0.1.0/24 range
private_ip = "10.0.1.30"
location = "nbg1"
model = "cax21"
image = "ubuntu-24.04"
pool = "graine"
}
]
cluster_name = "graine"
kubernetes_version = "1.34"
lb_kube_api_location = "nbg1"
lb_kube_api_model = "lb11"
lb_traefik_location = "nbg1"
lb_traefik_model = "lb11"
local_ssh_key_name = "graine_ed25519"
placement_group_name = "graine-placement-group"
private_network_name = "graine-private-network"
ssh_keys = ["graine"]
# Set the vault and item names
op_vault_kubeconfig = "graine"
op_item_kubeconfig = "iac_kubeconfig"
# From 1Password
hetzner_token = "{{op://graine/iac_hetzner_token/HETZNER_TOKEN}}"
sshd_port = "{{op://graine/iac_vps_sshd_port/VPS_SSH_PORT}}"
###################################
# !!! DO NOT EDIT, ADMIN ONLY !!! #
###################################
lb_kube_api_name = "lb-kube-api"
lb_kube_api_private_ip = "10.0.1.2"
lb_traefik_name = "lb-traefik"
lb_traefik_private_ip = "10.0.1.4"
pod_network_cidr = "10.244.0.0/16"
private_network_range = "10.0.1.0/24"
Liste control_plane
control_planeest la liste contenant les specs de nos VPS Control plan.
variable "control_plane" {
description = "List of Control Planes"
type = list(object({
name = string
private_ip = string
location = string
model = string
image = string
ipv4_id = optional(string)
pool = optional(string, "control-plane")
is_main = optional(bool, false)
is_backup = optional(bool, false)
is_amd = optional(bool, false)
workload = optional(string, "")
}))
}
name
Nom du control plan
private_ip
IPv4 privée assignée au control plan, dont le range est
10.0.1.0/24, définit par la variableprivate_network_range
location
Localisation du datacenter parmis les choix fixes suivants:
nbg1,fns1ethel1
model
Model du VPS. Exemple pour les VPS ARM:
CAX11,CAX21,CAX31etCAX41
image
Image de l’OS à utiliser parmis un large choix comme
ubuntu-24.04,debian-13etc
ipv4_id
Optionnel, uniquement si vous possédeez déjà des Primary IPv4
pool
Optionnel, uniquement si vous souhaitez associer vos control plan à un pool. la valeur par défaut est
control-plane
is_main
Semi-optionnel. Au moins un control plan doit avoir cette valeur à
true. Ce sera le control plan où l’initialisation se lancée.
is_backup
N’est utile que pour le
mergeprésent dans04-vps-common-setup.tf
is_amd
N’est utile que pour le
mergeprésent dans04-vps-common-setup.tf
workload
N’est utile que pour le
mergeprésent dans04-vps-common-setup.tf
Liste node
nodeest la liste contenant les specs de nos VPS Worker.
Identique à la liste control_plane, seul les valeurs strictes ou possibles sont expliquées.
variable "node" {
description = "List of Nodes"
type = list(object({
name = string
private_ip = string
location = string
model = string
image = string
ipv4_id = optional(string)
pool = string
is_main = optional(bool, false)
is_backup = optional(bool, false)
is_amd = optional(bool, false)
workload = optional(string, "")
}))
}
pool
Le nom du pool auquel appartient le worker.
is_main
N’est utile que pour le
mergeprésent dans04-vps-common-setup.tf
is_backup
Optionnel. Uniquement si vous déployez des worker de backup sur des datacenter différent.
is_amd
Optionnel. Uniquement si vous déployez des worker dont le vCPU est de type AMD.
workload
Optionnel. Uniquement si le worker appartient à un pool dédié à des montées en charge fréquentes par exemple.
Variables
cluster_name
Nom du cluster. Impact
kubernetes_config_contextd’Hetzner Base
kubernetes_version
Version de Kubernetes à utiliser, sous la forme
"MAJOR.MINOR". Exemple:"1.33","1.34"
lb_kube_api_location
Localisation du load balancer Kube API parmis les choix fixes suivants:
nbg1,fns1ethel1
lb_kube_api_model
Model du load balancer Kube API parmis les choix fixes suivants:
lb11,lb21etlb31
lb_traefik_location
Localisation du load balancer Traefik parmis les choix fixes suivants:
nbg1,fns1ethel1
lb_traefik_model
Model du load balancer TRaefik parmis les choix fixes suivants:
lb11,lb21etlb31
local_ssh_key_name
Nom local de la clé ssh privée. Les lignes 16 et 17 de Taskfile doit être modifiée en conséquence.
placement_group_name
Nom du groupe de placement
ssh_keys
Nom de la clé SSH saisie lors des prérequis Hetzner
op_vault_kubeconfig
Nom du coffre 1Password contenant l’objet
kubeconfig
op_item_kubeconfig
Nom de l’objet 1Password qui recevra le fichier
kubeconfiggénéré
hetzner_token
Chemin 1Password pour récupérer la valeur du token Hetzner. Exemple:
"{{op://graine/iac_hetzner_token/HETZNER_TOKEN}}"
sshd_port
Chemin 1Password pour récupérer la valeur du port SSH. Exemple:
"{{op://graine/iac_vps_sshd_port/VPS_SSH_PORT}}"
Caution
Les variables suivantes sont à éditer en connaissance et avec précaution !
lb_kube_api_name
Nom du load balancer Kube API. En minuscule et sans espaces.
lb_kube_api_private_ip
IPv4 privée du load balancer Kube API
lb_traefik_name
Nom du load balancer Traefik. En minuscule et sans espaces. Impact
lb_traefik_named’Hetzner Base
lb_traefik_private_ip
IPv4 privée du load balancer Traefik
pod_network_cidr
Range CIDR assigné au Pods
private_network_name
Nom du réseau privée. En minuscule et sans espaces. Impact
private_network_named’Hetzner Base
private_network_range
Range du réseau privée. Impact
control_plane,node,lb_kube_api_private_ipetlb_traefik_private_ip
Initialisation
Lorsque les précédentes étapes sont appliquées, lancez les commandes suivantes:
task init
task apply:all
task init va:
- générer le fichier
terraform.tfvarstout en récupérer les valeurs des objets 1Password - télécharger les providers Tofu / Terraform
task apply:all va:
- initialiser votre cluster et les load balancer
- générer le fichier
SUMMARY.mdcontenant les noms des VPS et leur IPv4 publique
Hetzner Base
Les sources de cet IaC déploieront la stack et les configurations suivantes:
- Le CNI Cilium
- Le Cloud Controller Manager d’Hetzner
- Le Container Storage Interface d’Hetzner
- La mise à jour des zones DNS Hetzner
- Divers
StorageClassavec chiffrement - Kubernetes Replicator
- Kubernetes Reloader
- Kubernetes Prometheus Stack
- Kubernetes Metrics Server
- Traefik et plusieurs Middleware
- Le service Kubernetes type LoadBalancer pour router les requêtes
lb-traefik - Cert Manager pour la gestion des certificats
- 1Password Connect
- ArgoCD poru le déploiement d’applications et de services
Optionel:
- Forgejo, le compte de service associé au registre et deux runner act
Prérequis
Vous devez créer plusieurs objets dans votre coffre 1Password dédié.
Objets
iac_argocd_ssh_keys
- desc: Clé SSH publique et privée dédiée à ArgoCD
- type: fichier(s)
- clés:
argocd_ed25519argocd_ed25519.pub
- tips:
ssh-keygen -t ed25519 -C "your_email@example.com" -f $HOME/.ssh/argocd_ed25519
iac_csi_volumes_passphrase
- desc: Passphrase pour le chiffrement des volumes
- type: string
- clés:
VOLUMES_PASSPHRASE: Une passphrase de votre choix
iac_grafana_admin
- desc: Compte admin de Grafana
- type: string(s)
- clés:
admin-user: nom d’utilisateuradmin-password: mot de passe
iac_hetzner_token
déjà présent puisque nécessaire pour Hetzner Infrastructure
- desc: Token Hetzner
- type: string
- clés:
HETZNER_TOKEN: valeur du token
iac_lets_encrypt
- desc: Email à destination de Let’s Encrypt
- type: string(s)
- clés:
EMAIL: une adresse mail valide
iac_op_connect
- desc: Token et JSON 1Password
- type: mixte
- clés:
OP_CONNET_TOKEN: le token du connecteur1password-credentials.json
Objets Optionels
iac_forgejo_admin
- desc: Compte admin de Forgejo
- type: string(s)
- clés:
username: nom d’utilisateurpassword: mot de passeemail: une adresse mail valide
iac_forgejo_runners
- desc: Configuration des runners
- type: string(s)
- clés:
CONFIG_INSTANCE: url de la forge (exemple: https://forge.tools.une-graine.fr)CONFIG_NAME: nom du pool de runnerCONFIG_TOKEN: valeur temporaire
iac_forgejo_smtp
- desc: Configuration SMTP
- type: string(s)
- clés:
SMTP_FROM: une adresse mail valideSMTP_PROTOCOL: le protocol utilisé (ex posteo:smtp+starttls)SMTP_ADDRESS: l’adresse du serveur SMTP (ex posteo:posteo.de)SMTP_PORT: le port à utiliser (ex posteo:465ou587)SMTP_ACCESS_KEY: le nom du compte autorisé à utiliser le serveur SMTPSMTP_SECRET_KEY: le secret associé àSMTP_ACCESS_KEY(exemple posteo)
shared_forge_argocd
- desc: Compte ArgoCD pour à la forge
- type: string(s)
- clés:
ACCESS_KEY: le nom du compteSECRET_KEY: mot de passe du compteEMAIL: une adresse mail valide
shared_forge_dispatch
- desc: token du compte ArgoCD pour la forge
- type: string
- clés:
TOKEN: valeur temporaire
shared_forge_registry
- desc: Compte de service pour accéder au registre Forgejo
- type: string(s)
- clés:
ACCESS_KEY: le nom du compteSECRET_KEY: mot de passe du compteEMAIL: une adresse mail valide
Fichier(s) objet
Les fichiers:
Doivent être modifiés selon:
- le nom de votre coffre
- le nom de l’objet si modifié
Vous pouvez également renommer ces fichier, il vous faudra alors modifier Les lignes 17 à 19 de Taskfile.
Terraform tfvars dist
Ici nous allons nous attarder sur le fichier de distribution tfvars dont le contenu est le suivant:
#######################
# YOU CAN EDIT #
#######################
namespaces = [
{
name = "base-services"
},
{
name = "shared-services"
},
{
name = "internal-services"
},
{
name = "monitoring-services"
},
]
dns = [
{
content = "@"
type = "A"
},
{
content = "www"
type = "A"
},
{
content = "*.internal"
type = "A"
},
{
content = "*.tools"
type = "A"
}
]
cert_manager_dns_list = [
# A Records (wilcard)
{
is_wildcard = true
name = "internal"
sub = "*.internal"
},
{
is_wildcard = true
name = "tools"
sub = "*.tools"
},
# A Records
{
is_wildcard = false
name = "www"
sub = "www"
}
]
argocd_url = "https://gitops.internal.une-graine.fr"
domain_name = "une-graine.fr"
forge_enabled = true
forge_ingress_cluster_issuer = "letsencrypt-tools-wildcard"
forge_ingress_tls_secret = "forgejo-tools-wildcard-cert"
forge_ssh_url = "ssh://git@forge.tools.une-graine.fr:13924/graine"
forge_ssh_port = "13924"
forge_url = "forge.tools.une-graine.fr"
grafana_admin_secret = "vaults/graine/items/iac_grafana_admin"
smtp_subject_prefix = "Une Graine - "
# Set the items path
argocd_dispatch_object = "vaults/graine/items/shared_forge_dispatch"
forge_admin_secret_object = "vaults/graine/items/iac_forgejo_admin"
forge_runner_secret_object = "vaults/graine/items/iac_forgejo_runners"
# From 1Password
argocd_ssh_key_pub = "{{op://graine/iac_argocd_ssh_keys/argocd_ed25519.pub}}"
forge_admin_access_key = "{{op://graine/iac_forgejo_admin/username}}"
forge_admin_email = "{{op://graine/iac_forgejo_admin/email}}"
forge_admin_secret_key = "{{op://graine/iac_forgejo_admin/password}}"
forge_argocd_access_key = "{{op://graine/shared_forge_argocd/ACCESS_KEY}}"
forge_argocd_email = "{{op://graine/shared_forge_argocd/EMAIL}}"
forge_argocd_secret_key = "{{op://graine/shared_forge_argocd/SECRET_KEY}}"
forge_registry_access_key = "{{op://graine/shared_forge_registry/ACCESS_KEY}}"
forge_registry_email = "{{op://graine/shared_forge_registry/EMAIL}}"
forge_registry_secret_key = "{{op://graine/shared_forge_registry/SECRET_KEY}}"
hetzner_token = "{{op://graine/iac_hetzner_token/HETZNER_TOKEN}}"
letsencrypt_email = "{{op://graine/iac_lets_encrypt/EMAIL}}"
smtp_address = "{{op://graine/iac_forgejo_smtp/SMTP_ADDRESS}}"
smtp_from = "{{op://graine/iac_forgejo_smtp/SMTP_FROM}}"
smtp_port = "{{op://graine/iac_forgejo_smtp/SMTP_PORT}}"
smtp_protocol = "{{op://graine/iac_forgejo_smtp/SMTP_PROTOCOL}}"
smtp_access_key = "{{op://graine/iac_forgejo_smtp/SMTP_ACCESS_KEY}}"
smtp_secret_key = "{{op://graine/iac_forgejo_smtp/SMTP_SECRET_KEY}}"
volumes_passphrase = "{{op://graine/iac_csi_volumes_passphrase/VOLUMES_PASSPHRASE}}"
onepassword_token = "{{op://graine/iac_op_connect/OP_CONNET_TOKEN}}"
#######################################
# !!! DO NOT EDIT UNLESS YOU KNOW !!! #
#######################################
kubernetes_config_path = "./sensitive/kubeconfig.yaml"
kubernetes_config_context = "kubernetes-admin@graine"
lb_traefik_name = "lb-traefik"
onepassword_credentials_file_name = "1password-credentials.json"
private_network_name = "graine-private-network"
Liste namespaces
namespaces est la liste des namespaces qui seront créés.
variable "namespaces" {
description = "List of Namespaces"
type = list(object({
name = string
pool = optional(string, "")
}))
}
name
Nom du namespace
pool
Uniquement si vous associez un namespace à un pool de worker
Caution
Les namespaces
base-services,shared-services,internal-servicesetmonitoring-servicessont requis pour le déploiement du socle.Si vous souhaitez modifier les noms, il faudra alors mettre à jour toutes les ressources TF.
Liste dns
dnsest la liste des enregistrements DNS qui seront mis à jour dans le DNS Zone d’Hetzner.
variable "dns" {
description = "Zone pointing to LB Traefik"
type = list(object({
content = string
type = string
}))
}
content
@pourallet les sous domaines
type
Type d’enregistrement (
A,CNAMEetc)
Liste cert_manager_dns_list
cert_manager_dns_list est la liste des sous domaines pour lesquels des certificats seront créés et distribués dans les différents namespaces.
variable "cert_manager_dns_list" {
description = "List of Wildcard"
type = list(object({
is_wildcard = bool
name = string
sub-name = optional(string, "")
sub = string
}))
}
is_wildcard
S’il s’agit d’un wildcard
name
Nom sera utilisé dans différents CRD de Cert Manager
sub-name
Unqiuement si l’on souhaite un sous-sous-domaine. Par exemple, si vous souhaitez le sous domaine
*.perso.tools, alors la valeur desub-nameseraperso.tools
sub
Sous domaine (exemple:
*.tools)
Note
Les noms des Issuers seront sous les formes suivantes:
letsencrypt-{name}-wildcardsiis_wildcardest àtrueletsencrypt-{name}siis_wildcardest àfalseLes noms des certificats seront sous les formes suivantes:
{name}-wildcard-certsiis_wildcardest àtrue{name}-certsiis_wildcardest àfalse
Variables
argocd_url
URL d’ArgoCD (exemple:
https://gitops.internal.une-graine.fr)
domain_name
Nom de domaine (exemple:
une-graine.fr)
forge_enabled
On passe à
falsesi l’on ne souhaite déployer la forge et ses composants
forge_ingress_cluster_issuer
Optionel. Nom de l’issuer Cert Manager
forge_ingress_tls_secret
Optionel. Nom du secret contenant le certificat
forge_ssh_url
Optionel. URL SSH de la forge à destination d’ArgoCD. Comme nous utilisons un port différent de
22, l’URL est sous la forme suivante:ssh://git@{forge_url}:{forge_ssh_port}/{projet}
forge_ssh_port
Optionel. Port SSH, différent de
22. Impactforge_ssh_url
forge_url
Optionel. URL de la forge. Impact
forge_ssh_url
grafana_admin_secret
Chemin standard vers l’objet 1Password
iac_grafana_admin(exemple:vaults/graine/items/iac_grafana_admin)
smtp_subject_prefix
Optionel. Préfixe des objets des emails envoyés par la forge
forge_admin_secret_object
Optionel. Chemin standard vers l’objet 1Password
iac_forgejo_admin(exemple:vaults/graine/items/iac_forgejo_admin)
forge_runner_secret_object
Optionel. Chemin standard vers l’objet 1Password
iac_forgejo_runners(exemple:vaults/graine/items/iac_forgejo_runners)
argocd_dispatch_object
Optionel. Chemin standard vers l’objet 1Password
shared_forge_dispatch(exemple:vaults/graine/items/shared_forge_dispatch)
argocd_ssh_key_pub
Optionel. Chemin CLI vers le fichier
argocd_ed25519.pubde l’objet 1Passwordiac_argocd_ssh_keys(exemple:{{op://graine/iac_argocd_ssh_keys/argocd_ed25519.pub}})
forge_admin_access_key
Optionel. Chemin CLI vers la clé
usernamede l’objet 1Passwordiac_forgejo_admin(exemple:{{op://graine/iac_forgejo_admin/username}})
forge_admin_email
Optionel. Chemin CLI vers la clé
iac_forgejo_admin(exemple:{{op://graine/iac_forgejo_admin/email}})
forge_admin_secret_key
Optionel. Chemin CLI vers la clé
passwordde l’objet 1Passwordiac_forgejo_admin(exemple:{{op://graine/iac_forgejo_admin/password}})
forge_argocd_access_key
Optionel. Chemin CLI vers la clé
ACCESS_KEYde l’objet 1Passwordshared_forge_argocd(exemple:{{op://graine/shared_forge_argocd/ACCESS_KEY}})
forge_argocd_email
Optionel. Chemin CLI vers la clé
shared_forge_argocd
forge_argocd_secret_key
Optionel. Chemin CLI vers la clé
SECRET_KEYde l’objet 1Passwordshared_forge_argocd
forge_registry_access_key
Optionel. Chemin CLI vers la clé
ACCESS_KEYde l’objet 1Passwordshared_forge_registry(exemple:{{op://graine/shared_forge_registry/ACCESS_KEY}})
forge_registry_email
Optionel. Chemin CLI vers la clé
shared_forge_registry
forge_registry_secret_key
Optionel. Chemin CLI vers la clé
SECRET_KEYde l’objet 1Passwordshared_forge_registry
hetzner_token
Chemin CLI vers la clé
HETZNER_TOKENde l’objet 1Passwordiac_hetzner_token
letsencrypt_email
Chemin CLI vers la clé
iac_lets_encrypt
smtp_address
Optionel. Chemin CLI vers la clé
SMTP_ADDRESSde l’objet 1Passwordiac_forgejo_smtp
smtp_from
Optionel. Chemin CLI vers la clé
SMTP_FROMde l’objet 1Passwordiac_forgejo_smtp
smtp_port
Optionel. Chemin CLI vers la clé
SMTP_PORTde l’objet 1Passwordiac_forgejo_smtp
smtp_protocol
Optionel. Chemin CLI vers la clé
SMTP_PROTOCOLde l’objet 1Passwordiac_forgejo_smtp
smtp_access_key
Optionel. Chemin CLI vers la clé
SMTP_ACCESS_KEYde l’objet 1Passwordiac_forgejo_smtp
smtp_secret_key
Optionel. Chemin CLI vers la clé
SMTP_SECRET_KEYde l’objet 1Passwordiac_forgejo_smtp
volumes_passphrase
Chemin CLI vers la clé
VOLUMES_PASSPHRASEde l’objet 1Passwordiac_csi_volumes_passphrase
onepassword_token
Chemin CLI vers la clé
OP_CONNET_TOKENde l’objet 1Passwordiac_op_connect
Caution
Les variables suivantes sont à éditer en connaissance et avec précaution !
kubernetes_config_path
Chemin local vers le fichier
kubeconfig.yaml
kubernetes_config_context
Contexte présent dans le fichier
kubeconfig.yaml(exemple:kubernetes-admin@graine)
lb_traefik_name
Nom du load balancer Traefik
onepassword_credentials_file_name
Nom du fichier JSON 1Password
private_network_name
Nom du réseau privée
Initialisation
Lorsque les précédentes étapes sont appliquées, lancez les commandes suivantes:
Sans la forge
task init
task apply
Avec la forge
Dans un premier temps:
task init
task apply:all
task init va:
- générer le fichier
terraform.tfvarstout en récupérer les valeurs des objets 1Password - télécharger les providers Tofu / Terraform
task apply va:
- installer toute la stack à l’exception de la forge et tout ce qui la concerne
task apply:base va déployer en plus:
- forgejo
- 2 runners act
- créer un compte ArgoCD et un compte de service permettant l’accès au registre
- ajouter la clé SSH publique ArgoCD à son compte
- créer un token associé au compte ArgoCD permettant le dispatch des actions