GCP Cloud CDN Yapılandırması: Kapsamlı Rehber

Google Cloud üzerinde bir web uygulaması ya da API yayınladığında, kullanıcıların coğrafi konumu ne olursa olsun hızlı bir deneyim yaşaması için CDN (Content Delivery Network) kullanmak neredeyse zorunlu hale gelmiş durumda. GCP’nin sunduğu Cloud CDN servisi, Google’ın küresel edge ağını kullanarak içerikleri kullanıcıya en yakın PoP’tan (Point of Presence) sunuyor. Bu yazıda Cloud CDN’i sıfırdan yapılandırmayı, cache politikalarını optimize etmeyi ve gerçek dünya senaryolarında karşılaşılan sorunları ele almayı konuşacağız.

Cloud CDN’in Temel Mimarisi

Cloud CDN, Google Cloud Load Balancing üzerine inşa edilmiş bir servis. Yani CDN’i etkinleştirmek için önce bir HTTP(S) Load Balancer’a ihtiyacın var. Mimari şöyle çalışıyor:

  • İstemci isteği Google’ın edge ağına ulaşıyor
  • Edge node önce cache’e bakıyor, hit varsa direkt dönüyor
  • Cache miss durumunda istek backend‘e iletiliyor
  • Yanıt hem istemciye hem de edge cache’e yazılıyor

Bu yapı sayesinde backend sunucularının yükü dramatik biçimde düşüyor. Özellikle statik asset yoğun uygulamalarda %80-90 cache hit oranı görmek mümkün.

Cloud CDN’in desteklediği backend türleri şunlar:

  • Instance Groups: Klasik VM tabanlı backend’ler
  • Cloud Storage buckets: Statik dosya sunumu için ideal
  • Network Endpoint Groups (NEG): Container ve serverless backend’ler
  • Cloud Run, Cloud Functions, App Engine: Serverless entegrasyonlar

Ön Koşulların Hazırlanması

Başlamadan önce birkaç şeyin yerinde olması lazım. Önce gcloud CLI’nın güncel olduğundan emin ol:

gcloud components update
gcloud auth login
gcloud config set project YOUR_PROJECT_ID

Gerekli API’leri etkinleştir:

gcloud services enable compute.googleapis.com
gcloud services enable certificatemanager.googleapis.com

Örnek senaryomuzda bir e-ticaret uygulaması için CDN yapılandıracağız. Backend olarak bir Instance Group kullanacağız, statik dosyalar için ise Cloud Storage bucket’ı entegre edeceğiz.

Load Balancer ve Backend Servis Oluşturma

Cloud CDN’i etkinleştirmek için önce backend servisini oluşturman gerekiyor. Instance group’u zaten var olduğunu varsayıyorum, doğrudan backend servis adımına geçiyorum:

# Backend servis oluştur
gcloud compute backend-services create ecommerce-backend 
    --protocol=HTTP 
    --port-name=http 
    --health-checks=ecommerce-health-check 
    --global 
    --enable-cdn 
    --cache-mode=CACHE_ALL_STATIC

# Instance group'u backend'e ekle
gcloud compute backend-services add-backend ecommerce-backend 
    --instance-group=ecommerce-ig 
    --instance-group-zone=europe-west1-b 
    --balancing-mode=UTILIZATION 
    --max-utilization=0.8 
    --global

Burada --enable-cdn parametresi CDN’i aktif ediyor, --cache-mode=CACHE_ALL_STATIC ise Content-Type header’ına göre statik dosyaları otomatik cache’liyor.

Cache mode seçenekleri:

  • CACHE_ALL_STATIC: HTML dışındaki statik içerikleri otomatik cache’ler (resim, CSS, JS vb.)
  • USE_ORIGIN_HEADERS: Backend’in döndürdüğü Cache-Control header’larına göre davranır
  • FORCE_CACHE_ALL: Tüm yanıtları cache’ler, hatta no-cache direktiflerini bile override eder

URL Map ve HTTPS Proxy Yapılandırması

