
Tue Sep 01 2026

Hazırsan başlayalım 🚀
Üretim ortamına geçiş, bir modelin gerçek dünya dayanıklılığını test ettiği an. Laboratuvardaki metrikler güzel görünebilir ama canlı trafik, beklenmedik girdiler ve ölçek sorunları getirir. Bu yüzden sistem dayanıklılığı odaklı bir yaklaşım şart.
Neden bu kadar önemli?
Kısacası: Üretime alma anı "bitiş" değil, sürekli iyileştirme döngüsünün başlangıcı. Dayanıklı bir altyapı kurmazsan, modelin gücü riskli bir yük haline gelir.
Hadi pratik bir örnek üzerinden anlayalım 👇
Sonraki bölümlerde bu prensipleri nasıl kodlama ve pipeline'lara döküceğimize bakacağız.
Hazırsan bu üç sorunu tek tek, sistemik bir bakış açısıyla inceleyelim. Her biri öngörülebilirlik ve güvenilirlik üzerinde doğrudan etki yaratıyor ve bir araya geldiğinde dayanıklılığı ciddi oranda zayıflatıyor 🚧.
Özetle: Veri kalitesini garanti altına almak, guardrail mekanizmaları koymak ve tam gözlemlenebilirlik sağlamak; dayanıklı bir üretim ortamının üç temel direğidir. Her birini ayrı ayrı değil, bütünsel olarak ele almak, hem öngörülebilirliği hem de güvenilirliği artırır ✅.
Hadi pratikte karşılaştığımız en sık veri/bağlam sorunlarını tek tek inceleyelim. Her birinin test edilebilir bir senaryosu var ve hepsi modelin güvenilirliğini nasıl sarsabileceğini gösteriyor 🚨
null/None geldikçe model boşlukları doldurmak için hallüsinasyon yapıyor.address alanı olmadan istek at.int yerine string (ör. "123"), float yerine bool gelirse downstream hesaplamalar çöker.quantity alanına " beş " (string) gönder.discount_code alanı eklendi ama model hâlâ v1 şemasını kullanıyor.discount_code gönder, modelin bu alanı işleyip işlemediğini (veya hata verip vermediğini) izle.Aşağıdaki snippet, boş değer, tür eşleşmesi ve bağlam uyumluluğu kontrollerini tek bir fonksiyonda topluyor. Kendi pipeline’ına ekleyip unit testlerinizde koşturabilirsin 👇
from typing import Any, Dict, List, Tuple
def validate_payload(
payload: Dict[str, Any],
required_fields: List[str],
type_map: Dict[str, type],
context_version: int = 1,
) -> Tuple[bool, List[str]]:
"""
payload : Gelen veri sözlüğü
required_fields: Zorunlu alan isimleri
type_map : Alan -> beklenen Python tipi
context_version: Beklenen şema versiyonu (eski bağlam kontrolü)
Dönüş: (is_valid, hata_mesajları)
"""
errors: List[str] = []
# 1️⃣ Eksik alan kontrolü
for field in required_fields:
if field not in payload or payload[field] is None:
errors.append(f"❌ Eksik alan: '{field}'")
# 2️⃣ Tür uyumsuzluk kontrolü
for field, expected_type in type_map.items():
value = payload.get(field)
if value is not None and not isinstance(value, expected_type):
errors.append(
f"❌ Tür uyuşmazlığı: '{field}' beklenen {expected_type.__name__}, "
f"gelen {type(value).__name__}"
)
# 3️⃣ Bağlam/versiyon kontrolü (basit örnek)
payload_version = payload.get("_schema_version", 1)
if payload_version != context_version:
errors.append(
f"❌ Eski/geçersiz şema versiyonu: beklenen v{context_version}, "
f"gelen v{payload_version}"
)
return len(errors) == 0, errors
# ---- Kullanım örneği ----
if __name__ == "__main__":
sample = {
"order_id": 101,
"quantity": "5", # yanlış tip (string)
"address": None, # eksik alan
"_schema_version": 1, # doğru versiyon
}
required = ["order_id", "quantity", "address"]
types = {"order_id": int, "quantity": int, "address": str}
ok, msgs = validate_payload(sample, required, types, context_version=2)
if ok:
print("✅ Veri geçerli")
else:
for m in msgs:
print(m)
Bu sayede ne oluyor?
assert ile unit testine dönüştürülebilir.Özet: Eksik veri, tür uyumsuzluğu ve eski bağlam — üçlü bu sorun, modelin güvenilirliğini doğrudan tehlikeye atar. Yukarıdaki checklist ile bu riskleri CI/CD hattında otomatik olarak engelleyebilirsin. Hadi koduna ekleyelim ve gece rahat uyuyalım 😴✨
Hadi bir senaryo kurarak başlayalım: model üretime çıktığında bir değerlendirme süreci yoksa ne olur? 🤔
| Sorun | Açıklama |
|---|---|
| Kapsam darlığı | Sadece “küfür engelle” kuralı koyarsanız, PII sızıntısı veya hallüsinasyonlar geçer. |
| Statik listeler | Yeni argot, yeni veri formatları (ör. yeni TC kimlik no deseni) anında eklenmez. |
| Tek eylem tipi | Her ihlal için block kullanırsanız, kullanıcı deneyimi kırılır; replace veya truncate gibi esnek aksiyonlar gerekir. |
| Gözlem yok | Kural ihlalleri loglanmazsa, hangi kural ne sıklıkla tetikleniyor bilmezsiniz. |
block, replace, truncate, flag_for_review gibi seçenekler kullan.guardrails:
- name: no_pii
type: regex
pattern: '\b\d{3}-\d{2}-\d{4}\b'
action: block
- name: profanity_filter
type: keyword_list
keywords: ["kötü kelime1", "kötü kelime2"]
action: replace
replacement: "***"
- name: max_tokens
type: token_limit
limit: 500
action: truncate
- name: hallucination_check
type: semantic_similarity
threshold: 0.75
action: flag_for_review
Bu sayede ne oluyor?
no_pii → SSN benzeri desenleri engeller.profanity_filter → Küfürleri maskeler.max_tokens → Çok uzun cevapları keser.hallucination_check → Düşük benzerlik skorlu cevapları insan incelemesine bırakır.Bu yapıyı bir kez koyup unutmayın; sürekli izleme + otomatik test = güvenli üretim ✅.
Hazırsan başlayalım 🚀
Bir sistem gözlemlenebilir değilse, arka planda ne olduğunu asla tam olarak bilemezsiniz. Eksik loglama, metrik toplama ve uyarı mekanizmaları, küçük bir sorunu dev bir kesintiye dönüştürebilir. İşte bu boşlukların neler yarattığı ve nasıl kapatabileceğimiz:
Aşağıda, bir HTTP istek gecikmesi metriğini toplayıp, 95. percentile 500 ms’yi geçerse uyarı gönderen minimal bir yapılandırma var.
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'my-service'
static_configs:
- targets: ['service-host:9090']
# alert.rules.yml
groups:
- name: latency-alerts
rules:
- alert: HighRequestLatency
expr: histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 0.5
for: 2m
labels:
severity: critical
annotations:
summary: "⚠️ Yüksek istek gecikmesi (95. percentile > 500ms)"
description: "{{ $labels.instance }} üzerinde 5 dakika boyunca gecikme eşiği aşıldı."
# alertmanager.yml
route:
receiver: 'slack-notifications'
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receivers:
- name: 'slack-notifications'
slack_configs:
- api_url: 'https://hooks.slack.com/services/XXXX/XXXX/XXXX'
channel: '#alerts'
title: '{{ .GroupLabels.alertname }}'
text: '{{ .CommonAnnotations.description }}'
Ne oluyor burada?
prometheus.yml → Servisimizden her 15 s’de bir metrik çeker.alert.rules.yml → 95. percentile gecikme 0.5 s’yi geçerse HighRequestLatency uyarısı tetikler.alertmanager.yml → Uyarı Slack kanalına düşer, ekibimiz anında haberdar olur ✅.Hadi bu boşlukları kapatalım ve sistemlerimizi gözlemleyebilir, izlenebilir hale getirelim! 🚦
Hazırsan bu kontrol listesini birlikte inceleyelim. Üç ana alana ayırdım: Altyapı & Ortam, Uygulama & Kod, Süreç & İzleme. Her adımın neden kritik olduğunu da kısaca not ettim — böylece ekibiniz "checklist yapıyoruz" demekten öte, neden yapıyoruz diye de anlasın 🎯
| # | Adım | Neden Kritik? | Eylem Özeti |
|---|---|---|---|
| 1.1 | Immutable image/tag kullanımı | latest tag'i sürüm takibini imkansız kılar, rollback'te sürpriz yaşatır |
Tüm base image'lar ve dependency'ler için semver tag (örn. node:20.12.1-alpine) kilitleyin |
| 1.2 | Secrets management | Hardcoded secret = veri sızıntısı riski, rotation imkansız | Vault / AWS Secrets Manager / 1Password CLI ile runtime injection; repo'ya hiçbir secret commit etmeyin ❗️ |
| 1.3 | Network segmentation & least privilege | Yanlış yapılandırılmış SG / NACL = lateral movement yolu | DB sadece app subnet'ten erişilebilir; egress kuralları deny-by-default |
| 1.4 | Immutable infrastructure / drift detection | Manuel müdahale = reproducibility kaybı | Terraform plan/apply CI'da zorunlu; drift tespiti için terraform plan -detailed-exitcode nightly job |
| 1.5 | Container runtime hardening | Root container = host escape riski | runAsNonRoot: true, readOnlyRootFilesystem: true, capabilities: drop: ["ALL"] ✅ |
Kısa not: Bu adımları PR template'ine de ekleyin — review sırasında "Altyapı kontrolü geçti mi?" sorusunu standartlaştırırsınız 🛠
| # | Adım | Neden Kritik? | Eylem Özeti |
|---|---|---|---|
| 2.1 | SAST / SCA taraması | Vulnerable dependency = supply chain attack (Log4j hatırlayalım) | CI pipeline'da blocking modda: github.com/securego/gosec, npm audit --audit-level=high, trivy fs . |
| 2.2 | Dependency pinning & lockfiles | Transitive dep güncellemesi breaking change getirebilir | package-lock.json, go.sum, Cargo.lock commit edin; Dependabot/Renovate PR'larını auto-merge değil, review required yapın |
| 2.3 | Input validation & output encoding | XSS, SQLi, command injection giriş kapısı | Tüm boundary'lerde (HTTP, CLI, message queue) allowlist validation; template engine'lerde auto-escaping aktif |
| 2.4 | AuthZ/AuthN doğrulama | Broken access control = OWASP #1 | Policy-as-code (OPA/Cedar) testleri CI'da; integration test ile "user A, resource B'ye erişemez" senaryoları |
| 2.5 | Error handling & logging hygiene | Stack trace leakage = information disclosure | Structured JSON log; PII maskleme; error response'larda details alanını production'da kapatın |
| 2.6 | SBOM üretimi | Compliance & incident response için kaynak haritası | syft / cyclonedx-go ile her build'te SPDX/JSON artifact olarak publish edin 📦 |
| # | Adım | Neden Kritik? | Eylem Özeti |
|---|---|---|---|
| 3.1 | Canary / blue-green deploy stratejisi | Big-bang deploy = rollback süresi uzar, etki alanı büyür | Argo Rollouts / Flagger ile %5 → %25 → %100 otomatik; health check + SLO gate |
| 3.2 | Runbook & rollback prosedürü | Incident'te "ne yapacağız?" sorusu zaman kaybıdır | Her servis için 1 sayfalık runbook: rollback komutu, feature flag key'i, on-call kişi, iletişim kanalı |
| 3.3 | Observability baseline | Deploy sonrası "her şey normal mi?" cevabı verilemezse körüz | RED metrics (rate, errors, duration) + SLO burn alert; dashboard linki runbook'ta |
| 3.4 | Feature flag ile dark launch | Riskli değişikliği production trafiğinde test etmeden göndermek | LaunchDarkly / Unleash / homegrown; default-off, canary grubu ile açın 🔁 |
| 3.5 | Post-deploy smoke test & synthetic monitoring | CI geçti ama production'da bozulmuş olabilir | Critical user journey'ler için Playwright/Cypress smoke test; her 5 dk'da bir synthetic ping |
| 3.6 | Change freeze / communication penceresi | Beklenmedik deploy = destek ekibini şaşırtır | Deploy takvimi paylaşılan calendarda; #releases kanalında "deploy başladı / bitti" mesajı zorunlu 📢 |
| # | Alan | Adım | Durum | Not / Sahip |
|-----|-------------------|-------------------------------------------|-------|-------------|
| 1.1 | Altyapı | Immutable image/tag kilitli mi? | ☐ | |
| 1.2 | Altyapı | Secrets management aktif mi? | ☐ | |
| 1.3 | Altyapı | Network segmentation / least privilege? | ☐ | |
| 1.4 | Altyapı | Drift detection job çalışıyor mu? | ☐ | |
| 1.5 | Altyapı | Container hardening (non-root, read-only) | ☐ | |
| 2.1 | Uygulama | SAST/SCA blocking modda mı? | ☐ | |
| 2.2 | Uygulama | Lockfile commit edilmiş mi? | ☐ | |
| 2.3 | Uygulama | Input validation / output encoding var mı?| ☐ | |
| 2.4 | Uygulama | AuthZ policy testleri CI'da mı? | ☐ | |
| 2.5 | Uygulama | Error handling & log hygiene kontrolü | ☐ | |
| 2.6 | Uygulama | SBOM artifact publish ediliyor mu? | ☐ | |
| 3.1 | Süreç | Canary/blue-green stratejisi tanımlı mı? | ☐ | |
| 3.2 | Süreç | Runbook + rollback prosedürü güncel mi? | ☐ | |
| 3.3 | Süreç | RED metrics + SLO burn alert aktif mi? | ☐ | |
| 3.4 | Süreç | Feature flag dark launch hazır mı? | ☐ | |
| 3.5 | Süreç | Post-deploy smoke test çalışıyor mu? | ☐ | |
| 3.6 | Süreç | Change freeze / comms penceresi paylaşıldı mı? | ☐ | |
Nasıl kullanılır?
- Bu tabloyu repo'nuzdaki
RELEASE_CHECKLIST.mddosyasına koyun- Her sürüm öncesi PR description'a bu tabloyu kopyalayın
- Ekip arkadaşlarınız
@mentionile sahiplenip☐→✅/❌güncellesin- Merge gate'inizde "All checklist items ✅" zorunlu kılın — böylece unutulmaz ⛔
include edinÖzetle: Bu checklist bir kez yazıp unutulan bir belge değil, her sürümde ekip ritüeline dönüşen bir güvenlik alışkanlığı olmalı 🛡️ İlk sürümde eksikleriniz olacak — önemli olan her release'de bir tane daha kapatmak. Hadi bir sonraki deploy'unuzda deneyin, retrospektifde ne kadar fark ettiğinizi göreceksiniz ✨
Hadi pratik bir betik üzerinden anlayalım. Birkaç günlük bir kontrol listesini çalıştıran, sorunları yakalayan ve net bir rapor oluşturan küçük bir Bash scripti yazacağız (ai-deploy-check.sh). Bu sayede dağıtım aşamasında "tüm servise bak" diyebiliyor, sorunları hemen görüyorsunuz.
#!/usr/bin/env bash
# ai-deploy-check.sh – Basit dağıtım kontrol listesi
# Kullanım: ./ai-deploy-check.sh
set -euo pipefail
# Renk tanımları (CI ortamlarında yardımcı olur)
RED='[31m'
GREEN='[32m'
YELLOW='[33m'
NC='[0m' # No Color
log_info() { echo -e "${GREEN}[INFO]${NC} $*" ; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*" ; }
log_err() { echo -e "${RED}[ERROR]${NC} $*" ; }
# 1️⃣ Docker'ın kurulu olup olmadığını kontrol et
if ! command -v docker >/dev/null 2>&1; then
log_err "Docker bulunamadı – lütfen Docker'ı yükleyin."
exit 1
fi
log_info "Docker kontrolü tamam."
# 2️⃣ Temel çevre değişkenlerini kontrol et
for var in APP_ENV DATABASE_URL; do
if [[ -z "${!var:-}" ]]; then
log_warn "$var ayarlanmamış."
fi
done
# 3️⃣ Belirtilen imajı çek (örnek)
IMAGE="myrepo/my-app:${APP_VERSION:-latest}"
log_info "İmaj çekiliyor: $IMAGE"
docker pull "$IMAGE" || {
log_err "İmaj çekilemedi: $IMAGE"
exit 2
}
# 4️⃣ Önbelleği temizle ve konteyneri başlat ( örnek )
CONTAINER_NAME="my-app-container"
docker rm -f "$CONTAINER_NAME" >/dev/null 2>&1 || true
docker run -d \
--name "$CONTAINER_NAME" \
-p 8080:8080 \
"$IMAGE" || {
log_err "Konteyner başlatılamadı."
exit 3
}
log_info "Konteyner başlatıldı: $CONTAINER_NAME"
# 5️⃣ Sağlık kontrolü yap ( basit curl )
sleep 5
if ! curl -f http://localhost:8080/health >/dev/null 2>&1; then
log_err "Sağlık kontrolü başarısız."
docker logs "$CONTAINER_NAME"
exit 4
fi
log_info "Sağlık kontrolü geçti."
# 6️⃣ Port erişilebilirliği
if ! docker port "$CONTAINER_NAME" | grep -q "8080"; then
log_err "Port 8080 konteynerde yayınlanmıyor."
exit 5
fi
log_info "Port 8080 erişilebilir."
# Raporlama
echo "---------------------------"
log_info "Dağıtım denetimi tamamlandı."
log_info "Tüm kontroller geçti ✅"
echo "---------------------------"
# Özet dosyası (opsiyonel)
{
echo "Rapor oluşturulma zamanı: $(date)"
echo "İmaj: $IMAGE"
echo "Konteyner durumu: $(docker inspect --format='{{.State.Status}}' "$CONTAINER_NAME")"
} > deploy_check_report.txt
log_info "Rapor 'deploy_check_report.txt' dosyasına kaydedildi."
deploy_check_report.txt adında basit bir özet dosyası oluşturulur.Bu betiği CI/CD pipeline'ına dahil ederseniz, dağıtımlar öncesinde hızlı bir kontrol gerçekleşir. Bir sorun çıktığında betik hemen durur, böylece hata ayıklama süreci daha verimli hale gelir. 🚀
Harika bir yol katededin! 🎉 Sistem dayanıklılığı (resilience) bir hedef değil, sürekli bir alışkanlıktır. Bugün uyguladıklarımız — circuit breaker, retry, timeout, bulkhead — sadece "belli başlı hataları önleyen kod parçacıkları" değil; üretim ortamında uykuyu kaçıran o gece yarısı alarmlerden kurtaran kalkandır 🛡️.
Bu kadar derinlemesine konuya dalan, kodları okuyan, "neden?" diye soran bir geliştirici nadirdir. Şu an elinizde üretimde hayatta kalabilen servisler yazma kasası var. Bunu biriktirdikçe, sistemleriniz sadece "çalışır" olmaktan çıkıp "güvenilir" olur.
Hadi, sistemlerinizi dayanıklı kılmaya devam edin. Bir sonraki deploy'da "bu sefer farklı" diyebilmek için buradayız. 🤝
Kolay gelsin, güvenli deploylar! 🚢✨
Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.
All rights reserved