TB
← Tüm yazılar

Ortamlar arasi tutarlılık

Geliştirme, test ve üretim ortamları arasında yapılandırma, altyapı ve davranış tutarlılığını sağlamanın stratejileri, araçları ve pratik uygulamaları.

"Benim makinemde çalışıyor" cümlesi, yazılım geliştirmenin en pahalı esprilerinden biridir. Geliştirme ortamında sorunsuz geçen kod, staging'de farklı bir veritabanı sürümü yüzünden başarısız olur; üretimde ise eksik environment variable felakete dönüşür. Ortamlar arası tutarlılık (environment parity), bu sınıf sorunları kökünden azaltır.

12-Factor App ilkesi

Heroku'nun 12-Factor metodolojisinin onuncu maddesi açıktır: dev/prod parity. Geliştirme, staging ve production ortamları mümkün olduğunca aynı olmalıdır. Zaman geçtikçe fark büyür; bu nedenle tutarlılık sürekli bir çaba gerektirir, bir kerelik kurulum değildir.

Tutarlılık boyutları:

  • Altyapı: Aynı container imajı, aynı orchestrator
  • Bağımlılıklar: Aynı runtime sürümü, aynı kütüphane versiyonları
  • Yapılandırma: Aynı config şeması, farklı değerler
  • Veri: Anonimleştirilmiş üretim benzeri test verisi

Container ile ortam standardizasyonu

Docker, ortamlar arası tutarlılığın en etkili araçlarından biridir. Uygulama container imajı olarak paketlenir; geliştirme, CI ve üretim aynı imajı çalıştırır. Fark yalnızca dışarıdan enjekte edilen yapılandırmadır.

# Aynı imaj, farklı ortam
docker run -e ASPNETCORE_ENVIRONMENT=Development app:2.4.0
docker run -e ASPNETCORE_ENVIRONMENT=Production app:2.4.0

Multi-stage build ile geliştirme bağımlılıkları üretim imajına girmez; imaj boyutu ve saldırı yüzeyi küçülür.

Yapılandırma yönetimi

Yapılandırma kod deposunda değil, ortam değişkenlerinde veya secret manager'da tutulmalıdır. ASP.NET Core'da appsettings.json temel şema sağlar; ortam-spesifik override appsettings.Production.json veya environment variable ile gelir.

Tutarlılık kontrol listesi:

  1. Tüm ortamlarda aynı config key'leri tanımlı mı?
  2. Eksik key uygulama başlangıcında hata veriyor mu?
  3. Secret'lar asla repo'da değil, vault'ta mı?
  4. Config değişikliği deployment gerektirmeden yapılabiliyor mu?

Altyapı kodu ile ortam klonlama

Terraform modülleri ile staging ve production aynı kod tabanından üretilir. Tek fark tfvars dosyasındaki parametrelerdir:

# staging.tfvars
instance_count = 1
db_sku         = "B_Standard_B1ms"

# production.tfvars
instance_count = 3
db_sku         = "GP_Standard_D4s_v3"

Kod farkı ortamlar arası "staging'de çalıştı, prod'da patladı" senaryosunun bir numaralı nedenidir.

Veri tutarlılığı

Üretim veritabanının tam kopyası geliştirmede kullanılamaz; KVKK ve güvenlik engelleri vardır. Alternatifler:

  • Anonimleştirilmiş snapshot: Kişisel veriler maskeleme scripti ile temizlenir
  • Synthetic data: Fabrik pattern ile gerçekçi test verisi üretilir
  • Contract testing: Veri yerine API sözleşmesi doğrulanır

Veritabanı şema sürümü tüm ortamlarda aynı olmalıdır. Migration'lar CI pipeline'ında staging'e otomatik, production'a onaylı uygulanır.

Feature flag ile davranış farkı

Ortamlar arası tutarlılık, tüm ortamlarda aynı kodun çalışması demektir; aynı özelliklerin açık olması değildir. Feature flag mekanizması, kod deploy edilmiş ama özellik kapalı senaryosunu yönetir:

if (featureFlags.IsEnabled("new-checkout-flow"))
{
    return await _newCheckout.ProcessAsync(order);
}
return await _legacyCheckout.ProcessAsync(order);

Staging'de flag açık, production'da kapalı olabilir; kod aynıdır. Bu, ortam-spesifik branch tutma anti-pattern'inin yerini alır.

CI/CD pipeline tutarlılığı

Pipeline'ın kendisi de ortamlar arası farklı davranmamalıdır. Aynı build artifact tüm ortamlara promote edilir:

  1. Build: imaj oluştur, test çalıştır, imajı registry'e push et
  2. Deploy staging: aynı imaj tag'i ile staging'e deploy
  3. Deploy production: onay sonrası aynı imaj tag'i ile production'a deploy

Production'da yeniden build yapmak, test edilmemiş bir artifact'ın canlıya çıkması demektir. "Hotfix için prod'da build aldık" istisnası runbook'ta tanımlı olmalı ve nadir kullanılmalıdır.

Testcontainers ile entegrasyon testi

CI ortamında gerçek PostgreSQL, Redis veya RabbitMQ container'ları Testcontainers ile ayağa kaldırılır. Mock yerine gerçek bağımlılık kullanımı, ortam farkından kaynaklanan sürprizleri azaltır:

var postgres = new PostgreSqlBuilder()
    .WithImage("postgres:16-alpine")
    .Build();
await postgres.StartAsync();

