Terraform Planı Gizemi: Yanlış Kaynak Silen Otomasyon
Modern altyapı yönetiminin vazgeçilmez araçlarından biri olan Terraform, “Infrastructure as Code” (IaC) felsefesini benimseyerek cloud kaynaklarımızı kod aracılığıyla tanımlamamızı ve yönetmemizi sağlar. Bu sayede, altyapı süreçleri otomatize edilir, tutarlılık artırılır ve insan hataları minimize edilir. Ancak, bu otomasyonun gücü beraberinde büyük bir sorumluluk da getirir. Özellikle, terraform plan çıktısının doğru okunmaması veya otomasyonun körü körüne apply etmesi, ciddi felaketlere yol açabilir.
Bugün, Terraform’un en güçlü özelliklerinden biri olan terraform plan komutunun derinliklerine inecek, otomasyon süreçlerinde yanlış kaynakların silinmesine neden olan gizemleri çözecek ve bu tür talihsiz olayları önlemek için uygulanabilecek stratejileri detaylı bir şekilde inceleyeceğiz. Altyapınızı güvenle yönetmek için bu kritik bilgileri anlamak, her DevOps mühendisinin ve cloud mimarının önceliği olmalıdır.
Terraform Planı Nedir ve Neden Önemlidir?
terraform plan komutu, Terraform’un kalbinde yer alan ve herhangi bir değişiklik uygulamadan önce ne olacağını size gösteren bir önizleme aracıdır. Bu komut, mevcut altyapınızın durumu (state) ile Terraform konfigürasyonunuz arasında bir karşılaştırma yapar ve bu karşılaştırmaya dayanarak hangi kaynakların oluşturulacağını, güncelleneceğini veya silineceğini adım adım listeler.
Bu önizleme, potansiyel hataları veya istenmeyen değişiklikleri tespit etmek için hayati bir adımdır. Bir apply işlemi gerçekleştirmeden önce, tüm ekibin beklenen değişiklikleri doğrulamasını sağlar. Bu sayede, üretim ortamında beklenmedik kesintilerin veya veri kayıplarının önüne geçilmiş olur.
Plan Çıktısının Detaylı İncelenmesi
terraform plan çıktısı, yapılacak değişiklikleri sembollerle belirtir:
+(Create): Yeni bir kaynak oluşturulacak.-(Destroy): Mevcut bir kaynak silinecek.~(Update): Mevcut bir kaynak güncellenecek (değişikliğin türüne göre “in-place” veya “replace” olabilir).-/+(Destroy then Create): Bir kaynak önce silinecek, sonra yeni parametrelerle tekrar oluşturulacak. Bu genellikle bir kaynağın değiştirilemez (immutable) özelliklerinde yapılan değişikliklerde görülür.
Herhangi bir terraform plan çıktısını incelerken, özellikle Destroy (-) veya Destroy then Create (-/+) işaretlerine dikkat etmek gerekir. Bu işaretler, mevcut bir kaynağın silineceği anlamına gelir ve bu durum genellikle önemli bir veri kaybına veya kesintiye yol açabilir. Bu nedenle, bir silme işlemi öngörüldüğünde, bunun gerçekten amaçlanan bir eylem olup olmadığını iki kez kontrol etmek zorunludur.
# Örnek bir plan çıktısı (basitlestirilmis)
Terraform will perform the following actions:
# aws_instance.web_server will be created
+ resource "aws_instance" "web_server" {
+ ami = "ami-0abcdef1234567890"
+ instance_type = "t2.micro"
+ tags = {
+ "Name" = "new-web-server"
}
}
# aws_s3_bucket.data_bucket will be destroyed
- resource "aws_s3_bucket" "data_bucket" {
- acl = "private"
- bucket = "my-old-data-bucket-123"
- force_destroy = false
- id = "my-old-data-bucket-123"
# (lifecycle non-destructive changes)
}
# aws_instance.db_server will be updated in-place
~ resource "aws_instance" "db_server" {
id = "i-0123456789abcdef0"
~ instance_type = "t2.medium" -> "t2.large"
# (lifecycle non-destructive changes)
}
Plan: 1 to add, 1 to change, 1 to destroy.
Bu örnekte, bir web_server oluşturulacak, bir data_bucket silinecek ve bir db_server güncellenecektir. Özellikle data_bucket’ın silinecek olması, dikkatle incelenmesi gereken bir durumdur.
Otomasyon ve Terraform: Birleşim Noktası
Terraform, CI/CD (Sürekli Entegrasyon/Sürekli Teslimat) pipeline’ları ile entegre edildiğinde gerçek gücünü gösterir. Otomatik pipeline’lar, geliştiricilerin kod değişikliklerini otomatik olarak test etmesine, doğrulamasını yapmasına ve cloud ortamlarına dağıtmasına olanak tanır. Bu entegrasyon, altyapı değişikliklerinin hızlı, tekrarlanabilir ve hatasız bir şekilde yapılmasını sağlar.
Bir CI/CD pipeline’ında tipik bir Terraform süreci aşağıdaki adımları içerebilir:
terraform init: Gerekli provider’ları ve modülleri indirir.terraform validate: Konfigürasyon dosyalarını sözdizimi ve semantik hatalar açısından kontrol eder.terraform plan: Yapılacak değişiklikleri önizler ve bir plan dosyası (.tfplan) oluşturur.- Onay Aşaması: Plan çıktısı incelenir ve manuel veya otomatik olarak onaylanır.
terraform apply: Onaylanan planı cloud ortamına uygular.
Bu adımların otomasyonu, manuel müdahale ihtiyacını azaltarak dağıtım hızını artırır ve insan hatası riskini düşürür. Ancak, bu otomasyonun potansiyel tehlikeleri de göz ardı edilmemelidir.
Otomatik Plan Onaylama Tehlikeleri
Otomatik pipeline’larda en büyük risk, terraform apply -auto-approve komutunun körü körüne kullanılmasıdır. Bu komut, terraform plan tarafından oluşturulan planı herhangi bir insan müdahalesi veya onayı olmaksızın doğrudan uygular. Eğer plan çıktısı yanlış bir silme işlemi içeriyorsa ve bu otomasyon tarafından fark edilmezse, felaket kaçınılmaz hale gelir.
Bir geliştirici yanlışlıkla bir resource bloğunu koddan silebilir veya bir count değerini 0’a düşürebilir. Eğer CI/CD pipeline’ı bu değişikliği yakalayan terraform plan çıktısını bir onay adımına sunmadan doğrudan apply ederse, ilgili kaynak anında silinecektir. Bu durum, özellikle yüksek öncelikli veya kritik kaynaklar için kabul edilemez sonuçlar doğurabilir.
Yanlış Kaynak Silme Senaryosu: Vaka Çalışması
Bir senaryo düşünelim: Bir şirket, üretim ortamında çalışan kritik bir veritabanı sunucusunu (örneğin, aws_db_instance) yönetmek için Terraform kullanıyor. Geliştirici ekibi, yeni bir özellik üzerinde çalışırken, yanlışlıkla veya bir yanlış anlama sonucu, veritabanı sunucusunu tanımlayan Terraform konfigürasyonundaki aws_db_instance bloğunu yorum satırı haline getirir veya tamamen siler.
CI/CD pipeline’ı bu değişikliği algılar. terraform plan komutu çalıştırıldığında, çıktı şu şekilde görünür:
# Örnek plan çıktısı: Veritabanı siliniyor
Terraform will perform the following actions:
# aws_db_instance.main_db will be destroyed
- resource "aws_db_instance" "main_db" {
- allocated_storage = 20
- engine = "mysql"
- id = "my-production-db-identifier"
- instance_class = "db.t3.medium"
- skip_final_snapshot = false
# (lifecycle non-destructive changes)
}
Plan: 0 to add, 0 to change, 1 to destroy.
Eğer pipeline, bu terraform plan çıktısını otomatik olarak apply -auto-approve ile onaylayacak şekilde yapılandırılmışsa, üretim veritabanı anında silinecektir. Bu durum, saatler süren bir kesintiye, veri kaybına ve ciddi finansal zararlara yol açabilir. Bu tür bir olay, genellikle bir “kök neden analizi” (Root Cause Analysis - RCA) gerektirir ve organizasyonun güvenliğini sorgulatır.
Tetikleyici Faktörler ve Kök Neden Analizi
Yanlış kaynak silmelerine yol açan yaygın tetikleyici faktörler ve kök nedenler şunlar olabilir:
- Yanlışlıkla Kaynak Silme (HCL’den Kaldırma): En basit ve yaygın neden, bir geliştiricinin Terraform kodundan bir
resourcebloğunu yanlışlıkla kaldırmasıdır. countveyafor_eachDeğişiklikleri: Bir kaynağıncountmetası 1’den 0’a düşürüldüğünde veyafor_eachdöngüsündeki bir anahtar kaldırıldığında, ilgili kaynak silinir. Bu durum, özellikle dinamik kaynak tanımlamalarında sıkça karşılaşılan bir hatadır.resource "aws_instance" "web" { count = var.enable_web_server ? 1 : 0 # var.enable_web_server false olursa, sunucu silinir # ... }- State Drift (Durum Kayması): Terraform state dosyası ile gerçek altyapı arasındaki uyumsuzluklardır. Örneğin, bir kaynak manuel olarak silinir ancak state’te hala mevcut görünürse, Terraform bu durumu “silinmiş” olarak algılamaz. Ancak daha tehlikelisi, bir kaynak manuel olarak oluşturulur ve Terraform kodu tarafından yönetilmezse, Terraform bunu kendi yönetimi dışı bir kaynak olarak görür ve bir sorun yaratmaz. Ancak, eğer Terraform kodu bir kaynağı yönettiğini düşünüyorsa ve bu kaynak manuel olarak değiştirildiyse, Terraform planı beklenmedik değişiklikler gösterebilir.
- Modül Güncellemeleri: Kullanılan bir Terraform modülünün yeni bir versiyonu, iç yapısında yapılan değişiklikler nedeniyle beklenmedik
destroyişlemleri tetikleyebilir. Modülünoutput’ları veyaresourcetanımlamaları değiştiğinde bu durum ortaya çıkabilir. - Provider Versiyon Değişiklikleri: Terraform provider’larının yeni versiyonları bazen kaynakların varsayılan davranışlarını veya attribute’lerini değiştirebilir, bu da beklenmedik
destroyveyareplaceişlemlerine yol açabilir. - Değişken Değerlerinin Yanlış Ayarlanması: Ortam değişkenleri,
tfvarsdosyaları veya CI/CD pipeline’ında yanlış ayarlanmış değişkenler, kaynaklarıncountveyafor_eachdeğerlerini etkileyerek silinmelerine neden olabilir. - Resource Renaming veya ID Değişiklikleri: Terraform, bir kaynağın
id’sini veyatype’ını değiştirmediğiniz sürece, birresourcebloğunun adını değiştirdiğinizde (örneğinaws_instance.old_nameyerineaws_instance.new_name) bunu yeni bir kaynak oluşturup eskisini silme olarak algılar. Bunu önlemek içinterraform state mvveyamovedblokları kullanılmalıdır.
Felaketi Önlemek İçin Stratejiler
Yanlış kaynak silme senaryolarını önlemek için çok katmanlı bir savunma stratejisi oluşturmak esastır. İşte bazı etkili yaklaşımlar:
Kapsamlı Plan İncelemesi ve Onay Mekanizmaları
Otomasyon ne kadar hızlı olursa olsun, kritik değişiklikler için insan denetimi vazgeçilmezdir.
- Manuel İnceleme: Özellikle üretim ortamına yapılan her dağıtım öncesinde,
terraform plançıktısı bir ekip üyesi veya mimar tarafından dikkatlice incelenmeli ve onaylanmalıdır. - Pull Request (PR) Tabanlı Onaylar: Terraform kod değişiklikleri bir Git deposunda yönetiliyorsa, her değişiklik için bir Pull Request (veya Merge Request) oluşturulmalıdır. CI/CD pipeline’ı, PR açıldığında
terraform plan’ı çalıştırır ve çıktıyı PR yorumlarına ekler. Bu sayede ekip üyeleri, kodu ve plan çıktısını birlikte inceleyerek onay verebilir. - Policy-as-Code (PaC): OPA (Open Policy Agent) veya HashiCorp Sentinel gibi araçlar kullanarak, Terraform planlarını belirli güvenlik veya uyumluluk politikalarına göre otomatik olarak doğrulayabilirsiniz. Örneğin, “üretim ortamında
aws_db_instancesilme işlemleri engellenmelidir” gibi bir kural tanımlanabilir.
State Yönetimi ve Drift Tespiti
Terraform state’inin doğru ve güncel olması, planların doğruluğu için kritiktir.
- Remote State Kullanımı: State dosyasının lokalde tutulması yerine S3, Azure Blob Storage, Google Cloud Storage veya Terraform Cloud gibi uzak bir depolama alanında tutulması tavsiye edilir. Bu, state’in merkezi, güvenli ve versiyonlanabilir olmasını sağlar.
- Drift Tespiti (
terraform refresh):terraform refreshkomutu, Terraform state’ini gerçek altyapı durumuyla senkronize eder. Bu, manuel değişikliklerin state’e yansımasını sağlar.terraform plan -refresh-onlyise sadece state’i yeniler ve mevcut konfigürasyona göre silme/oluşturma işlemleri önermez, sadece drift’i gösterir. Düzenli drift tespiti, beklenmedik değişiklikleri erken aşamada fark etmenizi sağlar.
Güvenli CI/CD Pipeline Tasarımı
Pipeline’ların kendisi, istenmeyen değişiklikleri önleyecek şekilde tasarlanmalıdır.
- Ortam Ayrımı: Geliştirme, test ve üretim ortamları birbirinden tamamen izole edilmeli ve farklı Terraform state’leri tarafından yönetilmelidir. Üretim ortamına dağıtım yapmadan önce değişiklikler test ortamında doğrulanmalıdır.
- Minimum Ayrıcalık Prensibi (Least Privilege): CI/CD ajanı veya kullanıcı, Terraform operasyonlarını gerçekleştirmek için yalnızca gerekli minimum yetkilere sahip olmalıdır. Özellikle
destroyyetkisi, kritik ortamlarda kısıtlanmalıdır. - Koşullu
auto-approve:auto-approvesadece belirli koşullar altında (örneğin, sadece test ortamında veya manuel onaydan sonra) kullanılmalıdır. - Plan Dosyasının Kullanımı:
terraform plan -out=tfplankomutu ile oluşturulan plan dosyası, daha sonraterraform apply tfplanile uygulanmalıdır. Bu,planveapplyarasında geçen sürede başka bir kod değişikliğinin planı etkilemesini önler ve uygulamanın tam olarak planlanan şekilde gerçekleşmesini garanti eder. - Versiyon Sabitleme: Terraform versiyonu, provider versiyonları ve modül versiyonları (
~> 1.0,= 1.0.0) kod içerisinde sabitlenmelidir. Bu, beklenmedik versiyon yükseltmelerinden kaynaklanabilecek uyumsuzlukları ve hataları önler.
Kaynak Kilitleme ve Koruma (Lifecycle Rules)
Terraform ve cloud sağlayıcıları, kaynakları yanlışlıkla silinmeye karşı korumak için mekanizmalar sunar.
prevent_destroyMeta-Argumentı: Terraform’da, bir kaynağınlifecyclebloğundaprevent_destroy = trueayarlayarak, o kaynağınterraform destroyveyaterraform applyile silinmesini engelleyebilirsiniz. Bu, özellikle kritik veritabanları veya depolama kovaları için çok değerli bir güvenlik katmanıdır.
Bu ayar aktifken, Terraform bu bucket’ı silme girişimi yaptığında bir hata verecektir. Silme işlemi için bu ayarınresource "aws_s3_bucket" "sensitive_data_bucket" { bucket = "my-critical-data-bucket" lifecycle { prevent_destroy = true } }falseyapılması gerekir.- Cloud Sağlayıcılarının Silme Koruması: AWS RDS
Deletion Protection, Azure SQL DatabaseDeletion Locksveya Google Cloud StorageRetention Policygibi cloud servislerinin kendideletion protectionözelliklerini kullanmak, ekstra bir güvenlik katmanı sağlar. Bu, Terraform dışından da gelebilecek yanlışlıkla silme işlemlerine karşı koruma sağlar.
Kod Örnekleri ve En İyi Uygulamalar
prevent_destroy Kullanımı
Kritik bir S3 bucket’ı için prevent_destroy özelliğini nasıl kullanacağınıza dair bir örnek:
# main.tf
resource "aws_s3_bucket" "production_assets" {
bucket = "my-company-prod-assets-2026"
acl = "private"
tags = {
Environment = "Production"
ManagedBy = "Terraform"
}
# Bu bucket'ın Terraform tarafından yanlışlıkla silinmesini engeller
lifecycle {
prevent_destroy = true
}
}
# vars.tf
variable "aws_region" {
description = "AWS bölgesi"
type = string
default = "eu-central-1"
}
provider "aws" {
region = var.aws_region
}
Bu konfigürasyon ile, eğer birisi aws_s3_bucket.production_assets kaynağını HCL’den kaldırır ve terraform apply çalıştırmaya çalışırsa, Terraform bir hata verecek ve silme işlemini reddedecektir.
$ terraform plan
# (aws_s3_bucket.production_assets kaynağını kaldırdıktan sonra)
Terraform will perform the following actions:
# aws_s3_bucket.production_assets will be destroyed
- resource "aws_s3_bucket" "production_assets" {
- acl = "private"
- bucket = "my-company-prod-assets-2026"
- id = "my-company-prod-assets-2026"
- tags = {
- "Environment" = "Production"
- "ManagedBy" = "Terraform"
}
}
Plan: 0 to add, 0 to change, 1 to destroy.
$ terraform apply
Error: Instance cannot be destroyed
on main.tf line 14, in resource "aws_s3_bucket" "production_assets":
14: lifecycle {
15: prevent_destroy = true
16: }
This instance would be destroyed, but its meta-argument `prevent_destroy` is set to true.
To destroy this instance, remove that meta-argument and run `terraform apply` again.
terraform plan -out ve Güvenli terraform apply Akışı
CI/CD pipeline’ınızda plan dosyasını kullanarak güvenli bir dağıtım akışı oluşturabilirsiniz:
# Örnek GitLab CI/CD pipeline yapılandırması (basitleştirilmiş)
stages:
- init
- validate
- plan
- apply
variables:
TF_ROOT: ${CI_PROJECT_DIR}/terraform
TF_PLAN_FILE: plan.tfplan
init:
stage: init
script:
- cd $TF_ROOT
- terraform init
validate:
stage: validate
script:
- cd $TF_ROOT
- terraform validate
- terraform fmt -check=true # Kod formatını kontrol et
plan:
stage: plan
script:
- cd $TF_ROOT
- terraform plan -out=$TF_PLAN_FILE
- terraform show -no-color $TF_PLAN_FILE # Plan çıktısını okunabilir formatta göster
artifacts:
paths:
- ${TF_ROOT}/${TF_PLAN_FILE}
expire_in: 1 day # Plan dosyasını sakla
apply_review:
stage: apply
needs:
- plan
script:
- echo "Terraform plan has been generated. Please review the artifacts and approve the deployment."
- echo "To apply, trigger the 'apply_production' job manually."
when: manual # Manuel onay gerektiren bir aşama
apply_production:
stage: apply
needs:
- apply_review
script:
- cd $TF_ROOT
- terraform apply $TF_PLAN_FILE
when: manual # Manuel tetikleme ile apply
Bu pipeline, plan aşamasında bir .tfplan dosyası oluşturur ve bunu artifacts olarak saklar. apply_review aşaması manueldir ve kullanıcıya planı incelemesi için bir hatırlatma sunar. apply_production aşaması da manueldir ve sadece planın incelenip onaylanmasından sonra tetiklenebilir. Bu sayede, otomatik apply -auto-approve riskinden kaçınılmış olur.
Güvenli count ve for_each Kullanımı
Dinamik kaynakları yönetirken count veya for_each kullanımı, dikkatli olunmadığında beklenmedik silmelere yol açabilir. Kaynakların sırasını veya anahtarlarını değiştirmek, Terraform’un “bu eski kaynak silindi, yeni bir tane oluşturulacak” şeklinde yorumlamasına neden olabilir.
movedBlokları: Terraform 1.1’den itibarenmovedblokları, kaynakların yeniden adlandırılması veyafor_eachanahtarlarının değiştirilmesi gibi durumlarda, Terraform’a bu kaynakların aslında silinmediğini, sadece konumlarının değiştiğini bildirmenizi sağlar.# Eski: # resource "aws_instance" "web_server" { ... } # Yeni: resource "aws_instance" "app_server" { # Kaynak adını değiştirdik # ... } # moved bloğu ile Terraform'a bildiriyoruz: moved { from = aws_instance.web_server to = aws_instance.app_server }for_eachKullanırken Stabil Anahtarlar:for_eachkullanırken, koleksiyonunuzdaki anahtarların stabil olduğundan emin olun. Örneğin, bir liste yerine bir map kullanmak ve map anahtarlarının değişmeyeceğinden emin olmak, kaynakların yanlışlıkla silinmesini önleyebilir.
# Yanlış (sıra değişirse silinme riski var):
# variable "instance_names" {
# type = list(string)
# default = ["web1", "web2"]
# }
# resource "aws_instance" "web" {
# count = length(var.instance_names)
# tags = {
# Name = var.instance_names[count.index]
# }
# # ...
# }
# Doğru (anahtarlar stabil olduğu için daha güvenli):
variable "web_servers" {
type = map(object({
instance_type = string
ami_id = string
}))
default = {
"prod-web-01" = { instance_type = "t3.medium", ami_id = "ami-0abcdef123" }
"prod-web-02" = { instance_type = "t3.medium", ami_id = "ami-0abcdef123" }
}
}
resource "aws_instance" "web" {
for_each = var.web_servers
instance_type = each.value.instance_type
ami = each.value.ami_id
tags = {
Name = each.key
}
# ...
}
Bu örnekte, for_each ile map kullanmak, her bir sunucunun benzersiz bir anahtarla (örneğin “prod-web-01”) ilişkilendirilmesini sağlar. Bu sayede, map’ten bir anahtar silinmediği sürece, diğer sunucuların sıralaması değişse bile Terraform yanlışlıkla silme işlemi yapmaz.
Sonuç
Terraform, altyapı yönetiminde devrim yaratan güçlü bir araçtır. Ancak, gücünün farkında olmak ve potansiyel risklerini anlamak, onu sorumlu bir şekilde kullanmanın anahtarıdır. terraform plan komutu, bu riskleri yönetmek için bize sunulan en değerli araçlardan biridir. Onun çıktısını dikkatlice incelemek, otomasyonu körü körüne apply etmekten kaçınmak ve prevent_destroy gibi koruyucu mekanizmaları kullanmak, yanlış kaynak silme felaketlerini önlemenin temelidir.
Altyapınızı otomatize ederken hız ve verimlilik arayışında olmak doğaldır, ancak güvenlik ve tutarlılıktan asla ödün verilmemelidir. Güçlü bir CI/CD pipeline’ı, kapsamlı bir inceleme süreci ve iyi tanımlanmış politikalarla birleştiğinde, Terraform’un tüm avantajlarından yararlanırken, potansiyel riskleri minimize edebilirsiniz. Unutmayın, iyi planlanmış ve denetlenmiş bir otomasyon, sorunsuz ve güvenli bir altyapının temelidir.
Peki, siz Terraform planlarınızı otomasyon süreçlerinizde nasıl yönetiyorsunuz? Yanlış kaynak silme durumlarını önlemek için hangi stratejileri kullanıyorsunuz? Yorumlarda düşüncelerinizi ve deneyimlerinizi paylaşmaktan çekinmeyin!