Sıfırdan Terraform: HCL, Sağlayıcı ve Planla-Uygula-Yok Et Döngüsü
2026 yılında Kod Olarak Altyapı pazarı öyle bir olgunluğa ulaştı ki Terraform'u göz ardı etmek, İşlemleri bilmeden SQL yazmak: teknik olarak mümkün, ancak profesyonel olarak riskli. HashiCorp'un Terraform'u bugün %32,8 pazar payı IaC araçları arasında Registry.terraform.io'da 4 milyon aylık sağlayıcı kurulumu. Bu kılavuz sizi sıfırdan ele alıyor Planla-Uygula-Yok Et döngüsünün sağlam bir şekilde anlaşılmasıyla AWS ve Azure üzerinde çalışan bir kuruluma geçiş Bu da üretimde maliyetli hataları önleyecektir.
IaC'ye yaklaşan geliştiricilerden en sık duyduğum soru şu: “Çünkü sadece kullanmıyorum bash betikleri mi yoksa AWS konsolu mu?”. Bunun cevabı kavramın içindedir. bildirimsel altyapı: Terraform'a söylemiyorsun gibi kaynakları yaratın diyorsunuz hangi eyalet ulaşmak istiyorsun. Terraform Operasyonların sırasını anlamak, kaynaklar arasındaki bağımlılıkları yönetmek ve bağımsızlığı sağlamakla ilgilenir.
Ne Öğreneceksiniz
- Terraform'u yükleyin ve tfenv'i birden fazla sürümü yönetecek şekilde yapılandırın
- HCL sözdizimi: bloklar, nitelikler, ifadeler ve yerleşik işlevler
- AWS sağlayıcısını ve Azure sağlayıcısını güvenli kimlik doğrulamayla yapılandırma
- Tam yaşam döngüsü:
terraform init,plan,apply,destroy - Durum dosyasını anlamak: nedir, nerede bulunur, neden hiçbir zaman manuel olarak değiştirilmemelidir?
- Bir Terraform projesini başından itibaren ölçeklenebilir bir şekilde yapılandırın
- Değişkenler, yereller ve çıktı: konfigürasyonu profesyonel bir şekilde düzenleyin
Önkoşullar ve Kurulum
HCL'nin ilk satırını yazmadan önce ortamı profesyonelce ayarlayalım. Yeni başlayanların en yaygın hatası Terraform'u global olarak bir paket yöneticisiyle kurmaktır ve sonra kendinizi belirli bir sürüme takılıp kalmış halde buluyorsunuz. Doğru çözüm tfenv, Terraform'un sürüm yöneticisi (Node.js için nvm'ye eşdeğer).
# Installa tfenv (macOS/Linux)
git clone https://github.com/tfutils/tfenv.git ~/.tfenv
echo 'export PATH="$HOME/.tfenv/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Installa l'ultima versione stabile di Terraform
tfenv install latest
tfenv use latest
# Verifica installazione
terraform version
# Output: Terraform v1.9.x on linux_amd64
# Installa una versione specifica se il progetto la richiede
tfenv install 1.8.5
tfenv use 1.8.5
# Lista versioni installate
tfenv list
Windows için 2026'da ve WSL2'de Ubuntu veya Chocolatey ile önerilen yaklaşım:
# Windows con Chocolatey
choco install terraform
# Oppure scarica il binario da releases.hashicorp.com
# e aggiungilo al PATH manualmente
Ayrıca VS Code eklentisini de yükleyin HashiCorp Terraformu (kimlik: hashicorp.terraform):
sağlayıcılar için sözdizimi vurgulama, otomatik tamamlama, tanıma gitme ve entegrasyon sunar
ile terraform fmt. HCL için mevcut en sağlam IDE deneyimidir.
HCL: HashiCorp Yapılandırma Dili
HCL (HashiCorp Yapılandırma Dili), özel olarak tasarlanmış bir bildirim dilidir
Altyapıların yapılandırılması için. Genel amaçlı bir programlama dili değildir:
zorunluluk döngüsü yoktur (kullanın for_each e count), hiçbir istisnası yoktur,
Asenkron G/Ç'si yoktur. Bu bir özellikler, sınır değil: basitlik,
konfigürasyonların tesadüfi karmaşıklığı.
Her Terraform projesinin temel dosyası e main.tf. Ortak kongre
ve yapılandırmayı şu dosyalara ayırın:
progetto-terraform/
├── main.tf # Risorse principali
├── variables.tf # Dichiarazione variabili
├── outputs.tf # Output values
├── versions.tf # Required providers e terraform block
├── locals.tf # Valori locali computati
└── terraform.tfvars # Valori delle variabili (non committare se contiene segreti)
Temel blok türleriyle birlikte HCL'nin temel yapısı şöyledir:
# versions.tf — blocco terraform: configura il comportamento del core
terraform {
required_version = ">= 1.8.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.100"
}
}
}
# variables.tf — dichiarazione variabili di input
variable "environment" {
description = "Nome dell'ambiente (dev, staging, prod)"
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "L'ambiente deve essere dev, staging o prod."
}
}
variable "aws_region" {
description = "AWS Region dove deployare le risorse"
type = string
default = "eu-west-1"
}
variable "instance_count" {
description = "Numero di istanze EC2 da creare"
type = number
default = 2
}
variable "tags" {
description = "Tag comuni da applicare a tutte le risorse"
type = map(string)
default = {
ManagedBy = "Terraform"
Project = "demo"
}
}
# locals.tf — valori computati a partire da variabili
locals {
# Naming convention uniforme
name_prefix = "${var.environment}-${var.tags["Project"]}"
# Merge tag comuni con tag specifici per risorsa
common_tags = merge(var.tags, {
Environment = var.environment
CreatedAt = timestamp()
})
}
AWS Sağlayıcısını Yapılandırma
I sağlayıcı Terraform'un harici API'lerle etkileşime girmesine izin veren eklentilerdir: AWS, Azure, GCP, Kubernetes, GitHub, Datadog — neredeyse her hizmetin bir Terraform sağlayıcısı vardır. AWS sağlayıcısı, desteklenen 1.200'den fazla kaynak türüyle en olgun sağlayıcıdır.
AWS kimlik doğrulaması için, HCL kodunda hiçbir zaman sabit kodlu erişim anahtarını kullanmayın. AWS sağlayıcısı öncelik sırasına göre aşağıdaki modları destekler:
# main.tf — configurazione provider AWS
provider "aws" {
region = var.aws_region
# NON fare questo in produzione:
# access_key = "AKIA..." # MAI
# secret_key = "..." # MAI
# Metodo consigliato 1: assume role (best practice per CI/CD)
# assume_role {
# role_arn = "arn:aws:iam::123456789:role/TerraformRole"
# }
# I tag di default vengono applicati a tutte le risorse
default_tags {
tags = local.common_tags
}
}
# Configurazione autenticazione (fuori da main.tf)
# La best practice e usare il file ~/.aws/credentials oppure
# variabili di ambiente:
# export AWS_ACCESS_KEY_ID="..."
# export AWS_SECRET_ACCESS_KEY="..."
# export AWS_DEFAULT_REGION="eu-west-1"
#
# In produzione: IAM Instance Profile o OIDC con GitHub Actions
Şimdi ilk AWS kaynaklarını oluşturalım: genel ve özel alt ağlara sahip bir VPC:
# main.tf — prime risorse AWS
# Data source: recupera gli AZ disponibili nella region
data "aws_availability_zones" "available" {
state = "available"
}
# VPC principale
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${local.name_prefix}-vpc"
}
}
# Subnet pubblica (una per AZ)
resource "aws_subnet" "public" {
count = min(length(data.aws_availability_zones.available.names), 2)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${local.name_prefix}-public-${count.index + 1}"
Tier = "Public"
}
}
# Subnet privata
resource "aws_subnet" "private" {
count = min(length(data.aws_availability_zones.available.names), 2)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 10)
availability_zone = data.aws_availability_zones.available.names[count.index]
tags = {
Name = "${local.name_prefix}-private-${count.index + 1}"
Tier = "Private"
}
}
# Internet Gateway per le subnet pubbliche
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${local.name_prefix}-igw"
}
}
# Route table pubblica
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = {
Name = "${local.name_prefix}-rt-public"
}
}
# Associazione route table - subnet pubblica
resource "aws_route_table_association" "public" {
count = length(aws_subnet.public)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
# outputs.tf — valori di output
output "vpc_id" {
description = "ID della VPC creata"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "IDs delle subnet pubbliche"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "IDs delle subnet private"
value = aws_subnet.private[*].id
}
Planla-Uygula-Yok Et Döngüsü
Terraform yaşam döngüsü dört temel komuttan oluşur. Bunları iyice anlayın Üretimde en yaygın kazalardan kaçınmak önemlidir.
Terraform başlangıcı
# Inizializza il working directory:
# - Scarica i provider (plugin binaries)
# - Configura il backend per lo state
# - Installa i moduli referenziati
terraform init
# Output atteso:
# Initializing the backend...
# Initializing provider plugins...
# - Finding hashicorp/aws versions matching "~> 5.0"...
# - Installing hashicorp/aws v5.54.1...
# Terraform has been successfully initialized!
# Upgrade dei provider all'ultima versione compatibile
terraform init -upgrade
# Ricrea il .terraform.lock.hcl (file di lock dei provider)
terraform providers lock -platform=linux_amd64 -platform=darwin_amd64
.terraform.lock.hcl dosyası
Dosya .terraform.lock.hcl depoya kaydedilmelidir.
Tüm ekip üyelerinin ve CI hattının tam olarak aynısını kullanmasını sağlar
sağlayıcı sürümü, altyapı için "makinemde çalışıyor" seçeneğinden kaçınıyor.
Dizin .terraform/ bunun yerine şuraya gider: .gitignore.
dünya planı
# Genera il piano di esecuzione (DRY RUN)
terraform plan
# Salva il piano in un file binario (consigliato per CI/CD)
terraform plan -out=tfplan
# Specifica le variabili inline
terraform plan -var="environment=staging" -var="instance_count=3"
# Usa un file di variabili
terraform plan -var-file="staging.tfvars"
# Output tipico di plan:
# Terraform will perform the following actions:
#
# # aws_vpc.main will be created
# + resource "aws_vpc" "main" {
# + arn = (known after apply)
# + cidr_block = "10.0.0.0/16"
# + enable_dns_hostnames = true
# ...
# }
#
# Plan: 8 to add, 0 to change, 0 to destroy.
Sembol + yaratılışı gösterir, ~ yerinde düzenleme,
-/+ yok et ve yeniden yarat (kesinti süresini zorla), - yıkım.
İşaretli blokları her zaman dikkatlice okuyun -/+:
kaynağın yeniden oluşturulması gerektiği anlamına gelir ve bu da genellikle kesinti veya veri kaybına neden olur.
Terraform uygulaması
# Applica le modifiche (chiede conferma interattiva)
terraform apply
# Applica il piano salvato (NON chiede conferma - usare in CI/CD)
terraform apply tfplan
# Auto-approve per ambienti non critici (attento in prod!)
terraform apply -auto-approve
# Apply con variabili
terraform apply -var="environment=prod" -var-file="prod.tfvars"
# Output dopo apply:
# Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
#
# Outputs:
# vpc_id = "vpc-0123456789abcdef0"
# public_subnet_ids = [
# "subnet-0abc123def456gh78",
# "subnet-0def456abc789ij01",
# ]
Terraform'u yok etmek
# Distrugge TUTTE le risorse gestite dallo state corrente
terraform destroy
# Destroy con auto-approve (ATTENZIONE: irreversibile)
terraform destroy -auto-approve
# Distrugge solo una risorsa specifica (con grande cautela)
terraform destroy -target=aws_subnet.public[0]
# In produzione, preferisci eliminare le risorse dal codice
# e fare terraform apply: Terraform le distruggerà correttamente
Anti-Desen: Üretimde dünya biçimini yok etme
Asla koşma terraform destroy bir kurtarma planı olmadan.
En iyi uygulama, kaynağı HCL kodundan kaldırmak ve çalıştırmaktır. terraform apply:
aynı sonucu elde edersiniz, ancak önce inceleyebileceğiniz açık bir planla.
Bazı kuruluşlar yok etme işlemini IAM politikası düzeyinde yürütme yeteneğini engeller
üretim ortamları hakkında.
Azure Sağlayıcısını Yapılandırma
sağlayıcı azurerm Azure kaynaklarını yönetir. AWS'den farklı olarak, Azure, kimlik doğrulama için Hizmet Sorumlusunu veya Yönetilen Kimlik'i kullanır.
# versions.tf aggiornato con provider Azure
terraform {
required_version = ">= 1.8.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.100"
}
}
}
# Configurazione provider Azure
provider "azurerm" {
features {
resource_group {
prevent_deletion_if_contains_resources = true
}
key_vault {
purge_soft_delete_on_destroy = false
recover_soft_deleted_key_vaults = true
}
}
# Autenticazione via variabili d'ambiente (consigliato)
# ARM_CLIENT_ID, ARM_CLIENT_SECRET, ARM_TENANT_ID, ARM_SUBSCRIPTION_ID
# oppure Azure CLI: az login
}
# Risorse Azure di base
resource "azurerm_resource_group" "main" {
name = "${local.name_prefix}-rg"
location = "West Europe"
tags = local.common_tags
}
resource "azurerm_virtual_network" "main" {
name = "${local.name_prefix}-vnet"
address_space = ["10.1.0.0/16"]
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tags = local.common_tags
}
resource "azurerm_subnet" "public" {
name = "public-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.1.1.0/24"]
}
resource "azurerm_subnet" "private" {
name = "private-subnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = ["10.1.2.0/24"]
}
Değişkenler, Yereller ve Veri Kaynakları
Değişkenlerin, yerellerin ve veri kaynaklarının iyi kullanımı Terraform konfigürasyonunu diğerlerinden ayırır özel bir senaryodan profesyonel. İşte temel kalıplar:
# Tipi di variabili in HCL
# Stringa semplice
variable "app_name" {
type = string
default = "myapp"
}
# Numero con validazione
variable "min_instances" {
type = number
default = 1
validation {
condition = var.min_instances >= 1 && var.min_instances <= 10
error_message = "Il numero di istanze deve essere tra 1 e 10."
}
}
# Lista di stringhe
variable "allowed_cidr_blocks" {
type = list(string)
default = ["10.0.0.0/8"]
}
# Map di stringhe
variable "database_config" {
type = map(string)
default = {
engine = "postgres"
version = "15.4"
size = "db.t3.medium"
}
}
# Oggetto con schema tipizzato
variable "network_config" {
type = object({
vpc_cidr = string
subnet_count = number
enable_nat = bool
})
default = {
vpc_cidr = "10.0.0.0/16"
subnet_count = 2
enable_nat = false
}
}
# Locals: valori computati (non input dall'utente)
locals {
# Concatenazioni
full_name = "${var.environment}-${var.app_name}"
# Condizionale ternario
instance_type = var.environment == "prod" ? "t3.medium" : "t3.micro"
# Ciclo su lista (for expression)
subnet_cidrs = [
for i in range(var.network_config.subnet_count) :
cidrsubnet(var.network_config.vpc_cidr, 8, i)
]
# Map transformation
tag_map = {
for k, v in var.database_config :
"db_${k}" => v
}
}
# Data sources: recuperano informazioni da risorse esistenti
# non gestite da questo state
# AMI Amazon Linux 2023 piu recente
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# Account ID corrente (utile per ARN)
data "aws_caller_identity" "current" {}
# Uso nei resource:
# ami = data.aws_ami.amazon_linux.id
# account_id = data.aws_caller_identity.current.account_id
Durum Dosyası: Terraform'un Kalbi
Dosya terraform.tfstate Terraform'un "gerçeğin kaynağıdır": her varlığın haritasını çıkarın
HCL'de buluttaki gerçek dünyadaki karşılığı olarak tanımlanır. Nasıl çalıştığını anlamak önemlidir
en ciddi sorunlardan kaçının.
// Struttura semplificata di terraform.tfstate
{
"version": 4,
"terraform_version": "1.9.0",
"serial": 42,
"lineage": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"outputs": {
"vpc_id": {
"value": "vpc-0123456789abcdef0",
"type": "string"
}
},
"resources": [
{
"mode": "managed",
"type": "aws_vpc",
"name": "main",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 1,
"attributes": {
"id": "vpc-0123456789abcdef0",
"cidr_block": "10.0.0.0/16",
"enable_dns_hostnames": true,
...
}
}
]
}
]
}
Devlet Dosyası İçin Altın Kurallar
- Asla düzenleme
terraform.tfstatemanuel olarak - Asla taahhütte bulunma Git deponuzda belirtin (bunu ekleyin
.gitignore) - Ekiplerde şunu kullanın: her zaman uzak bir arka uç kilitlemeli (bkz. serinin 03. Maddesi)
- Devlet bunu kapsayabilir sırlar açıkta (RDS şifresi, kimlik bilgileri): Bunu hassas veriler olarak ele alın
- Riskli operasyonlardan önce, manuel yedekleme gerçekleştirin:
terraform state pull > backup.tfstate
Devlet Denetleme Komutları
# Lista tutte le risorse gestite dallo state
terraform state list
# Mostra i dettagli di una risorsa specifica
terraform state show aws_vpc.main
# Rinomina una risorsa nello state (senza toccare l'infrastruttura)
terraform state mv aws_subnet.public aws_subnet.public_new
# Rimuove una risorsa dallo state (Terraform non la gestirà piu)
# La risorsa rimane nel cloud ma non è piu "owned" da Terraform
terraform state rm aws_subnet.private[0]
# Importa una risorsa esistente nello state
# (vedi articolo 03 per dettagli)
terraform import aws_vpc.main vpc-0123456789abcdef0
# Mostra l'output senza fare apply
terraform output vpc_id
terraform output -json # tutti gli output in formato JSON
Önerilen Proje Yapısı
Gerçek projelerde tek dizin yapısı hızla yönetilemez hale gelir. Üretimde Terraform altyapısını organize etmek için iki yaygın model aşağıda verilmiştir:
# Pattern 1: Organizzazione per ambiente
infra/
├── modules/ # Moduli riusabili
│ ├── networking/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── compute/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
├── environments/
│ ├── dev/
│ │ ├── main.tf # Usa i moduli
│ │ ├── variables.tf
│ │ ├── terraform.tfvars # Valori specifici per dev
│ │ └── versions.tf
│ ├── staging/
│ │ └── ...
│ └── prod/
│ └── ...
└── .gitignore # Esclude .terraform/, *.tfstate
# Pattern 2: Terragrunt (wrapper per DRY)
infra/
├── terragrunt.hcl # Config globale
├── modules/
│ └── networking/
├── live/
│ ├── dev/
│ │ └── networking/
│ │ └── terragrunt.hcl
│ └── prod/
│ └── networking/
│ └── terragrunt.hcl
Başlamak için En İyi Uygulamalar
Teoriyi gördükten sonra Terraform kullananları ayıran temel kuralları burada bulabilirsiniz. İlk günden itibaren teknik borç yaratanlar tarafından doğru bir şekilde:
# 1. Formatta sempre prima di committare
terraform fmt -recursive
# 2. Valida la sintassi
terraform validate
# 3. Usa tflint per linting avanzato (trova deprecazioni, pattern errati)
tflint --init
tflint
# 4. Esegui checkov per security scanning
pip install checkov
checkov -d .
# 5. Pre-commit hooks per automatizzare tutto
# .pre-commit-config.yaml
# repos:
# - repo: https://github.com/antonbabenko/pre-commit-terraform
# hooks:
# - id: terraform_fmt
# - id: terraform_validate
# - id: terraform_tflint
# - id: terraform_checkov
Terraform için .gitignore
# .gitignore per progetti Terraform
.terraform/
*.tfstate
*.tfstate.backup
*.tfstate.*.backup
.terraform.tfstate.lock.info
*.tfvars # Se contengono segreti (crea terraform.tfvars.example)
override.tf
override.tf.json
*_override.tf
*_override.tf.json
crash.log
.terraformrc
terraform.rc
Tam Örnek: AWS'de Web Uygulaması
Hepsini gerçek bir örnekte bir araya getirelim: Güvenlik grubuna sahip bir EC2 bulut sunucusu, yük dengeleyici ve RDS veritabanı, doğru yapılandırılmış.
# main.tf — infrastruttura web app completa
# Security Group per le istanze web
resource "aws_security_group" "web" {
name = "${local.name_prefix}-sg-web"
description = "Security group per istanze web"
vpc_id = aws_vpc.main.id
ingress {
description = "HTTP dal load balancer"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [aws_security_group.alb.id]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "${local.name_prefix}-sg-web" }
}
# Security Group per ALB
resource "aws_security_group" "alb" {
name = "${local.name_prefix}-sg-alb"
description = "Security group per Application Load Balancer"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Launch Template per le istanze EC2
resource "aws_launch_template" "web" {
name_prefix = "${local.name_prefix}-lt-"
image_id = data.aws_ami.amazon_linux.id
instance_type = local.instance_type
network_interfaces {
associate_public_ip_address = false
security_groups = [aws_security_group.web.id]
}
user_data = base64encode(<<-EOF
#!/bin/bash
dnf update -y
dnf install -y nginx
systemctl enable nginx
systemctl start nginx
echo "Deploy Terraform - ${var.environment}
" > /usr/share/nginx/html/index.html
EOF
)
tag_specifications {
resource_type = "instance"
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web"
})
}
}
# Auto Scaling Group
resource "aws_autoscaling_group" "web" {
name = "${local.name_prefix}-asg"
vpc_zone_identifier = aws_subnet.private[*].id
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
min_size = var.environment == "prod" ? 2 : 1
max_size = var.environment == "prod" ? 6 : 2
desired_capacity = var.environment == "prod" ? 2 : 1
launch_template {
id = aws_launch_template.web.id
version = "$Latest"
}
tag {
key = "Name"
value = "${local.name_prefix}-web"
propagate_at_launch = true
}
}
# Application Load Balancer
resource "aws_lb" "main" {
name = "${local.name_prefix}-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
enable_deletion_protection = var.environment == "prod"
tags = local.common_tags
}
resource "aws_lb_target_group" "web" {
name = "${local.name_prefix}-tg-web"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
health_check {
enabled = true
healthy_threshold = 2
unhealthy_threshold = 3
timeout = 5
interval = 30
path = "/health"
}
}
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.main.arn
port = "80"
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = aws_lb_target_group.web.arn
}
}
Sonuçlar ve Sonraki Adımlar
Artık Terraform ile profesyonel olarak çalışmak için sağlam bir temele sahipsiniz: sözdizimini biliyorsunuz HCL, AWS ve Azure sağlayıcılarını nasıl yapılandıracağınızı biliyorsunuz, Planla-Uygula-Yok Et döngüsünü ve kuralları anlıyorsunuz durum dosyasını güvenli bir şekilde yönetmek için gereklidir.
Terraform ile büyümenizin bir sonraki doğal adımı kodunuzu düzenlemeyi öğrenmektir içinde yeniden kullanılabilir modüller: Altyapınız 200-300 hattı aştığında HCL'nin geliştirilmesiyle modülerleştirme, sürdürülebilirlik açısından zorunlu hale gelir.
Komple Seri: Terraform ve IaC
- Madde 01 (bu) — Sıfırdan Terraform: HCL, Sağlayıcı ve Planla-Uygula-Yok Et
- Madde 02 — Yeniden Kullanılabilir Terraform Modüllerinin Tasarlanması: Yapı, G/Ç ve Kayıt Defteri
- Madde 03 — Terraform Durumu: S3/GCS ile Uzak Arka Uç, Kilitleme ve İçe Aktarma
- Madde 04 — CI/CD'de Terraform: GitHub Eylemleri, Atlantis ve Çekme İsteği İş Akışı
- Madde 05 — IaC Testi: Terratest, Terraform Yerel Testi ve Sözleşme Testi
- Madde 06 — IaC Güvenliği: Checkov, Trivy ve OPA Kod Olarak Politika
- Madde 07 — Terraform Çoklu Bulut: Paylaşılan Modüllerle AWS + Azure + GCP
- Madde 08 — Terraform için GitOps: Flux TF Denetleyicisi, Spacelift ve Drift Tespiti
- Madde 09 - Terraform, Pulumi ve OpenTofu: Son Karşılaştırma 2026
- Madde 10 - Terraform Kurumsal Kalıpları: Çalışma Alanı, Sentinel ve Ekip Ölçeklendirmesi
Resmi Kaynaklar
- Terraform'un resmi belgeleri
- Terraform Kayıt Defteri — sağlayıcılar, modüller ve politikalar
- HashiCorp Learn — Etkileşimli eğitimler