CI'daki test ortamı, production'a yakın davranır; "CI'da geçti, prod'da kırıldı" riski düşer.

Ortam drift tespiti

Zamanla ortamlar sapabilir. Düzenli kontroller:

  • IaC plan çıktısı: beklenmeyen drift var mı?
  • Dependency audit: ortamlar arası paket sürümü farkı
  • Config diff: staging ve prod config key karşılaştırması
  • Runtime version: .NET, Node, PostgreSQL minor sürüm uyumu

Haftalık veya sprint sonunda otomatik drift raporu üretmek, sorunları büyümeden yakalar.

Ephemeral preview ortamları

Her pull request için geçici ortam oluşturmak, tutarlılığı test etmenin güçlü yoludur. PR merge edilmeden önce gerçek altyapıda çalışan uygulama incelenir. Preview ortamı production modülünün küçültülmüş kopyasıdır; farklı bir deployment yöntemi kullanılmaz.

Organizasyonel boyut

Teknik araçlar tek başına yeterli değildir. Ekip kültürü de tutarlılığı desteklemelidir:

  • Ortam-spesifik hack'ler code review'da reddedilir
  • "Sadece prod'da çalışan" config kabul edilmez
  • Incident post-mortem'de ortam farkı kök neden olarak araştırılır

Pratik hedefler

%100 parity gerçekçi değildir; üretim ölçeği staging'de maliyetli olabilir. Hedef, anlamlı parity olmalıdır:

  1. Aynı container imajı ve config şeması
  2. Aynı major bağımlılık sürümleri
  3. Representative (temsilci) test verisi
  4. Aynı deployment mekanizması
  5. Staging'de production trafik profiline yakın load test

Ağ ve güvenlik tutarlılığı

Ortamlar arası fark yalnızca uygulama kodunda değil, ağ topolojisinde de oluşabilir. Staging'de açık olan firewall kuralı production'da kapalıysa, entegrasyon testi geçer ama canlı trafik başarısız olur. IaC ile ağ kuralları da kod olarak tanımlanmalı; ortamlar arası fark yalnızca CIDR ve IP aralıklarında olmalıdır.

TLS sertifika zinciri, DNS yapılandırması ve WAF kuralları staging'de production ile aynı yapıda test edilmelidir. Self-signed sertifika kullanan staging ortamı, sertifika pinning kullanan istemcilerde production'a taşınmayan gizli hataya yol açar.

Performans ve ölçek farkı yönetimi

Staging'in production kadar büyük olması maliyetli olduğundan ölçek farkı kaçınılmazdır. Bu farkı yönetmek için:

  • Oranları koruyun: production 3 node ise staging 1 node olabilir, ama aynı imaj ve config kullanılmalı
  • Load test ile ölçek dışı davranışları staging'de simüle edin
  • Auto-scaling kuralları aynı metriklere dayanmalı; yalnızca eşik değerleri farklılaşmalı

Performans testi sonuçları ortam farkından arındırılarak raporlanır; "staging'de 200ms, prod'da 800ms" karşılaştırması yanıltıcı olabilir çünkü kaynak boyutu farklıdır.

Üçüncü parti servis tutarlılığı

Ödeme gateway, SMS sağlayıcı ve harita servisi gibi dış bağımlılıklar ortamlar arası farklı endpoint kullanmalıdır. Sandbox/staging API anahtarları production anahtarlarından ayrı tutulur. Ancak API sözleşmesi (request/response şeması) aynı olmalıdır; sandbox'ın farklı response formatı döndürmesi entegrasyon sürprizlerine neden olur.

Contract test, sandbox ile production API davranışının uyumunu sürekli doğrular. Sağlayıcı API sürümü değiştiğinde hem sandbox hem production endpoint'leri aynı sprint'te güncellenir.

Tutarlılık metrikleri

Olgun ekipler ortam parity'yi ölçer:

  1. Config key coverage: staging ve prod arasındaki key eşleşme yüzdesi
  2. Image digest parity: staging'de test edilen imaj ile prod'da çalışan imaj aynı mı
  3. Dependency version drift: lock file farkı var mı
  4. Incident ortam farkı oranı: olayların yüzde kaçı ortam tutarsızlığından kaynaklandı

Bu metrikler sprint retrospektifinde gözden geçirilir; parity skoru düşüyorsa teknik borç olarak ele alınır.

Local development ile parity

Geliştirici makinesi de tutarlılık zincirinin parçasıdır. Dev Containers veya Docker Compose ile local ortam, CI ve staging ile aynı servis topolojisini çalıştırır. Host makinede doğrudan dotnet run yerine container içinde geliştirme, "local'de farklı SDK sürümü" sorununu ortadan kaldırır.

Compose override dosyası (docker-compose.override.yml) kişisel tercihler içindir; takım genelinde paylaşılan docker-compose.yml değiştirilmemelidir. Override gitignore'da tutulur; ortak yapılandırma repo'da kalır.

Platform engineering perspektifi

Platform ekibi, geliştirici ekiplere tutarlı ortam şablonları (golden path) sunar. Yeni servis oluşturulduğunda CI pipeline, Dockerfile, health check, config şeması ve deployment manifest otomatik scaffold edilir. Her ekip sıfırdan farklı pattern icat etmek yerine onaylı şablonu kullanır. Bu yaklaşım ortamlar arası tutarlılığı organizasyon ölçeğinde garanti eder.

Bu hedefler karşılandığında "benim makinemde çalışıyor" cümlesi tarihe karışır; güvenilir teslimat hızlanır.