Terraform Nedir, Hangi Sorunu Çözer?
Terraform, altyapıyı bildirimsel (declarative) bir yapılandırma dosyasıyla tanımlamanızı ve bu tanımı farklı bulut ya da servis sağlayıcılarında uygulamanızı sağlayan bir Infrastructure as Code (IaC) aracıdır. Elle konsoldan kaynak açmak yerine, istediğiniz son durumu yazarsınız; Terraform mevcut durumla karşılaştırıp aradaki farkı uygular.
Temel akış üç komuta dayanır: init (sağlayıcıları ve modülleri indirir), plan (ne yapılacağını gösterir), apply (uygular). Bu döngüyü anlamak, Terraform'un geri kalanını anlamanın çoğunu oluşturur.
Önkoşullar
- Bir bulut sağlayıcısında (örneklerde AWS kullanılacak) hesap ve API erişim bilgileri.
- Terraform CLI kurulu olmalı. Sürüm numarası vermiyorum; kurulumdan sonra
terraform versionile kendi sürümünüzü doğrulayın. Sürüme bağlı davranış farkları için resmi dokümantasyonu esas alın. - Temel komut satırı bilgisi.
Sağlayıcı sürümlerini ve Terraform çekirdek sürümünü required_providers ve required_version bloklarıyla sabitlemek, ekip içinde tutarlılık için önemlidir.
İlk Yapılandırma
Bir çalışma dizini oluşturup içine .tf uzantılı dosyalar koyun. Terraform bu dizindeki tüm .tf dosyalarını birlikte okur; dosya adları serbesttir.
# versions.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
~> 5.0 gibi bir kısıt, 5.x içindeki yamaları kabul edip 6.0'a çıkmayı engeller. Üretimde sürüm aralığını bilinçli seçin; kilit dosyası (.terraform.lock.hcl) tam sürümü zaten kaydeder ve sürüm kontrolüne eklenmelidir.
Değişkenler ve Çıktılar
Değişkenler değerleri parametreleştirir; çıktılar ise uygulama sonrası bilgi döndürür.
# variables.tf
variable "region" {
type = string
description = "Kaynakların oluşturulacağı AWS bölgesi"
default = "eu-central-1"
}
variable "instance_type" {
type = string
default = "t3.micro"
}
# outputs.tf
output "instance_id" {
value = aws_instance.web.id
description = "Oluşturulan EC2 örneğinin kimliği"
}
Değişkenlere değer vermenin yolları: default, terraform.tfvars dosyası, -var bayrağı veya ortam değişkenleri. Öncelik sırası Terraform dokümantasyonunda tanımlıdır; karışıklığı önlemek için ekipte tek bir yöntem benimseyin.
Kaynak Tanımlama ve Bağımlılıklar
# main.tf
resource "aws_instance" "web" {
ami = "ami-xxxxxxxxxxxxxxxxx" # kendi bölgeniz için geçerli bir AMI ile değiştirin
instance_type = var.instance_type
tags = {
Name = "web-server"
}
}
AMI kimliğini uydurmayın; kullandığınız bölgeye ait gerçek bir değeri konsoldan veya aws CLI ile alın.
Terraform, bir kaynağın çıktısını başka bir kaynağın girdisinde kullandığınızda bağımlılığı otomatik çıkarır ve oluşturma sırasını buna göre belirler. Örneğin bir güvenlik grubunun kimliğini örnek tanımında referans verirseniz, Terraform önce grubu oluşturur. Sıra kritik olduğu halde referans yoksa depends_on kullanılabilir, ancak bu son çare olmalıdır; gereksiz kullanım planı okunaksız hale getirir.
Plan ve Apply Döngüsü
terraform init
terraform fmt # biçimlendirme
terraform validate # sözdizimi ve temel tutarlılık
terraform plan
terraform apply
plan çıktısında + oluşturulacak, ~ güncellenecek, - silinecek kaynakları gösterir. apply öncesi planı mutlaka okuyun; özellikle silme işaretlerini. terraform destroy ise yapılandırmadaki kaynakları siler ve geri alınamaz.
State: Terraform'un Hafızası
Terraform, yönettiği kaynakları bir state dosyasında tutar. Varsayılan olarak yerel terraform.tfstate dosyası kullanılır; bu, tek kişilik denemeler için yeterlidir.
Ekip çalışmasında yerel state ciddi sorun çıkarır: iki kişi aynı anda apply çalıştırırsa state bozulabilir. Çözüm, uzak bir backend (örneğin S3 + DynamoDB kilitleme) kullanmaktır.
# backend.tf (örnek yapı; değerleri kendi ortamınıza göre doldurun)
terraform {
backend "s3" {
bucket = "sirket-terraform-state"
key = "web/terraform.tfstate"
region = "eu-central-1"
dynamodb_table = "terraform-lock"
encrypt = true
}
}
State dosyası düz metin olarak hassas değerler (şifreler, anahtarlar) içerebilir. Bu yüzden:
- State'i sürüm kontrolüne koymayın.
- Backend'de şifrelemeyi açın ve erişimi kısıtlayın.
terraform outputile yazdırdığınız değerlerin de görünür olduğunu unutmayın.
Modüller
Tekrarlanan yapılandırmayı modüllere ayırmak bakımı kolaylığı sağlar. Bir modül, girdi değişkenleri, kaynaklar ve çıktılardan oluşan bir dizindir.
module "web" {
source = "./modules/web"
instance_type = var.instance_type
region = var.region
}
Modül sürümlemesi için source olarak uzak bir Git deposu veya registry kullanıyorsanız bir sürüm/etiket sabitleyin. Sabitlenmemiş modül kaynağı, bir gün farkında olmadan değişen altyapı demektir.
Yaygın Hatalar
- State'i elle düzenlemek. State bozulursa
terraform statealt komutlarıyla (ör.state mv,state rm) müdahale edin; dosyayı doğrudan açıp değiştirmeyin. - Planı okumadan
apply. Özellikle-işaretli satırlar veri kaybı anlamına gelebilir. - Hassas değerleri koda gömmek. Erişim anahtarlarını
.tfdosyasına yazmak yerine ortam değişkeni veya gizli yönetim aracı kullanın. - Sürümleri sabitlememek. Sağlayıcı ve modül sürümlerini kilitleyin; aksi halde aynı kod farklı makinelerde farklı sonuç üretebilir.
depends_on'u alışkanlık haline getirmek. Çoğu bağımlılık referanslarla zaten çıkarılır.- Kaynakları elle değiştirmek. Konsoldan yapılan değişiklikler state ile uyuşmazlık yaratır; bir sonraki
applybunları geri alabilir.
Güvenlik Etkileri
- State erişimi = altyapı erişimi. State'i okuyabilen biri, tanımlı kaynaklar ve olası gizli değerler hakkında bilgi sahibi olur.
- Least privilege. Terraform'un kullandığı kimlik yalnızca gereken izinlere sahip olmalı;
*yetkili anahtarlar kaçınılmalı. - Plan çıktısı.
planveapplyçıktıları CI loglarına düşer; hassas değerlerin loglanmasını engelleyin. - Değişmez altyapı. Kaynakları elle yamamak yerine kodu güncelleyip yeniden uygulamak, denetlenebilirlik sağlar.
Kapanış
Terraform'u güvenli kullanan ekip, sürümleri sabitleyen, state'i uzak ve şifreli tutan, planı okuyan ve değişiklikleri koda yansıtan ekiptir. Bu üç alışkanlık — sürüm kilitleme, uzak state, plan disiplini — aracın geri kalanını öngörülebilir kılar.