xpeditis2.0/infra/prod/terraform/servers.tf
2026-09-07 21:40:50 +02:00

117 lines
3.5 KiB
HCL

# =============================================================================
# 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
}
}