GCP Cloud CDN Kurulum ve Yapılandırma Rehberi
Google Cloud Platform’da bir web uygulaması yayına aldığınızda, kullanıcıların coğrafi konumundan bağımsız olarak hızlı bir deneyim yaşaması için CDN (Content Delivery Network) kullanmak neredeyse zorunlu hale geliyor. GCP Cloud CDN, Google’ın küresel ağ altyapısını kullanarak statik ve dinamik içerikleri edge node’lardan sunuyor. Bu yazıda Cloud CDN’i sıfırdan kuracak, yapılandıracak ve gerçek dünya senaryolarında nasıl kullanacağımızı adım adım inceleyeceğiz.
Cloud CDN Nedir ve Ne Zaman Kullanmalısınız
Cloud CDN, Google’ın 100’den fazla ülkede bulunan edge PoP (Point of Presence) lokasyonları üzerinden içerik dağıtımı yapan bir hizmettir. Temel çalışma mantığı şu şekildedir: kullanıcı bir istek attığında, bu istek önce en yakın edge node’a gider. Edge node’da içerik önbellekte varsa, doğrudan oradan döner. Yoksa origin server’a gidip yanıtı alır, önbellekler ve kullanıcıya iletir.
Bunu kullanmanız gereken başlıca durumlar:
- Statik dosya yoğunluğu: CSS, JS, görseller, videolar gibi içeriklerin büyük kısmını oluşturduğu siteler
- Global kullanıcı kitlesi: Türkiye dışında da kullanıcısı olan uygulamalar
- Yüksek trafikli dönemler: Kampanya, sezon sonu gibi ani trafik artışlarına karşı origin’i korumak
- Origin maliyeti azaltma: Backend sunucusunun bant genişliği ve işlem yükünü düşürmek
Cloud CDN’in önemli bir farkı, HTTP Load Balancer ile sıkı entegrasyonudur. Yani Cloud CDN’i aktif etmek için mutlaka bir HTTP(S) Load Balancer oluşturmanız gerekiyor.
Ön Gereksinimler
Başlamadan önce şunların hazır olması gerekiyor:
- Aktif bir GCP projesi ve fatura hesabı
gcloudCLI kurulu ve yapılandırılmış- Yeterli IAM izinleri (en azından
roles/compute.admin) - Origin olarak kullanılacak bir kaynak (Cloud Storage bucket, backend instance grubu veya Cloud Run servisi)
gcloud CLI versiyonunuzu ve bağlı projenizi kontrol edin:
gcloud version
gcloud config get-value project
gcloud config set project YOUR_PROJECT_ID
Gerekli API’leri etkinleştirin:
gcloud services enable compute.googleapis.com
gcloud services enable storage.googleapis.com
Senaryo 1: Cloud Storage ile Statik Site CDN Kurulumu
En yaygın kullanım senaryosundan başlayalım. Bir React veya Vue.js build çıktısını Cloud Storage’a koyup CDN üzerinden sunacağız.
Cloud Storage Bucket Oluşturma
# Bucket oluştur (benzersiz isim zorunlu)
gsutil mb -p YOUR_PROJECT_ID -c STANDARD -l europe-west1 gs://cdn-static-assets-demo
# Public okuma izni ver
gsutil iam ch allUsers:objectViewer gs://cdn-static-assets-demo
# Statik web sitesi yapılandırması
gsutil web set -m index.html -e 404.html gs://cdn-static-assets-demo
# Örnek dosyaları yükle
gsutil -m cp -r ./dist/* gs://cdn-static-assets-demo/
Backend Bucket ve Load Balancer Kurulumu
Cloud CDN’in devreye girmesi için Load Balancer’a ihtiyacımız var. Sırayla oluşturalım:
# Backend bucket oluştur
gcloud compute backend-buckets create cdn-backend-bucket
--gcs-bucket-name=cdn-static-assets-demo
--enable-cdn
--cache-mode=CACHE_ALL_STATIC
--default-ttl=3600
--max-ttl=86400
# URL map oluştur
gcloud compute url-maps create cdn-url-map
--default-backend-bucket=cdn-backend-bucket
# HTTP proxy oluştur
gcloud compute target-http-proxies create cdn-http-proxy
--url-map=cdn-url-map
# Global forwarding rule oluştur (statik IP)
gcloud compute addresses create cdn-static-ip
--network-tier=PREMIUM
--ip-version=IPV4
--global
gcloud compute forwarding-rules create cdn-forwarding-rule
--address=cdn-static-ip
--global
--target-http-proxy=cdn-http-proxy
--ports=80
IP adresini öğrenin ve DNS kaydı oluşturun:
gcloud compute addresses describe cdn-static-ip --global --format="value(address)"
HTTPS Yapılandırması
Production ortamında HTTP yetmez, HTTPS zorunlu. Google-managed SSL sertifikası kullanalım:
# SSL sertifikası oluştur
gcloud compute ssl-certificates create cdn-ssl-cert
--domains=cdn.example.com
--global
# HTTPS proxy oluştur
gcloud compute target-https-proxies create cdn-https-proxy
--url-map=cdn-url-map
--ssl-certificates=cdn-ssl-cert
# HTTPS forwarding rule
gcloud compute forwarding-rules create cdn-https-rule
--address=cdn-static-ip
--global
--target-https-proxy=cdn-https-proxy
--ports=443
Senaryo 2: Compute Engine Backend ile Dinamik İçerik CDN
Statik dosyaların yanı sıra API yanıtlarını da önbellekleyebilirsiniz. Bunun için Compute Engine instance grubu veya Cloud Run backend kullanacağız.
Instance Group Backend ile Kurulum
# Instance template oluştur
gcloud compute instance-templates create web-server-template
--machine-type=e2-medium
--image-family=debian-11
--image-project=debian-cloud
--tags=http-server,https-server
--metadata=startup-script='#!/bin/bash
apt-get update
apt-get install -y nginx
systemctl enable nginx
systemctl start nginx'
# Managed instance group oluştur
gcloud compute instance-groups managed create web-mig
--template=web-server-template
--size=2
--zone=europe-west1-b
# Health check oluştur
gcloud compute health-checks create http web-health-check
--port=80
--request-path=/health
--check-interval=10s
--timeout=5s
--healthy-threshold=2
--unhealthy-threshold=3
# Backend service oluştur (CDN etkin)
gcloud compute backend-services create web-backend-service
--protocol=HTTP
--port-name=http
--health-checks=web-health-check
--enable-cdn
--cache-mode=USE_ORIGIN_HEADERS
--global
# Backend'i instance group'a bağla
gcloud compute backend-services add-backend web-backend-service
--instance-group=web-mig
--instance-group-zone=europe-west1-b
--global
Cache Modu Seçenekleri ve Yapılandırması
Cloud CDN’de üç farklı cache modu var ve hangisini seçeceğiniz kullanım senaryonuza göre değişiyor:
- CACHE_ALL_STATIC: JS, CSS, görseller, fontlar gibi statik içerikleri otomatik önbellekler. Origin header’larını görmezden gelebilir.
- USE_ORIGIN_HEADERS: Origin’den gelen
Cache-Control,Expiresheader’larına göre davranır. En esnek seçenek. - FORCE_CACHE_ALL: Tüm yanıtları önbellekler, hatta
Cache-Control: no-cachebile gelse. Dikkatli kullanın.
Mevcut backend bucket’ın cache ayarlarını güncellemek için:
gcloud compute backend-buckets update cdn-backend-bucket
--cache-mode=USE_ORIGIN_HEADERS
--default-ttl=7200
--max-ttl=604800
--client-ttl=3600
--negative-caching
--negative-caching-policy='404=60,410=120'
--default-ttl: Origin header yoksa kullanılacak TTL (saniye cinsinden) --max-ttl: Origin header’ı ne derse desin maksimum TTL süresi --client-ttl: Tarayıcı önbelleği için gönderilen TTL --negative-caching: 404, 410 gibi hata kodlarını da önbellekler --negative-caching-policy: Hangi hata kodunun kaç saniye önbelleğe alınacağı
Cache Invalidation (Önbellek Temizleme)
Deploy sonrasında eski içeriğin kullanıcılara görünmesi, en sık karşılaşılan CDN sorunlarından biridir. Cache invalidation ile belirli URL’lerin önbelleğini temizleyebilirsiniz.
# Belirli bir dosyayı temizle
gcloud compute url-maps invalidate-cdn-cache cdn-url-map
--path="/index.html"
--global
# Bir dizini tamamen temizle
gcloud compute url-maps invalidate-cdn-cache cdn-url-map
--path="/static/*"
--global
# Tüm önbelleği temizle (dikkatli kullanın, maliyetli olabilir)
gcloud compute url-maps invalidate-cdn-cache cdn-url-map
--path="/*"
--global
CI/CD pipeline’ınıza şu scripti ekleyerek her deploy sonrasında otomatik temizlik yapabilirsiniz:
#!/bin/bash
# deploy_and_invalidate.sh
set -e
PROJECT_ID="your-project-id"
BUCKET_NAME="cdn-static-assets-demo"
URL_MAP="cdn-url-map"
BUILD_DIR="./dist"
echo "Dosyalar upload ediliyor..."
gsutil -m rsync -r -d "$BUILD_DIR" "gs://$BUCKET_NAME"
echo "Cache invalidation yapiliyor..."
gcloud compute url-maps invalidate-cdn-cache "$URL_MAP"
--path="/*"
--global
--project="$PROJECT_ID"
echo "Deploy tamamlandi!"
Signed URL ile Güvenli İçerik Dağıtımı
Sadece yetkili kullanıcıların belirli içeriklere erişmesini istiyorsanız, Cloud CDN Signed URL özelliğini kullanabilirsiniz. Ödeme duvarı arkasındaki içerikler, premium video içerikleri veya kişisel belgeler için idealdir.
Önce bir signing key oluşturun:
# Key oluştur ve backend'e ekle
gcloud compute sign-url-key create cdn-signing-key
--key-file=cdn-signing-key.json
--backend-bucket=cdn-backend-bucket
# Key'i kaydet (güvenli yerde saklayın!)
head -c 16 /dev/urandom | base64 | tr '+/' '-_' > cdn-signing-key.bin
Python ile signed URL oluşturma örneği:
import datetime
import base64
import hashlib
import hmac
from urllib.parse import urlparse, urlencode
def sign_url(url, key_name, key, expiration_seconds=3600):
"""Cloud CDN icin signed URL olusturur."""
expiration = int(
(datetime.datetime.utcnow() +
datetime.timedelta(seconds=expiration_seconds)).timestamp()
)
parsed = urlparse(url)
# Query string'e key name ve expiration ekle
query_params = f"KeyName={key_name}&Expires={expiration}"
if parsed.query:
url_to_sign = f"{url}&{query_params}"
else:
url_to_sign = f"{url}?{query_params}"
# HMAC-SHA1 imzala
decoded_key = base64.urlsafe_b64decode(key)
signature = base64.urlsafe_b64encode(
hmac.new(decoded_key, url_to_sign.encode('utf-8'), hashlib.sha1).digest()
).decode('utf-8')
return f"{url_to_sign}&Signature={signature}"
# Kullanim
with open('cdn-signing-key.bin', 'r') as f:
key = f.read().strip()
signed = sign_url(
url="https://cdn.example.com/premium/video.mp4",
key_name="cdn-signing-key",
key=key,
expiration_seconds=3600
)
print(signed)
Cache Hit Oranını İzleme ve Optimizasyon
CDN kurduğunuzda ilk sorulardan biri “ne kadar etkili çalışıyor?” olur. Cloud Monitoring ile bunu takip edebilirsiniz.
# Cache hit oranını sorgula (Cloud Monitoring MQL ile)
gcloud monitoring metrics list
--filter="metric.type=loadbalancing.googleapis.com/https/request_count"
# Daha detaylı metrik sorgusu
gcloud logging read
'resource.type="http_load_balancer" AND jsonPayload.cacheHit=true'
--limit=100
--format=json | jq '.[].jsonPayload | {url: .requestUrl, status: .status, cacheHit: .cacheHit}'
Prometheus uyumlu bir monitoring stack kullanıyorsanız, Cloud Monitoring Exporter ile metrikleri çekebilirsiniz. Ama basit bir kontrol için şu gcloud komutu da işe yarar:
# Son 1 saatteki cache istatistikleri
gcloud logging read
'resource.type="http_load_balancer"'
--freshness=1h
--format='value(jsonPayload.cacheHit, jsonPayload.requestUrl)' |
awk '{if($1=="true") hit++; else miss++} END {print "Hit:", hit, "Miss:", miss, "Hit Rate:", hit/(hit+miss)*100"%"}'
Cache hit oranı düşükse kontrol edilecekler:
- Vary header sorunu: Origin,
Vary: CookieveyaVary: Authorizationgönderiyorsa CDN bu istekleri önbelleklemez. Origin tarafında düzeltin. - TTL çok kısa: Origin’den gelen
Cache-Control: max-age=60gibi kısa TTL’ler önbellek ömrünü azaltır. - Cache-Control: private: Bu header’ı taşıyan yanıtlar CDN tarafından önbelleğe alınmaz. Sadece kullanıcıya özgü içeriklerde kullanın.
- Query string farkları:
?v=1ve?v=2farklı cache key’leri oluşturur. Query string’leri normalize edin.
Custom Headers ve Security Policy Entegrasyonu
Cloud CDN’e Cloud Armor entegre ederek DDoS koruması ve WAF kuralları ekleyebilirsiniz:
# Cloud Armor security policy oluştur
gcloud compute security-policies create cdn-security-policy
--description="CDN icin temel guvenlik politikasi"
# Belirli bir ülkeden gelen trafiği engelle
gcloud compute security-policies rules create 1000
--security-policy=cdn-security-policy
--expression="origin.region_code == 'RU'"
--action=deny-403
# Rate limiting kuralı ekle (IP başına 100 istek/dakika)
gcloud compute security-policies rules create 2000
--security-policy=cdn-security-policy
--expression="true"
--action=rate-based-ban
--rate-limit-threshold-count=100
--rate-limit-threshold-interval-sec=60
--ban-duration-sec=600
# Security policy'yi backend'e bağla
gcloud compute backend-services update web-backend-service
--security-policy=cdn-security-policy
--global
Custom response header’ları da ekleyebilirsiniz. Bu özellikle debugging sırasında hangi edge node’un yanıt verdiğini görmek için faydalıdır:
gcloud compute backend-buckets update cdn-backend-bucket
--custom-response-header='X-Cache-Status: {cdn_cache_status}'
--custom-response-header='X-Edge-Location: {cdn_pop_id}'
--custom-response-header='Strict-Transport-Security: max-age=31536000; includeSubDomains'
Terraform ile Infrastructure as Code
Tüm bu yapıyı manuel CLI komutuyla kurmak yerine Terraform ile yönetmek, production ortamlarında çok daha mantıklı. Temel yapılandırma:
# main.tf
resource "google_compute_backend_bucket" "cdn_backend" {
name = "cdn-backend-bucket"
bucket_name = google_storage_bucket.static_assets.name
enable_cdn = true
cdn_policy {
cache_mode = "CACHE_ALL_STATIC"
default_ttl = 3600
max_ttl = 86400
client_ttl = 3600
negative_caching = true
negative_caching_policy {
code = 404
ttl = 60
}
cache_key_policy {
include_host = true
include_protocol = true
include_query_string = false
}
}
}
resource "google_compute_url_map" "cdn_url_map" {
name = "cdn-url-map"
default_service = google_compute_backend_bucket.cdn_backend.id
}
resource "google_compute_managed_ssl_certificate" "cdn_cert" {
name = "cdn-ssl-cert"
managed {
domains = ["cdn.example.com"]
}
}
resource "google_compute_global_address" "cdn_ip" {
name = "cdn-static-ip"
network_tier = "PREMIUM"
}
resource "google_compute_global_forwarding_rule" "https_rule" {
name = "cdn-https-rule"
target = google_compute_target_https_proxy.cdn_https_proxy.id
port_range = "443"
ip_address = google_compute_global_address.cdn_ip.address
load_balancing_scheme = "EXTERNAL"
}
Bu Terraform konfigürasyonunu terraform plan ile test edip terraform apply ile uygulayabilirsiniz. State’i remote backend’de (GCS bucket) tutmayı unutmayın.
Maliyet Optimizasyonu İpuçları
Cloud CDN kullandıkça şu maliyet kalemlerine dikkat edin:
- Cache egress: Önbellekten sunulan verinin maliyeti, origin’e kıyasla çok daha düşüktür ama sıfır değildir.
- Cache fill: Her cache miss’de origin’den veri çekilir ve bu ücretlidir.
- Invalidation: Her invalidation isteği ücretlidir,
/*yaparken dikkatli olun. - SSL sertifikası: Google-managed ücretsizdir, ama third-party sertifika kullanırsanız ücret ödeyebilirsiniz.
Maliyeti düşürmek için:
- Versiyonlanmış dosya adları kullanın (
app.v2.1.jsgibi) ve invalidation yerine yeni URL’ler açın Cache-Control: immutableheader’ı ekleyin değişmeyecek dosyalara- Küçük dosyaları birleştirin (bundle edin), her biri ayrı bir cache entry oluşturur
- Lifecycle policy ile eski bucket objelerini temizleyin
Sonuç
Cloud CDN, GCP ekosisteminde hem kurulumu hem de yönetimi görece kolay bir hizmet. HTTP Load Balancer üzerine oturduğu için başlangıçta biraz altyapı kurmanız gerekiyor ama bu zahmet, elde ettiğiniz performans ve ölçeklenebilirlik kazanımları düşünüldüğünde son derece mantıklı.
Özetlemek gerekirse kritik noktalara bir bakalım: backend bucket ya da backend service oluştururken --enable-cdn flag’ini eklemeyi unutmayın. Cache mode seçiminizi yükünüzün yapısına göre yapın; statik dosyalar için CACHE_ALL_STATIC, dinamik API’ler için USE_ORIGIN_HEADERS genellikle iyi bir başlangıç noktasıdır. Cache hit oranınızı düzenli izleyin ve düşük çıkıyorsa Vary header’larını ve TTL ayarlarınızı gözden geçirin. Production’a geçmeden önce Cloud Armor ile en azından temel rate limiting ve coğrafi kısıtlamaları ekleyin.
Son olarak, tüm altyapıyı Terraform veya benzeri bir IaC aracıyla yönetin. Manuel yapılandırmalar zamanla kaybolur, Terraform state’i her zaman yerinde durur.
