Modele Terraform Enterprise: Spațiu de lucru, Sentinel și Team Scaling
Model pentru adoptarea Terraform în organizațiile mari: strategia spațiului de lucru pentru mediu/echipă, Sentinel pentru balustrade financiare și conformitate, modul registru privat și management secret cu Vault.
IaC la scară întreprindere: adevăratele provocări
Când Terraform trece de la o echipă de 3 oameni la o organizație cu 50 de echipe care gestionați sute de medii cloud, provocări apar ca articolele introductive nu menționează niciodată: cum să vă asigurați că nimeni nu poate crea o instanță de 50.000 USD/lună accidental? Cum să împiedici o echipă să suprascrie starea alteia? Cum asigura conformitatea cu politicile de securitate ale companiei fără a bloca productivitate? Cum să gestionezi secretele la nivel central?
În acest articol final al seriei, acoperim modelele de întreprindere pentru Terraform: HCP Terraform (fostă Terraform Cloud) ca platformă de guvernare, Santinelă ca limbaj de politică pentru barierele financiare și conformitate, e Seif HashiCorp pentru gestionarea centralizată a secretelor.
Ce vei învăța
- Strategia spațiului de lucru: plat, monorepo, pe echipă/mediu/strat
- Sentinel: limbajul politicii HashiCorp, testarea simulată, nivelurile de aplicare
- Garanții financiare: blocați cazurile costisitoare, alerte automate de buget
- Private Module Registry: versiuni, guvernare, RBAC pentru module
- Vault + Terraform: secrete dinamice, injectare secretă fără hardcoding
- Scalarea echipei: seturi de variabile, declanșatoare de rulare, grupuri de agenți
Strategia spațiului de lucru: organizarea infrastructurii la scară
Un spațiu de lucru Terraform Cloud/Enterprise corespunde unui fișier de stare izolat. Strategia de denumire și organizare a spațiilor de lucru este prima decizie afectează întregul ciclu de viață al infrastructurii întreprinderii. Există trei modele principalele, fiecare cu avantaje și dezavantaje distincte.
Model 1: După mediu (cel mai frecvent)
# Naming convention: {team}-{service}-{environment}
# Esempio per un team platform con servizi networking, compute, database:
platform-networking-dev
platform-networking-staging
platform-networking-prod
platform-compute-dev
platform-compute-staging
platform-compute-prod
platform-database-dev
platform-database-staging
platform-database-prod
# Pro: isolamento completo per ambiente
# Pro: policy diverse per prod vs non-prod (piu strict su prod)
# Con: se hai 20 team con 5 servizi ognuno = 300 workspace da gestire
# Con: aggiornare una variabile comune richiede toccare molti workspace
Model 2: Monorepo cu spații de lucru dinamice
# Struttura monorepo con HCP Terraform
terraform-infra/
├── modules/ # Moduli privati condivisi
├── stacks/ # "Stack" = unita di deployment
│ ├── networking/
│ │ ├── main.tf
│ │ └── variables.tf
│ ├── eks-cluster/
│ └── rds-aurora/
└── workspaces/ # Configurazione per ogni workspace
├── platform-networking-prod.tfvars
├── platform-networking-staging.tfvars
└── team-a-eks-prod.tfvars
# HCP Terraform workspace configuration (via Terraform provider)
resource "tfe_workspace" "networking_prod" {
name = "platform-networking-prod"
organization = "myorg"
# Trigger: applica automaticamente su push al branch main
# ma solo per i file nella directory stacks/networking
trigger_prefixes = ["stacks/networking/"]
working_directory = "stacks/networking"
# Auto-apply solo in non-prod
auto_apply = false # prod: sempre approvazione manuale
# Terraform version
terraform_version = "1.9.x"
tag_names = ["env:prod", "team:platform", "tier:networking"]
}
Seturi de variabile: Configurație partajată între spațiile de lucru
# Variable Sets = gruppo di variabili applicabili a piu workspace
# Evita di duplicare le stesse variabili in 50 workspace
# Esempio: Variable Set globale con configurazione AWS
resource "tfe_variable_set" "aws_prod" {
name = "AWS Production Credentials"
description = "Credenziali AWS per ambienti di produzione"
organization = "myorg"
global = false # Non globale: solo workspace con tag specifici
}
# Variabili nel set (environment variables per il runner)
resource "tfe_variable" "aws_role_arn" {
key = "AWS_ROLE_ARN"
value = "arn:aws:iam::123456789:role/TerraformProdRole"
category = "env"
variable_set_id = tfe_variable_set.aws_prod.id
sensitive = false
}
# Applica il variable set a workspace con tag "env:prod"
resource "tfe_workspace_variable_set" "prod_networking" {
variable_set_id = tfe_variable_set.aws_prod.id
workspace_id = tfe_workspace.networking_prod.id
}
Sentinel: Politica ca cod pentru guvernanța întreprinderii
Santinelă și cadrul de politică proprietar al HashiCorp, disponibil în nivelurile Plus și Enterprise ale HCP Terraform. Spre deosebire de OPA/Rego (open-source), Sentinel este conceput special pentru HashiCorp: are acces nativ la planul Terraform cu un model bogat de date și un sistem de aplicare pe trei niveluri.
Niveluri de aplicare
# Sentinel ha tre livelli di enforcement:
# 1. advisory: la policy fallisce ma il run procede (solo log/warning)
# Uso: notifiche soft, metriche, awareness
# 2. soft-mandatory: la policy fallisce e blocca l'apply,
# MA un utente con permessi puo fare override con giustificazione
# Uso: policy importanti che potrebbero avere eccezioni legittime
# 3. hard-mandatory: la policy fallisce e NESSUNO puo fare override
# Uso: compliance legale, sicurezza critica, guardrail finanziari
# Configurazione enforcement nel policy set (HCP Terraform):
resource "tfe_policy_set" "global_policies" {
name = "global-security-policies"
organization = "myorg"
global = true # Applica a tutti i workspace
policy_ids = [
tfe_sentinel_policy.no_public_s3.id,
tfe_sentinel_policy.cost_limits.id,
tfe_sentinel_policy.required_tags.id,
]
}
Politica Sentinel: Paravane financiare
# cost-control.sentinel
# Blocca hard se il costo stimato supera soglie per ambiente
import "tfplan/v2" as tfplan
import "decimal"
# Leggi il tag "env" dal workspace per determinare le soglie
env = tfplan.variables["environment"].value
# Soglie di costo mensile (USD) per ambiente
cost_limits = {
"dev": decimal.new(500),
"staging": decimal.new(2000),
"prod": decimal.new(50000),
}
# Tipi di istanza EC2 proibiti in non-prod
expensive_types = [
"m5.4xlarge", "m5.8xlarge", "m5.16xlarge", "m5.24xlarge",
"c5.9xlarge", "c5.18xlarge",
"r5.8xlarge", "r5.16xlarge", "r5.24xlarge",
"p3.2xlarge", "p3.8xlarge", "p4d.24xlarge",
]
# Regola 1: Blocca istanze costose in non-prod
deny_expensive_instances = rule {
env is "prod" or
all tfplan.resource_changes as _, rc {
rc.type is not "aws_instance" or
rc.change.after.instance_type not in expensive_types
}
}
# Regola 2: Verifica costo stimato se disponibile (richiede Infracost)
check_estimated_cost = rule {
# La policy puo accedere ai costi stimati tramite Terraform Cloud
# se Infracost e integrato nel workflow
true # Placeholder: implementare con Infracost webhook
}
# Main: combina le regole
main = rule {
deny_expensive_instances and
check_estimated_cost
}
Politica Sentinel: Etichete obligatorii
# required-tags.sentinel
# Garantisce che tutte le risorse taggabili abbiano i tag obbligatori
import "tfplan/v2" as tfplan
# Tag obbligatori per ogni risorsa
required_tags = ["Environment", "Team", "CostCenter", "ManagedBy"]
# Tipi di risorsa che supportano i tag (lista parziale)
taggable_types = [
"aws_instance", "aws_vpc", "aws_subnet", "aws_s3_bucket",
"aws_rds_instance", "aws_eks_cluster", "aws_lb",
"azurerm_virtual_machine", "azurerm_virtual_network",
"google_compute_instance", "google_storage_bucket",
]
# Controlla ogni risorsa che viene creata o modificata
violations = []
for tfplan.resource_changes as address, rc {
if rc.type in taggable_types and
rc.change.actions contains "create" or rc.change.actions contains "update" {
tags = rc.change.after.tags else {}
for required_tags as tag {
if tag not in tags or tags[tag] is "" {
append(violations, sprintf(
"Risorsa %s manca del tag obbligatorio: %s",
[address, tag]
))
}
}
}
}
# Stampa le violazioni per il feedback all'utente
print("Tag violations:", violations)
main = rule { length(violations) is 0 }
Politica de testare Sentinel
# Sentinel CLI per testing locale delle policy
# Installa Sentinel CLI
sentinel version
# Sentinel v0.26.x
# Struttura directory per testing:
policies/
├── cost-control.sentinel
├── required-tags.sentinel
└── test/
├── cost-control/
│ ├── pass/
│ │ └── mock-tfplan.json # Plan con istanze economiche
│ └── fail/
│ └── mock-tfplan.json # Plan con istanze costose
└── required-tags/
├── pass/
│ └── mock-tfplan.json # Tutte le risorse hanno i tag
└── fail/
└── mock-tfplan.json # Risorse senza tag
# Genera mock da un plan reale:
terraform plan -out=tfplan.bin
terraform show -json tfplan.bin > mock-tfplan.json
# Modifica il JSON per creare scenari pass/fail
# Esegui i test:
sentinel test cost-control.sentinel
# PASS - cost-control.sentinel (2 test)
# PASS - test/cost-control/pass/mock-tfplan.json
# PASS - test/cost-control/fail/mock-tfplan.json
sentinel apply cost-control.sentinel
# Execution trace...
# Policy result: true
Registrul modul privat
Într-o organizație de întreprindere, modulele Terraform sunt mecanismul principal pentru standardizează infrastructura: echipa Platformă publică module „calea de aur” care echipele de aplicații consumă. HCP Terraform oferă un registru privat cu versiunea documentație semantică, generată automat și RBAC.
# Struttura di un modulo pubblicabile nel registry privato
terraform-module-aws-vpc/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── README.md # Documentazione auto-esposta nel registry
├── examples/
│ ├── simple/
│ │ └── main.tf # Esempio minimo
│ └── full/
│ └── main.tf # Esempio completo
└── tests/
└── vpc_test.go # Test Terratest
# Pubblicazione via Git tags (il registry legge i tag SemVer):
git tag v1.2.0
git push origin v1.2.0
# HCP Terraform registry: importa automaticamente il modulo
# dal repository GitHub/GitLab quando trova un tag vX.Y.Z
# Uso del modulo privato da altri workspace:
module "vpc" {
source = "app.terraform.io/myorg/aws-vpc/aws"
version = "~> 1.2"
environment = var.environment
cidr_block = "10.0.0.0/16"
subnet_count = 3
}
HashiCorp Vault: Management secret pentru Terraform
Cea mai frecventă problemă în conductele de întreprindere Terraform este managementul secret: parolele bazei de date, cheile API, certificatele. Seif HashiCorp rezolvă asta cu secrete dinamice: În loc de acreditările statice, Vault generează acreditări temporare la cerere care expiră automat.
Secretele dinamice ale seifului pentru AWS
# Configurazione Vault per generare credenziali AWS temporanee
# Provider Vault in Terraform
provider "vault" {
address = "https://vault.myorg.internal:8200"
# Autenticazione via AppRole (in CI/CD) o AWS IAM auth (in EC2/EKS)
}
# Leggi credenziali AWS dinamiche da Vault
data "vault_aws_access_credentials" "terraform_runner" {
backend = "aws"
role = "terraform-role"
type = "iam_user" # oppure "assumed_role" per STS
}
# Usa le credenziali nel provider AWS
provider "aws" {
region = var.aws_region
access_key = data.vault_aws_access_credentials.terraform_runner.access_key
secret_key = data.vault_aws_access_credentials.terraform_runner.secret_key
token = data.vault_aws_access_credentials.terraform_runner.security_token
}
# Vault genera credenziali con TTL di 1 ora
# Dopo il terraform apply, le credenziali scadono automaticamente
# Nessuna credenziale permanente nelle pipeline
Seif pentru secretele aplicației
# Recuperare segreti da Vault per passarli alle risorse
# (es: password database RDS)
data "vault_kv_secret_v2" "db_password" {
mount = "secret"
name = "prod/database/rds-main"
}
# Usa il segreto nella risorsa RDS
resource "aws_db_instance" "main" {
identifier = "${local.name_prefix}-rds"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.r6g.xlarge"
# Password da Vault: non hardcoded, non in tfvars
password = data.vault_kv_secret_v2.db_password.data["password"]
username = "app_user"
db_name = "appdb"
# Output: il DB endpoint viene scritto su Vault dopo l'apply
# tramite un provisioner o una pipeline separata
}
# Scrivi l'endpoint del DB su Vault dopo la creazione
resource "vault_kv_secret_v2" "db_connection" {
mount = "secret"
name = "prod/database/connection-info"
data_json = jsonencode({
host = aws_db_instance.main.address
port = aws_db_instance.main.port
database = aws_db_instance.main.db_name
})
}
Rulați declanșatoare și graficul de dependență între spațiile de lucru
# In organizzazioni grandi, i workspace hanno dipendenze:
# networking -> compute -> application
# Il cambio di networking deve triggerare il re-apply di compute
# HCP Terraform: Run Triggers
resource "tfe_run_trigger" "compute_from_networking" {
workspace_id = tfe_workspace.compute_prod.id # workspace downstream
sourceable_id = tfe_workspace.networking_prod.id # workspace upstream
}
# Quando networking-prod completa un apply con successo,
# HCP Terraform triggera automaticamente un plan su compute-prod
# che legge gli output di networking via remote_state data source
# Lettura output da workspace upstream
data "tfe_outputs" "networking" {
organization = "myorg"
workspace = "platform-networking-prod"
}
# Usa gli output nel compute workspace
resource "aws_eks_cluster" "main" {
name = "${local.name_prefix}-eks"
vpc_config {
subnet_ids = data.tfe_outputs.networking.values.private_subnet_ids
}
}
Grupuri de agenți: alergător auto-găzduit în medii private
# HCP Terraform Agent: per eseguire piani in reti private
# (es: infrastruttura on-premise, VPC senza accesso pubblico)
# Installa l'agent nel tuo ambiente
docker run -e TFE_AGENT_TOKEN="your-token" \
-e TFE_AGENT_NAME="datacenter-agent-01" \
hashicorp/tfc-agent:latest
# Oppure via Kubernetes DaemonSet nel cluster privato
kubectl apply -f - <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: tfc-agent
namespace: terraform-system
spec:
replicas: 3
selector:
matchLabels:
app: tfc-agent
template:
spec:
containers:
- name: tfc-agent
image: hashicorp/tfc-agent:latest
env:
- name: TFE_AGENT_TOKEN
valueFrom:
secretKeyRef:
name: tfc-agent-token
key: token
- name: TFE_AGENT_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
EOF
# Configura il workspace per usare l'agent pool privato
resource "tfe_workspace" "private_datacenter" {
name = "datacenter-networking-prod"
organization = "myorg"
agent_pool_id = tfe_agent_pool.datacenter.id
execution_mode = "agent" # Usa l'agent invece del runner HCP
}
Echipa RBAC în HCP Terraform
# Organizzare i permessi per team
resource "tfe_team" "platform_engineers" {
name = "platform-engineers"
organization = "myorg"
visibility = "organization"
}
resource "tfe_team" "app_developers" {
name = "app-developers"
organization = "myorg"
}
# Platform Engineers: accesso completo a tutti i workspace di networking
resource "tfe_team_access" "platform_networking" {
access = "admin" # plan, apply, destroy, admin
team_id = tfe_team.platform_engineers.id
workspace_id = tfe_workspace.networking_prod.id
}
# App Developers: solo plan (read) su prod, write su dev
resource "tfe_team_access" "dev_compute_prod" {
access = "read" # Solo visualizzazione, nessun trigger
team_id = tfe_team.app_developers.id
workspace_id = tfe_workspace.compute_prod.id
}
resource "tfe_team_access" "dev_compute_dev" {
access = "write" # Plan e apply, ma non admin
team_id = tfe_team.app_developers.id
workspace_id = tfe_workspace.compute_dev.id
}
Concluzii: Maturitatea întreprinderii IaC
Terraform enterprise nu este doar „Terraform cu mai multe spații de lucru”: este un sistem de guvernarea infrastructurii cu mașina de politici (Sentinel), management secret (Seif), pistă de audit completă și RBAC granular. Modelele descrise în acest articol ele reprezintă maturitatea Infrastructurii ca Cod în organizațiile pe care le administrează zeci de echipe și sute de medii cloud.
Cu acest articol încheiem seria Terraform și IaC: de la HCL de bază până la model de întreprindere, acum aveți toate instrumentele pentru a construi și gestiona infrastructurile nori profesionali la orice scară.
Seria completă: Terraform și IaC
- Articolul 01 — Terraform de la zero: HCL, Provider și Plan-Apply-Destroy
- Articolul 02 — Proiectarea modulelor Terraform reutilizabile
- Articolul 03 — Stare Terraform: Backend la distanță cu S3/GCS
- Articolul 04 — Terraform în CI/CD: GitHub Actions și Atlantis
- Articolul 05 — Testare IaC: Terratest și Terraform Test
- Articolul 06 — Securitate IaC: Checkov, Trivy și OPA
- Articolul 07 — Terraform Multi-Cloud: AWS + Azure + GCP
- Articolul 08 — GitOps pentru Terraform: Controller Flux TF și Spacelift
- Articolul 09 - Terraform vs Pulumi vs OpenTofu
- Articolul 10 (acest) — Modele Terraform Enterprise: spațiu de lucru, Sentinel și scalarea echipei







