Skip to content

Terraform

1. Blocchi di Controllo e Infrastruttura

Questi blocchi istruiscono il motore core di Terraform su come interfacciarsi con l'esterno, dove salvare i dati di stato e quali componenti reali o logici istanziare.

Costrutto Ambito Funzione
terraform {} Motore Configurazione globale di Terraform, vincoli di versione della CLI e dichiarazione dei provider richiesti.
backend Stato Configurazione (interna a terraform {}) per l'archiviazione remota e sicura del file .tfstate con supporto allo state locking.
provider {} API Inizializzazione dei plug-in e traduzione del codice HCL in chiamate API specifiche (gestione credenziali e regioni).
module {} Astrazione Invocazione di blocchi di codice riutilizzabili archiviati localmente o in repository remoti per evitare duplicazioni.
resource {} Infrastruttura Dichiarazione e configurazione dei singoli oggetti reali o logici da creare ed elaborare nel Cloud provider.
data {} Query Sorgente dati in sola lettura per interrogare le API Cloud e recuperare attributi di risorse preesistenti.

2. Blocchi di Flusso Dati (Variabili e Computazione)

Questi costrutti governano il passaggio e la manipolazione delle informazioni logiche all'interno del codice, rendendo l'infrastruttura dinamica e parametrizzabile.

Costrutto Ambito Funzione
variable Input Argomenti di ingresso per parametrizzare il codice dall'esterno (es. inseriti via CLI o file .tfvars).
locals Interno Espressioni logiche, costanti e computazioni locali non esportabili, usate per manipolare dati internamente.
output Output Valori esposti al termine dell'esecuzione o passati ad altri moduli (es. stringhe di connessione, indirizzi IP).

2. Comandi Principali della CLI di Terraform

Questi comandi consentono di gestire il ciclo di vita dell'infrastruttura, dall'inizializzazione della directory di lavoro fino alla distruzione delle risorse gestite.

Costrutto Ambito Funzione
terraform init Inizializzazione Scarica i provider specificati, inizializza il backend per lo stato e configura la directory di lavoro.
terraform validate Verifica Esegue un'analisi sintattica e strutturale dei file di configurazione per verificarne la correttozza formale.
terraform plan Pianificazione Genera e mostra il piano di esecuzione, confrontando lo stato reale con la configurazione desiderata senza applicare modifiche.
terraform apply Esecuzione Applica le modifiche pianificate sul target provider per raggiungere lo stato desiderato e aggiorna il file .tfstate.
terraform destroy Rimozione Elimina tutte le risorse gestite dalla configurazione corrente, distruggendo l'infrastruttura associata.
terraform state Gestione Stato Consente l'ispezione e la manipolazione avanzata del file .tfstate (es. rimozione o spostamento di risorse senza modificarle fisicamente).
terraform output Query Estrae e visualizza i valori delle variabili di output definiti nella configurazione corrente.
terraform fmt Formattazione Riformatta automaticamente i file di configurazione HCL secondo gli standard estetici nativi di Terraform.
---
### 3. Alberatura e Struttura dei File del Progetto

Di seguito viene illustrata l'organizzazione dei file all'interno del repository, basata sul principio di separazione degli ambienti e riutilizzo dei moduli.

Alberatura del Progetto: Multi-Ambiente con Modulo VPC

├── modules/
│   └── vpc/                           # Il codice statico viene convertito in modulo
│       ├── main.tf                    # Contiene le risorse: vpc, subnet, igw, route tables, sg
│       ├── variables.tf               # Definisce le variabili di input (cidr, ambiente, azs, ecc.)
│       └── outputs.tf                 # Esporta gli ID generati (vpc_id, subnet_ids)
└── environments/
    └── prod/                          # Ambiente di Produzione (Stato totalmente isolato)
        ├── main.tf                    # Inizializza il motore, il provider e invoca il modulo vpc
        └── terraform.tfvars           # File con i valori IP e tag specifici per la Produzione
        └── outputs.tf                 # Esporta gli ID generati (vpc_id, subnet_ids)

Esempi

modules/vpc/main.tf

resource "aws_vpc" "vpc_core" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  lifecycle {
    prevent_destroy = true
  }

  tags = {
    Name        = var.nome_progetto
    Environment = var.ambiente
  }
}

resource "aws_subnet" "subnet_pub_1a" {
  vpc_id            = aws_vpc.vpc_core.id
  cidr_block        = var.subnet_pub_1a_cidr
  availability_zone = "us-east-1a"

  lifecycle {
    prevent_destroy = true
  }

  tags = {
    Name        = "${var.nome_progetto}-subnet-pub-1a"
    Environment = var.ambiente
  }
}

resource "aws_subnet" "subnet_priv_1a" {
  vpc_id            = aws_vpc.vpc_core.id
  cidr_block        = var.subnet_priv_1a_cidr
  availability_zone = "us-east-1a"

  lifecycle {
    prevent_destroy = true
  }

  tags = {
    Name        = "${var.nome_progetto}-subnet-priv-1a"
    Environment = var.ambiente
  }
}

