Modules Terraform - Réseau¶
Introduction¶
Les modules Terraform encapsulent des groupes de ressources réutilisables. Ce module réseau crée une stack complète : réseau, sous-réseau, routeur, security groups.
Prérequis¶
- Terraform Provider OpenStack
- Compréhension des réseaux Neutron
Points à apprendre¶
Architecture du module¶
graph TB
subgraph "Module: network"
Network["Network<br/>openstack_networking_network_v2<br/>Réseau privé"]
Subnet["Subnet<br/>openstack_networking_subnet_v2<br/>Sous-réseau avec DHCP"]
Router["Router<br/>openstack_networking_router_v2<br/>Routeur vers external"]
RouterIf["Router Interface<br/>openstack_networking_router_interface_v2<br/>Connexion subnet-router"]
SG["Security Groups<br/>openstack_networking_secgroup_v2<br/>Groupes de sécurité"]
end
External["External Network<br/>Réseau provider"]
Instances["Instances<br/>VMs utilisant ce réseau"]
Router -->|Gateway| External
RouterIf -->|Attach| Router
RouterIf -->|Attach| Subnet
Subnet -->|Part of| Network
Instances -->|Connect| Network
Instances -->|Apply| SG
Structure du module¶
Variables du module¶
# modules/network/variables.tf
variable "name" {
description = "Nom de base pour les ressources"
type = string
}
variable "environment" {
description = "Environnement (dev, staging, prod)"
type = string
default = "dev"
}
variable "cidr" {
description = "CIDR du sous-réseau"
type = string
default = "192.168.0.0/24"
}
variable "dns_nameservers" {
description = "Serveurs DNS"
type = list(string)
default = ["8.8.8.8", "8.8.4.4"]
}
variable "enable_dhcp" {
description = "Activer DHCP"
type = bool
default = true
}
variable "external_network_name" {
description = "Nom du réseau externe"
type = string
default = "external"
}
variable "create_router" {
description = "Créer un routeur vers l'extérieur"
type = bool
default = true
}
variable "security_group_rules" {
description = "Règles de security group"
type = list(object({
direction = string
protocol = string
port_range_min = number
port_range_max = number
remote_ip_prefix = string
}))
default = [
{
direction = "ingress"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "0.0.0.0/0"
},
{
direction = "ingress"
protocol = "icmp"
port_range_min = 0
port_range_max = 0
remote_ip_prefix = "0.0.0.0/0"
}
]
}
variable "tags" {
description = "Tags pour les ressources"
type = map(string)
default = {}
}
Ressources principales¶
# modules/network/main.tf
locals {
name_prefix = "${var.environment}-${var.name}"
common_tags = merge(var.tags, {
environment = var.environment
managed_by = "terraform"
module = "network"
})
}
# Réseau privé
resource "openstack_networking_network_v2" "this" {
name = "${local.name_prefix}-network"
admin_state_up = true
tags = [for k, v in local.common_tags : "${k}=${v}"]
}
# Sous-réseau
resource "openstack_networking_subnet_v2" "this" {
name = "${local.name_prefix}-subnet"
network_id = openstack_networking_network_v2.this.id
cidr = var.cidr
ip_version = 4
enable_dhcp = var.enable_dhcp
dns_nameservers = var.dns_nameservers
allocation_pool {
start = cidrhost(var.cidr, 10)
end = cidrhost(var.cidr, 250)
}
tags = [for k, v in local.common_tags : "${k}=${v}"]
}
# Data source pour le réseau externe
data "openstack_networking_network_v2" "external" {
count = var.create_router ? 1 : 0
name = var.external_network_name
}
# Routeur
resource "openstack_networking_router_v2" "this" {
count = var.create_router ? 1 : 0
name = "${local.name_prefix}-router"
external_network_id = data.openstack_networking_network_v2.external[0].id
admin_state_up = true
tags = [for k, v in local.common_tags : "${k}=${v}"]
}
# Interface routeur
resource "openstack_networking_router_interface_v2" "this" {
count = var.create_router ? 1 : 0
router_id = openstack_networking_router_v2.this[0].id
subnet_id = openstack_networking_subnet_v2.this.id
}
Security Groups¶
# modules/network/security_groups.tf
# Security group principal
resource "openstack_networking_secgroup_v2" "this" {
name = "${local.name_prefix}-sg"
description = "Security group for ${var.name} in ${var.environment}"
}
# Règles dynamiques
resource "openstack_networking_secgroup_rule_v2" "rules" {
count = length(var.security_group_rules)
security_group_id = openstack_networking_secgroup_v2.this.id
direction = var.security_group_rules[count.index].direction
ethertype = "IPv4"
protocol = var.security_group_rules[count.index].protocol
port_range_min = var.security_group_rules[count.index].port_range_min
port_range_max = var.security_group_rules[count.index].port_range_max
remote_ip_prefix = var.security_group_rules[count.index].remote_ip_prefix
}
# Règle pour autoriser tout le trafic sortant
resource "openstack_networking_secgroup_rule_v2" "egress" {
security_group_id = openstack_networking_secgroup_v2.this.id
direction = "egress"
ethertype = "IPv4"
remote_ip_prefix = "0.0.0.0/0"
}
# Security group pour base de données (optionnel)
resource "openstack_networking_secgroup_v2" "database" {
name = "${local.name_prefix}-db-sg"
description = "Security group for database servers"
}
resource "openstack_networking_secgroup_rule_v2" "database_mysql" {
security_group_id = openstack_networking_secgroup_v2.database.id
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 3306
port_range_max = 3306
# Autoriser uniquement depuis le security group principal
remote_group_id = openstack_networking_secgroup_v2.this.id
}
resource "openstack_networking_secgroup_rule_v2" "database_postgres" {
security_group_id = openstack_networking_secgroup_v2.database.id
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 5432
port_range_max = 5432
remote_group_id = openstack_networking_secgroup_v2.this.id
}
Outputs du module¶
# modules/network/outputs.tf
output "network_id" {
description = "ID du réseau créé"
value = openstack_networking_network_v2.this.id
}
output "network_name" {
description = "Nom du réseau créé"
value = openstack_networking_network_v2.this.name
}
output "subnet_id" {
description = "ID du sous-réseau"
value = openstack_networking_subnet_v2.this.id
}
output "subnet_cidr" {
description = "CIDR du sous-réseau"
value = openstack_networking_subnet_v2.this.cidr
}
output "router_id" {
description = "ID du routeur"
value = var.create_router ? openstack_networking_router_v2.this[0].id : null
}
output "security_group_id" {
description = "ID du security group principal"
value = openstack_networking_secgroup_v2.this.id
}
output "security_group_name" {
description = "Nom du security group principal"
value = openstack_networking_secgroup_v2.this.name
}
output "database_security_group_id" {
description = "ID du security group database"
value = openstack_networking_secgroup_v2.database.id
}
Utilisation du module¶
# environments/production/main.tf
module "app_network" {
source = "../../modules/network"
name = "webapp"
environment = "production"
cidr = "10.10.0.0/24"
dns_nameservers = ["10.0.0.5", "10.0.0.6"]
external_network_name = "external"
security_group_rules = [
{
direction = "ingress"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "10.0.0.0/8" # SSH depuis réseau interne uniquement
},
{
direction = "ingress"
protocol = "tcp"
port_range_min = 80
port_range_max = 80
remote_ip_prefix = "0.0.0.0/0"
},
{
direction = "ingress"
protocol = "tcp"
port_range_min = 443
port_range_max = 443
remote_ip_prefix = "0.0.0.0/0"
}
]
tags = {
project = "webapp"
cost_center = "IT-123"
}
}
# Utiliser les outputs
output "webapp_network_id" {
value = module.app_network.network_id
}
Diagramme réseau créé¶
graph TB
subgraph "External Network"
Internet["Internet<br/>0.0.0.0/0"]
end
subgraph "Project Network"
subgraph "Router"
RouterNode["production-webapp-router<br/>Gateway vers external"]
end
subgraph "Subnet 10.10.0.0/24"
DHCP["DHCP<br/>10.10.0.2"]
Gateway["Gateway<br/>10.10.0.1"]
VM1["webapp-1<br/>10.10.0.10<br/>SG: webapp-sg"]
VM2["webapp-2<br/>10.10.0.11<br/>SG: webapp-sg"]
DB["database<br/>10.10.0.20<br/>SG: webapp-db-sg"]
end
end
Internet -->|Floating IPs| RouterNode
RouterNode -->|Route| Gateway
VM1 -->|MySQL<br/>3306| DB
VM2 -->|MySQL<br/>3306| DB
Exemples pratiques¶
Multi-tier network¶
# Réseau web (frontend)
module "web_network" {
source = "../../modules/network"
name = "web"
environment = "production"
cidr = "10.10.1.0/24"
security_group_rules = [
{ direction = "ingress", protocol = "tcp", port_range_min = 80, port_range_max = 80, remote_ip_prefix = "0.0.0.0/0" },
{ direction = "ingress", protocol = "tcp", port_range_min = 443, port_range_max = 443, remote_ip_prefix = "0.0.0.0/0" },
]
}
# Réseau application (backend)
module "app_network" {
source = "../../modules/network"
name = "app"
environment = "production"
cidr = "10.10.2.0/24"
create_router = false # Pas d'accès direct internet
security_group_rules = [
{ direction = "ingress", protocol = "tcp", port_range_min = 8080, port_range_max = 8080, remote_ip_prefix = "10.10.1.0/24" },
]
}
# Réseau database
module "db_network" {
source = "../../modules/network"
name = "database"
environment = "production"
cidr = "10.10.3.0/24"
create_router = false
security_group_rules = [
{ direction = "ingress", protocol = "tcp", port_range_min = 5432, port_range_max = 5432, remote_ip_prefix = "10.10.2.0/24" },
]
}
Ressources¶
Checkpoint¶
- Module réseau créé et fonctionnel
- Variables paramétrables
- Security groups configurables dynamiquement
- Outputs exposés pour les autres modules
- Testé dans différents environnements
- Documentation du module (README.md)