Modül 1 · Container & Temel Altyapı · ⏱ 7 dk

Terraform: altyapıyı kodla yaz

Terraform infrastructure as code

Bu derste neler öğreneceksin

  • Terraform resource block yazar
  • terraform.tfvars ile parametre geçer
  • terraform apply çalıştırır

Terraform: Altyapıyı Kod Olarak Yazmak

Veri mühendisliğinde sık yapılan hata: “Elimle tıklayarak GCP konsolundan bucket açtım, BigQuery dataset kurdum, IAM rolü verdim.” Üç ay sonra başka bir ortam kurman gerekti (staging, dev, prod), her şeyi sıfırdan elden yaptın. Yanlış ayarı kaçırdın, ortamlar drift etti.

Terraform bu sorunu çözer. Tüm altyapıyı kod olarak yazarsın. Tek bir komutla her ortamı aynı şekilde kurarsın. Yanlış olan bir şey varsa terraform plan sana önceden söyler.

Terraform’un Temel Kavramları

  • Provider: Bulut sağlayıcısı eklentisi. GCP, AWS, Azure, Docker, GitHub — hepsinin provider’ı var.
  • Resource: “Şu olsun” dediğin bir şey. Bir VM, bir bucket, bir veritabanı.
  • State: Terraform’un kurduğu her şeyin kaydı. Yerelde terraform.tfstate dosyasında.
  • Plan / Apply: Plan ne yapılacağını gösterir, apply gerçekten yapar.

Kurulum

Mac:

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

Windows (Scoop):

scoop install terraform

Linux:

sudo apt install terraform
# veya snap
sudo snap install terraform --classic

Doğrula: terraform --version. 1.x görmelisin.

Yerel Örnek: Docker ile Postgres

Önce yerel Docker üzerinde çalışalım, kredi kartı gerektirmez:

mkdir limonata-tf && cd limonata-tf

main.tf dosyası oluştur:

terraform {
  required_version = ">= 1.6"

  required_providers {
    docker = {
      source  = "kreuzwerker/docker"
      version = "~> 3.0"
    }
  }
}

provider "docker" {}

resource "docker_container" "limonata_db" {
  name  = "limonata-db"
  image = "postgres:18"
  env = [
    "POSTGRES_USER=${var.db_user}",
    "POSTGRES_PASSWORD=${var.db_password}",
    "POSTGRES_DB=${var.db_name}"
  ]
  ports {
    internal = 5432
    external = 5432
  }
}

variables.tf:

variable "db_user" {
  type        = string
  description = "Postgres kullanıcı adı"
}

variable "db_password" {
  type        = string
  description = "Postgres şifresi"
  sensitive   = true
}

variable "db_name" {
  type        = string
  description = "Postgres veritabanı adı"
}

terraform.tfvars:

db_user     = "elif"
db_password = "limonata2026"
db_name     = "limonata_db"

Şimdi sırayla:

terraform init
terraform plan
terraform apply

init provider’ı indirir. plan ne yapılacağını gösterir (henüz kurulum yok). apply onay ister, “yes” yaz, kurulum başlar.

docker ps ile limonata-db konteynerini gör.

Değişiklik ve Drift

terraform.tfvars’ta şifreyi değiştir:

db_password = "yeni-sifre-2026"

Tekrar:

terraform plan

Plan çıktısında şunu görürsün:

docker_container.limonata_db will be updated in-place
  ~ env = [
      - "POSTGRES_PASSWORD=limonata2026"
      + "POSTGRES_PASSWORD=yeni-sifre-2026"
    ]

Terraform, sadece değişeni günceller. Container’ı silmez, sadece env değişkenini değiştirir (uygulanabilir olanı).

Eğer biri dışarıdan docker rm ile konteyneri sildiyse, Terraform farkı görür ve yeniden kurar:

terraform plan
# "docker_container.limonata_db will be created" -> drift düzeltmesi

Bu drift detection, Terraform’un en güçlü özelliklerinden biri.

GCP Örneği (önizleme)

Bir sonraki derste GCP’ye geçeceğiz. Oraya hazırlık olarak kısa bir bakış:

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.gcp_project_id
  region  = "europe-west1"
}

resource "google_storage_bucket" "limonata_lake" {
  name     = "${var.gcp_project_id}-limonata-lake"
  location = "EU"

  uniform_bucket_level_access = true
}

resource "google_bigquery_dataset" "limonata" {
  dataset_id = "limonata_data"
  location   = "EU"
}

Bu kod bir bucket (data lake) ve bir BigQuery dataset kurar. Daha fazlasını sonraki derste.

En İyi Pratikler

  1. State’i uzakta tut. Birden fazla kişi aynı altyapıyı yönetiyorsa terraform.tfstate S3 veya GCS’de olmalı. Yoksa karışır.
  2. Asla şifre koda gömülmesin. sensitive = true ile değişken tanımla, terraform.tfvars ayrı dosyada, .gitignore’da.
  3. Modüler yaz. Bir klasörde tek bir main.tf yerine modüller (modules/ alt klasörler) ile grupla.
  4. Remote backend kullan. backend "gcs" { bucket = "..." } gibi.

Yıkmak

Test bitince:

terraform destroy

“yes” de. Tüm konteynerler silinir. State dosyası kalır; lazım olursa apply ile hepsi geri gelir.

Alıştırma

  1. terraform.tfvars dosyasını oluştur, içine db_password koy. apply çalıştır.
  2. Konteyner dışarıdan silindiğinde (docker rm -f limonata-db) Terraform plan çıktısı ne diyor? Drift düzeltiyor mu?
  3. Bucket ve dataset örneğini yorum olarak main.tf’e ekle. Hangi provider’ların eksik olduğunu listele.

Sıradaki

Yerelde altyapı kurmayı öğrendin. Şimdi bunu bulutta yapıyoruz →