Ο κλασικός μονόλιθος ξεκινάει το ίδιο παντού. Πρώτη μέρα: ένα main.tf, ένα VPC, ένα RDS. Δεύτερος χρόνος: 4.000 resources σε ένα state, το terraform plan τρέχει εννιά λεπτά, και κάθε αλλαγή σε security group κλειδώνει το αρχείο για όλους.
Το ένστικτο λέει split. Σωστό ένστικτο. Ο τρόπος που οι περισσότερες ομάδες κάνουν split είναι λάθος.
Γιατί το «split ανά ομάδα» αποτυγχάνει
Η ενστικτώδης κατανομή ακολουθεί το οργανόγραμμα:
terraform/
backend-team/
frontend-team/
data-team/
platform-team/
Σπάνε τρία πράγματα, με αυτή τη σειρά:
- Τα κοινόχρηστα resources χρειάζονται ιδιοκτήτη. Ποιανού state έχει το VPC; Το shared S3 bucket; Το IAM role που χρησιμοποιεί το CI όλων; Οι διαμάχες ιδιοκτησίας μετατρέπονται σε PRs που μένουν μια εβδομάδα ανοιχτά.
- Τα cross-state references πολλαπλασιάζονται. Το RDS subnet group του backend χρειάζεται το VPC ID του platform, οπότε διαβάζει το platform state μέσω
data "terraform_remote_state". Τώρα το plan του backend σπάει κάθε φορά που αλλάζουν τα outputs του platform. - Τα reorgs σαπίζουν τη δομή. Το data team συγχωνεύεται με το platform. Η δομή φακέλων είναι πια απολίθωμα. Ή θα μετονομάσεις (και θα ξαναγράψεις κάθε remote-state αναφορά) ή θα ζεις με ένα ψέμα.
Το οργανόγραμμα αλλάζει κάθε χρόνο. Η υποδομή αλλάζει με άλλο ρυθμό. Μην τα δένεις.
Σπάσε ανά lifecycle
Ομαδοποίησε resources ανάλογα με πόσο συχνά αλλάζουν, όχι ποιος τα έχει. Μια ρεαλιστική default δομή για τα περισσότερα cloud accounts:
terraform/
# Αλλάζει σχεδόν ποτέ. Manual approval για plan.
bootstrap/ # το ίδιο το state bucket, IAM roots, org-level SCPs
# Αλλάζει ~ κάθε τρίμηνο. Με προσοχή.
network/ # VPCs, subnets, transit gateways, DNS zones
data/ # RDS, ElastiCache, S3 buckets με business δεδομένα
# Αλλάζει ~ εβδομαδιαία. Auto-apply on merge.
platform/ # EKS clusters, ECR repos, shared IAM roles
# Αλλάζει ~ καθημερινά. Auto-apply ανά app.
apps/
api/
worker/
web/
Γιατί δουλεύει:
- Το blast radius ταιριάζει στο ρίσκο. Ένα κακό
apps/apiapply δεν μπορεί να ρίξει κατά λάθος το production database — άλλο state, άλλη ζώνη. - Οι χρόνοι του plan μένουν λογικοί. Κανένα layer δεν κρατάει πάνω από μερικές εκατοντάδες resources.
- Τα επικίνδυνα layers κινούνται αργά εξεπίτηδες. Όταν το
data/αλλάζει μία φορά το τρίμηνο, κάθε αλλαγή παίρνει την προσοχή που της αξίζει. - Τα reorgs δεν πειράζουν. Η δομή του φακέλου περιγράφει το σύστημα, όχι την ομάδα.
Πώς μιλούν τα layers μεταξύ τους
Τα κάτω layers εκθέτουν outputs. Τα πάνω layers τα διαβάζουν ως data sources.
# network/outputs.tf
output "vpc_id" {
value = aws_vpc.main.id
}
output "private_subnet_ids" {
value = aws_subnet.private[*].id
}
# platform/main.tf
data "terraform_remote_state" "network" {
backend = "s3"
config = {
bucket = "acme-tf-state"
key = "network/terraform.tfstate"
region = "eu-south-2"
}
}
module "eks" {
source = "./modules/eks"
vpc_id = data.terraform_remote_state.network.outputs.vpc_id
subnet_ids = data.terraform_remote_state.network.outputs.private_subnet_ids
}
Το βέλος της εξάρτησης δείχνει μόνο προς τα κάτω — apps εξαρτώνται από platform, platform από network, network από bootstrap. Ποτέ ανάποδα. Αν σου περάσει η σκέψη να διαβάσεις apps state από το platform, έχεις βάλει κάτι σε λάθος layer.
Τι παίζει με τα workspaces;
Χρησιμοποίησε terraform workspace για environments (dev / staging / prod) μέσα σε ένα layer. Μη το χρησιμοποιείς ως υποκατάστατο για split layer — τα workspaces μοιράζονται κώδικα, providers και lock file. Το split του state και τα workspaces είναι ορθογώνια εργαλεία που λύνουν διαφορετικά προβλήματα.
Σημειώσεις στο tooling
- Το Terragrunt κερδίζει εδώ — DRY backend config μεταξύ layers, dependency graphs που σε προειδοποιούν πριν σβήσεις output που άλλο state καταναλώνει.
- Atlantis ή Spacelift κάνει scope το plan-on-PR μόνο στο φάκελο που άλλαξε, οπότε το CI μένει γρήγορο.
- Μη βάζεις ένα S3 bucket ανά state. Ένα bucket, πολλά keys. Bucket-ανά-state γίνεται εφιάλτης δικαιωμάτων.
Είσαι στη μέση ενός split, ή ξεκινάς από έναν 4.000-resource μονόλιθο; Έχουμε ξεμπλέξει αρκετά τέτοια — πες μας τι σε δυσκολεύει.