Skip to content

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

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

modules/network/
├── main.tf
├── variables.tf
├── outputs.tf
├── security_groups.tf
└── README.md

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)