Backend servisimizi bir URL map’e bağlıyoruz:

# URL map oluştur
gcloud compute url-maps create ecommerce-url-map 
    --default-service=ecommerce-backend

# SSL sertifikası oluştur (Google-managed)
gcloud compute ssl-certificates create ecommerce-ssl-cert 
    --domains=www.example.com,example.com

# HTTPS proxy oluştur
gcloud compute target-https-proxies create ecommerce-https-proxy 
    --url-map=ecommerce-url-map 
    --ssl-certificates=ecommerce-ssl-cert

# Global forwarding rule oluştur
gcloud compute forwarding-rules create ecommerce-https-rule 
    --address=ecommerce-ip 
    --global 
    --target-https-proxy=ecommerce-https-proxy 
    --ports=443

HTTP’den HTTPS’e yönlendirme için ayrı bir forwarding rule gerekiyor:

# HTTP yönlendirme için URL map
gcloud compute url-maps import ecommerce-http-redirect 
    --global 
    --source /dev/stdin << 'EOF'
kind: compute#urlMap
name: ecommerce-http-redirect
defaultUrlRedirect:
  redirectResponseCode: MOVED_PERMANENTLY_DEFAULT
  httpsRedirect: true
EOF

gcloud compute target-http-proxies create ecommerce-http-proxy 
    --url-map=ecommerce-http-redirect

gcloud compute forwarding-rules create ecommerce-http-rule 
    --address=ecommerce-ip 
    --global 
    --target-http-proxy=ecommerce-http-proxy 
    --ports=80

Cache Key Politikalarını Özelleştirme

Varsayılan olarak Cloud CDN, tam URL’yi cache key olarak kullanıyor. Ama gerçek dünyada bu her zaman yeterli değil. Örneğin, aynı içeriğin farklı dil versiyonlarını ayrı cache’lemek isteyebilirsin.

Cache key politikasını backend servis düzeyinde ayarlayabiliyorsun:

gcloud compute backend-services update ecommerce-backend 
    --global 
    --cache-key-policy-include-host 
    --cache-key-policy-include-protocol 
    --cache-key-policy-include-query-string 
    --cache-key-policy-query-string-whitelist=lang,version,region

Query string whitelist önemli bir nokta. Eğer utm_source, fbclid gibi tracking parametrelerini cache key’e dahil etmezsen, aynı sayfa için gereksiz yere farklı cache entry’leri oluşturmamış olursun. Bu hem cache hit oranını artırır hem de storage maliyetini düşürür.

Header bazlı cache key özelleştirmesi için daha gelişmiş senaryolara bakabiliriz. Örneğin Accept-Language header’ına göre farklı cache:

gcloud compute backend-services update ecommerce-backend 
    --global 
    --cache-key-policy-include-http-headers=Accept-Language,Accept-Encoding

Cloud Storage Backend ile Statik Dosya CDN’i

E-ticaret senaryomuzda ürün görselleri ve statik assetler için Cloud Storage bucket’ını CDN arkasına almak istiyoruz. Bu yapı çok yaygın ve oldukça etkili:

# Storage bucket'ı backend olarak ekle
gcloud compute backend-buckets create static-assets-backend 
    --gcs-bucket-name=ecommerce-static-assets 
    --enable-cdn 
    --cache-mode=CACHE_ALL_STATIC 
    --default-ttl=86400 
    --max-ttl=604800 
    --client-ttl=3600

# URL map'e path rule ekle
gcloud compute url-maps add-path-matcher ecommerce-url-map 
    --path-matcher-name=assets-matcher 
    --default-service=ecommerce-backend 
    --backend-bucket-path-rules="/static/*=static-assets-backend,/images/*=static-assets-backend"

TTL değerlerini açıklayayım:

  • default-ttl: Cache-Control header’ı yoksa kullanılacak TTL (saniye cinsinden, burada 1 gün)
  • max-ttl: Backend ne söylerse söylesin cache’de tutulacak maksimum süre (burada 7 gün)
  • client-ttl: İstemci tarafında (tarayıcı) tutulacak süre (burada 1 saat)