resource "aws_subnet" "subnet_priv_1b" {
  vpc_id            = aws_vpc.vpc_core.id
  cidr_block        = var.subnet_priv_1b_cidr
  availability_zone = "us-east-1b"

  lifecycle {
    prevent_destroy = true
  }

  tags = {
    Name        = "${var.nome_progetto}-subnet-priv-1b"
    Environment = var.ambiente
  }
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc_core.id

  lifecycle {
    prevent_destroy = true
  }

  tags = {
    Name        = "${var.nome_progetto}-igw"
    Environment = var.ambiente
  }
}

resource "aws_default_route_table" "default_rt" {
  default_route_table_id = aws_vpc.vpc_core.default_route_table_id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.igw.id
  }

  tags = {
    Name        = "${var.nome_progetto}-main-rt"
    Environment = var.ambiente
  }
}

resource "aws_route_table" "private_rt" {
  vpc_id = aws_vpc.vpc_core.id

  tags = {
    Name        = "${var.nome_progetto}-private-rt"
    Environment = var.ambiente
  }
}

resource "aws_route_table_association" "priv_1a_association" {
  subnet_id      = aws_subnet.subnet_priv_1a.id
  route_table_id = aws_route_table.private_rt.id
}

resource "aws_route_table_association" "priv_1b_association" {
  subnet_id      = aws_subnet.subnet_priv_1b.id
  route_table_id = aws_route_table.private_rt.id
}

resource "aws_default_security_group" "default_sg" {
  vpc_id = aws_vpc.vpc_core.id

  ingress {
    protocol    = "tcp"
    from_port   = 22
    to_port     = 22
    cidr_blocks = [var.vpc_cidr]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name        = "${var.nome_progetto}-default-sg"
    Environment = var.ambiente
  }
}

modules/vpc/variables.tf

variable "nome_progetto" {
  type        = string
  description = "Prefisso utilizzato per il naming delle risorse"
}

variable "ambiente" {
  type        = string
  description = "Identificativo dell'ambiente operativo (es. staging, prod)"
}

variable "vpc_cidr" {
  type        = string
  description = "Blocco CIDR principale per la VPC"
}

variable "subnet_pub_1a_cidr" {
  type        = string
  description = "Blocco CIDR per la subnet pubblica 1a"
}

variable "subnet_priv_1a_cidr" {
  type        = string
  description = "Blocco CIDR per la subnet privata 1a"
}

variable "subnet_priv_1b_cidr" {
  type        = string
  description = "Blocco CIDR per la subnet privata 1b"
}

modules/vpc/outputs.tf

output "vpc_id" {
  value       = aws_vpc.vpc_core.id
  description = "ID della VPC creata"
}

output "public_subnet_id" {
  value       = aws_subnet.subnet_pub_1a.id
  description = "ID della subnet pubblica 1a"
}

output "private_subnet_ids" {
  value       = [aws_subnet.subnet_priv_1a.id, aws_subnet.subnet_priv_1b.id]
  description = "Lista degli ID delle subnet private"
}

environments/staging/main.tf

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "http" {
    lock_method   = "POST"
    unlock_method = "DELETE"
  }
}

provider "aws" {
  region = "us-east-1"
}

variable "nome_progetto" {}
variable "ambiente" {}
variable "vpc_cidr" {}
variable "subnet_pub_1a_cidr" {}
variable "subnet_priv_1a_cidr" {}
variable "subnet_priv_1b_cidr" {}

module "vpc" {
  source              = "../../modules/vpc"
  nome_progetto       = var.nome_progetto
  ambiente            = var.ambiente
  vpc_cidr            = var.vpc_cidr
  subnet_pub_1a_cidr  = var.subnet_pub_1a_cidr
  subnet_priv_1a_cidr = var.subnet_priv_1a_cidr
  subnet_priv_1b_cidr = var.subnet_priv_1b_cidr
}

environments/staging/terraform.tfvars

nome_progetto       = "test-staging"
ambiente            = "staging"
vpc_cidr            = "172.16.100.0/23"
subnet_pub_1a_cidr  = "172.16.100.0/24"
subnet_priv_1a_cidr = "172.16.101.0/25"
subnet_priv_1b_cidr = "172.16.101.128/25"

environments/staging/output.tf

output "staging_vpc_id" {
  value       = module.vpc.vpc_id
  description = "ID della VPC estratto dal modulo per l'ambiente di Staging"
}

output "staging_private_subnet_ids" {
  value       = module.vpc.private_subnet_ids
  description = "Lista ID subnet private per lo Staging"
}

T init

terraform init \
  -backend-config="address=https://gitlab.com/api/v4/projects/000000/terraform/state/staging" \
  -backend-config="username=${TF_HTTP_USERNAME}" \
  -backend-config="password=${TF_HTTP_PASSWORD}"