# ============================================================================= # Serveurs # ============================================================================= # Topologie retenue (2 VMs, cf. docs/mise-en-prod/00 et Excel previsions couts) : # # app-01 CPX41 8 vCPU / 16 Go k3s server + tous les pods (stateless) # db-01 CPX31 4 vCPU / 8 Go PostgreSQL 15 + Redis 7 (stateful, Docker) # # Pourquoi la base HORS de Kubernetes : PostgreSQL en StatefulSet apporte de la # complexite (PV, ordre de demarrage, upgrades) sans aucun gain a cette echelle. # Le hors-cluster rend les sauvegardes, la PITR et les restaurations triviales, # et permet de reconstruire integralement le noeud app sans toucher aux donnees. resource "hcloud_server" "app" { name = "${var.project_name}-app-01" server_type = var.app_server_type image = var.image location = var.location ssh_keys = [hcloud_ssh_key.admin.id] # Deux firewalls : le permanent, et celui que la CI ouvre puis referme. firewall_ids = [hcloud_firewall.app.id, hcloud_firewall.cicd.id] placement_group_id = hcloud_placement_group.spread.id backups = var.enable_hetzner_backups public_net { ipv4_enabled = true ipv6_enabled = true } network { network_id = hcloud_network.main.id ip = var.app_private_ip } user_data = templatefile("${path.module}/cloud-init.yaml.tftpl", { hostname = "${var.project_name}-app-01" deploy_user = var.deploy_user ssh_public_key = var.ssh_public_key }) labels = { project = var.project_name role = "app" managed = "terraform" } depends_on = [hcloud_network_subnet.main] lifecycle { # Un changement d'image ou de user_data recreerait le serveur : on veut une # decision explicite, pas une destruction silencieuse de la prod. ignore_changes = [image, user_data] } } resource "hcloud_server" "db" { name = "${var.project_name}-db-01" server_type = var.db_server_type image = var.image location = var.location ssh_keys = [hcloud_ssh_key.admin.id] firewall_ids = [hcloud_firewall.db.id] placement_group_id = hcloud_placement_group.spread.id backups = var.enable_hetzner_backups public_net { ipv4_enabled = true ipv6_enabled = true } network { network_id = hcloud_network.main.id ip = var.db_private_ip } user_data = templatefile("${path.module}/cloud-init.yaml.tftpl", { hostname = "${var.project_name}-db-01" deploy_user = var.deploy_user ssh_public_key = var.ssh_public_key }) labels = { project = var.project_name role = "data" managed = "terraform" } depends_on = [hcloud_network_subnet.main] lifecycle { ignore_changes = [image, user_data] } } # --- Volume de donnees PostgreSQL ------------------------------------------- # Volume dedie plutot que le disque systeme : agrandissable a chaud, snapshotable # independamment, et survit a une reinstallation complete du serveur. resource "hcloud_volume" "pgdata" { name = "${var.project_name}-pgdata" size = var.db_volume_size server_id = hcloud_server.db.id automount = false format = "ext4" labels = { project = var.project_name role = "pgdata" managed = "terraform" } lifecycle { # Garde-fou : un `terraform destroy` ne doit jamais emporter les donnees. prevent_destroy = true } }