Bucket’ın public erişimini ayarla ama doğrudan erişimi kısıtlamak isteyebilirsin. CDN signed URL kullanmak bunu çözüyor, buna birazdan değineceğiz.

Cache Invalidation (Önbellek Temizleme)

Deployment yaptıktan sonra eski içeriğin cache’de kalması ciddi sorunlara yol açabilir. Cloud CDN’de cache invalidation için:

# Belirli bir URL'nin cache'ini temizle
gcloud compute url-maps invalidate-cdn-cache ecommerce-url-map 
    --path="/index.html" 
    --global

# Wildcard ile tüm CSS dosyalarını temizle
gcloud compute url-maps invalidate-cdn-cache ecommerce-url-map 
    --path="/static/css/*" 
    --global

# Tüm cache'i temizle (dikkatli kullan!)
gcloud compute url-maps invalidate-cdn-cache ecommerce-url-map 
    --path="/*" 
    --global

Cache invalidation işlemleri genellikle birkaç dakika içinde tüm edge node’lara yayılıyor. Ama deploy pipeline’ına entegre etmek istiyorsan, invalidation’dan sonra bir süre beklemeyi veya cache bypass mekanizmasını kullanmayı düşün.

Gerçek dünyada CI/CD pipeline’ında bunu nasıl kullanırsın:

#!/bin/bash
# deploy-and-invalidate.sh

PROJECT_ID="my-project"
URL_MAP="ecommerce-url-map"
DEPLOY_PATHS=("/static/js/*" "/static/css/*" "/index.html")

echo "Deployment tamamlandi, cache temizleniyor..."

for path in "${DEPLOY_PATHS[@]}"; do
    echo "Cache temizleniyor: $path"
    gcloud compute url-maps invalidate-cdn-cache $URL_MAP 
        --path="$path" 
        --global 
        --project=$PROJECT_ID
    sleep 2
done

echo "Cache invalidation tamamlandi."

Signed URL ile Özel İçerik Koruması

Premium içerik veya kullanıcıya özel dosyalar için CDN’den yararlanırken aynı zamanda yetkisiz erişimi engellemek istiyorsan, Cloud CDN’in Signed URL özelliği tam olarak bunun için var.

Önce bir Cloud CDN key oluştur:

# CDN key oluştur
gcloud compute sign-url-key create ecommerce-cdn-key 
    --key-file=/tmp/cdn-key.json 
    --backend-service=ecommerce-backend 
    --global

Python ile signed URL üretme örneği (bu genellikle uygulama backend’inde yapılır):

# gcloud ile test amaçlı signed URL üret
gcloud compute sign-url 
    "https://www.example.com/premium/content.pdf" 
    --key-name=ecommerce-cdn-key 
    --key-file=/tmp/cdn-key.json 
    --expires-in=1h

Monitoring ve Cache Hit Oranını Takip Etme

CDN yapılandırdıktan sonra etkinliğini ölçmek şart. Cloud Monitoring üzerinden CDN metriklerini izleyebilirsin:

# Cache hit/miss oranlarını sorgulamak için gcloud logging
gcloud logging read 
    'resource.type="http_load_balancer" AND jsonPayload.cacheHit=true' 
    --limit=100 
    --format="json" 
    --project=YOUR_PROJECT_ID | 
    python3 -c "
import sys, json
logs = json.load(sys.stdin)
hits = len(logs)
print(f'Son 100 logda cache hit: {hits}')
"

Cloud Monitoring dashboard için alert policy oluşturmak da iyi bir pratik:

# Yüksek cache miss oranı için alert
gcloud alpha monitoring policies create 
    --policy-from-file=cdn-alert-policy.yaml

cdn-alert-policy.yaml içeriği:

cat > cdn-alert-policy.yaml << 'EOF'
displayName: "CDN Cache Miss Rate High"
combiner: OR
conditions:
  - displayName: "Cache miss rate > 50%"
    conditionThreshold:
      filter: >
        resource.type="https_lb_rule"
        AND metric.type="loadbalancing.googleapis.com/https/request_count"
        AND metric.labels.cache_result="MISS"
      comparison: COMPARISON_GT
      thresholdValue: 1000
      duration: 300s
      aggregations:
        - alignmentPeriod: 60s
          perSeriesAligner: ALIGN_RATE
notificationChannels:
  - projects/YOUR_PROJECT/notificationChannels/CHANNEL_ID
EOF

Gerçek Dünya Senaryosu: A/B Test ile CDN Optimizasyonu

Bir müşteride şöyle bir durum yaşadık: Sitelerinin Türkiye’deki kullanıcıları için load time’ı optimize etmeleri gerekiyordu. Avrupa’daki edge node’lardan geldiği için Türkiye’de hala 200-300ms gecikme vardı. Cloud CDN’in compression özelliğini açmak ve cache TTL’leri artırmak büyük fark yarattı.

Compression’ı etkinleştirmek için:

# Backend servis için compression modu ayarla
gcloud compute backend-services update ecommerce-backend 
    --global 
    --compression-mode=AUTOMATIC

AUTOMATIC mod, Accept-Encoding header’ına göre gzip veya brotli sıkıştırması uygular. Özellikle büyük JSON yanıtları ve HTML sayfaları için %60-70 boyut küçülmesi sağlıyor.

Ayrıca custom response header ekleyerek debug süreçlerini kolaylaştırabilirsin:

# Cache durumunu header olarak döndür
gcloud compute backend-services update ecommerce-backend 
    --global 
    --custom-response-header='X-Cache-Status:{cdn_cache_status}' 
    --custom-response-header='X-Cache-ID:{cdn_cache_id}'

Bu headerlar sayesinde tarayıcı developer tools’dan direkt “HIT” ya da “MISS” görebiliyorsun. Hem debug hem de müşteriye kanıtlama için çok işe yarıyor.

Güvenlik: Cloud Armor ile CDN Entegrasyonu

CDN’in önüne Cloud Armor security policy eklemek, DDoS koruması ve WAF özellikleri kazandırıyor:

# Security policy oluştur
gcloud compute security-policies create ecommerce-security-policy 
    --description="E-commerce CDN security policy"

# Rate limiting kuralı ekle
gcloud compute security-policies rules create 1000 
    --security-policy=ecommerce-security-policy 
    --expression="true" 
    --action=rate-based-ban 
    --rate-limit-threshold-count=1000 
    --rate-limit-threshold-interval-sec=60 
    --ban-duration-sec=600 
    --conform-action=allow 
    --exceed-action=deny-429

# Security policy'yi backend'e bağla
gcloud compute backend-services update ecommerce-backend 
    --global 
    --security-policy=ecommerce-security-policy

Cloud Armor ile CDN’i birlikte kullanmanın güzel yanı şu: Kötü niyetli istekler edge’de engelleniyor, backend’e hiç ulaşmıyor. Bu hem güvenlik hem de maliyet açısından avantajlı.

Terraform ile Infrastructure as Code

Manuel gcloud komutları yerine Terraform kullanmak, özellikle birden fazla ortam yönetiyorsan çok daha temiz bir yaklaşım:

# main.tf için backend service tanımı
cat > cdn_backend.tf << 'EOF'
resource "google_compute_backend_service" "ecommerce_cdn" {
  name                  = "ecommerce-backend"
  protocol              = "HTTP"
  port_name             = "http"
  load_balancing_scheme = "EXTERNAL"
  enable_cdn            = true

  cdn_policy {
    cache_mode                   = "CACHE_ALL_STATIC"
    default_ttl                  = 86400
    max_ttl                      = 604800
    client_ttl                   = 3600
    negative_caching             = true
    serve_while_stale            = 86400
    
    cache_key_policy {
      include_host          = true
      include_protocol      = true
      include_query_string  = true
      query_string_whitelist = ["lang", "version"]
    }
  }

  backend {
    group           = google_compute_instance_group_manager.ecommerce.instance_group
    balancing_mode  = "UTILIZATION"
    max_utilization = 0.8
  }

  health_checks = [google_compute_health_check.ecommerce.id]
}
EOF

terraform init
terraform plan
terraform apply

serve_while_stale parametresi dikkat çekici: Cache süresi dolmuş olsa bile, backend’e istek yaparken eski cache’i sunmaya devam ediyor. Bu kullanıcı deneyimini bozmuyor, backend yenileme arka planda gerçekleşiyor.

Yaygın Sorunlar ve Çözümleri

Sorun 1: Cache hit oranı beklenenden düşük

Genellikle sebebi Cache-Control header’larının yanlış ayarlanmış olması. Backend’in döndürdüğü headerlara bak:

curl -I https://www.example.com/static/main.js | grep -E "cache-control|age|x-cache"

Eğer no-store veya private görüyorsan, backend uygulamanın bu headerlari düzeltmesi gerekiyor.

Sorun 2: Websocket bağlantıları CDN üzerinden geçmiyor

Cloud CDN WebSocket desteklemiyor. WebSocket için ayrı bir backend service ve load balancer oluşturman gerekiyor, CDN’i bypass etmeli.

Sorun 3: Büyük dosyalarda yavaş ilk yükleme

Cloud CDN, büyük dosyalar için range request caching’i destekliyor. Video içeriklerinde max-ttl değerini yüksek tut ve serve_while_stale aktif et.

Sorun 4: Farklı kullanıcılara farklı içerik gönderme gereksinimi

Kişiselleştirilmiş içerik için CDN kullanmamalısın. Bu istekleri backend’e yönlendir, cache key’e cookie eklemek yönetilemez bir karmaşıklık yaratır.

Maliyet Optimizasyonu

Cloud CDN maliyeti iki bileşenden oluşuyor: cache egress ve HTTP request sayısı. Maliyeti düşürmek için:

  • Cache hit oranını artır (TTL’leri optimize et)
  • Gereksiz query string parametrelerini cache key’den çıkar
  • Küçük dinamik yanıtları CDN’e sokma, sadece statik assetleri cache’le
  • Negative caching aktif et, 404 yanıtları da cache’lensin ki backend sürekli aynı geçersiz isteği işlemesin
# Negative caching için TTL ayarla
gcloud compute backend-services update ecommerce-backend 
    --global 
    --negative-caching 
    --negative-caching-policy='404=300,410=300'

Bu ayar 404 ve 410 yanıtlarını 5 dakika cache’liyor. Bot’ların sürekli var olmayan URL’lere istek atması durumunda backend’i koruyan çok etkili bir mekanizma.

Sonuç

Cloud CDN yapılandırması ilk bakışta karmaşık görünse de, katmanlı mantığını kavrayınca oldukça sezgisel hale geliyor. Temel akış şu: Load Balancer oluştur, backend servisine CDN’i etkinleştir, cache mode ve TTL politikalarını ihtiyacına göre ayarla, cache key’leri optimize et.

Gerçek dünya projelerinde en büyük farkı yaratan şeyler genellikle şunlar oluyor: TTL değerlerini agresif biçimde artırmak, gereksiz query string parametrelerini cache key’den çıkarmak ve compression’ı aktif etmek. Bu üç ayarlamayı doğru yapan projelerde backend trafiğinin %70-80 azaldığını, sayfa yüklenme sürelerinin ise yarıya indiğini gördüm.

Cloud Armor entegrasyonunu da atlama. CDN’i güvenlik katmanı olmadan açmak, trafik yüklenmesini azaltırken saldırı yüzeyini artırabilir. İkisini birlikte yapılandırmak, hem performans hem de güvenlik açısından sağlam bir altyapı ortaya çıkarıyor.

Monitoring tarafında cache hit oranını, origin load’u ve error rate’i düzenli takip et. Cloud Monitoring’deki hazır dashboard template’leri bu konuda işini oldukça kolaylaştırıyor.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir