Cloudflare R2 ile S3 Uyumlu Nesne Depolama Kullanımı
Bulut depolama maliyetleri son yıllarda ciddi bir sorun haline geldi. AWS S3’ün egress (çıkış bandgenişliği) ücretleri özellikle büyük miktarda veri dışarı çıkarmanız gerektiğinde faturanızı patlatabilir. Cloudflare R2 tam da bu noktada devreye giriyor: sıfır egress ücreti ile S3 uyumlu bir depolama çözümü sunuyor. Eğer S3 API’sine zaten alışkınsanız, R2’ye geçiş düşündüğünüzden çok daha kolay.
Bu yazıda R2’yi sıfırdan kuracağız, AWS CLI ve rclone ile nasıl kullanacağımızı göreceğiz, bucket politikaları ve erişim yönetimini ele alacağız, ardından gerçek dünya senaryolarında nasıl işe yaradığını inceleyeceğiz.
Cloudflare R2 Nedir ve S3’ten Ne Farkı Var?
R2, Cloudflare’in 2022’de genel kullanıma açtığı nesne depolama hizmetidir. S3 API’si ile birebir uyumlu olduğu için mevcut araçlarınızı, kütüphanelerinizi ve iş akışlarınızı büyük ölçüde değiştirmeden kullanabilirsiniz.
Asıl fark ücretlendirme modelinde:
- Egress ücreti yok: R2’den veri çekerken bant genişliği ücreti ödemezsiniz. Bu, özellikle medya dosyaları, yedekleme arşivleri veya sık erişilen büyük dosyalar için muazzam bir tasarruf demek.
- Depolama ücreti: Aylık 10 GB ücretsiz, sonrası GB başına 0.015 dolar.
- İşlem ücreti: Sınıf A işlemleri (yazma) milyonda 4.50 dolar, Sınıf B işlemleri (okuma) milyonda 0.36 dolar. Aylık 1 milyon okuma/yazma ücretsiz.
- Bölge seçimi yok: R2 otomatik olarak kullanıcıya en yakın konuma veri servis eder. Bucket oluştururken bölge belirtmek zorunda değilsiniz, bu hem kolaylık hem de küresel dağıtım açısından avantajlı.
S3 ile tam uyumlu olmayan birkaç nokta da var: object lock, requester-pays gibi bazı gelişmiş özellikler henüz tam destek almıyor. Ama büyük çoğunluğu için bu bir sorun teşkil etmiyor.
Cloudflare R2 Kurulumu ve API Token Oluşturma
Önce Cloudflare dashboard’una gidin ve R2 Object Storage bölümünü açın. Hesabınızda R2’yi etkinleştirmeniz gerekiyor, bu işlem kredi kartı bilgisi istiyor ama ilk kullanımda ücret çıkmıyor.
Bucket oluşturma:
Dashboard üzerinden “Create bucket” diyerek yeni bir bucket oluşturabilirsiniz. İsim olarak DNS uyumlu, küçük harf ve tire içeren bir isim seçin. Örneğin: myapp-assets-prod.
API Token oluşturma:
R2 API token’ları, Cloudflare’in genel API token sisteminden ayrı bir yerden yönetiliyor. R2 sayfasında sağ üstteki “Manage R2 API Tokens” bağlantısına tıklayın.
Token oluştururken şu izinlere dikkat edin:
- Admin Read & Write: Tüm bucket’lara tam erişim
- Object Read & Write: Belirli bucket’lara nesne düzeyinde erişim
- Object Read only: Salt okuma erişimi
Üretim ortamları için her uygulama veya servis için ayrı token oluşturun ve minimum gerekli izni verin. Token oluşturduktan sonra size şu bilgiler gösterilecek:
- Access Key ID
- Secret Access Key
- Endpoint URL (hesap ID’nize özgü, örn:
https://.r2.cloudflarestorage.com)
Bu bilgileri güvenli bir yere kaydedin. Secret Key sadece bir kez gösteriliyor.
AWS CLI ile R2 Kullanımı
AWS CLI, S3 uyumlu herhangi bir endpoint ile çalışabilir. R2 için özel bir endpoint belirtmeniz yeterli.
AWS CLI yapılandırması:
# R2 için özel profil oluştur
aws configure --profile r2
# Sorulacak bilgileri girin:
# AWS Access Key ID: <R2_ACCESS_KEY_ID>
# AWS Secret Access Key: <R2_SECRET_ACCESS_KEY>
# Default region name: auto
# Default output format: json
Sonrasında her komutta --endpoint-url ve --profile parametrelerini kullanmanız gerekiyor:
# Bucket listele
aws s3 ls --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com --profile r2
# Dosya yükle
aws s3 cp ./myfile.tar.gz s3://myapp-assets-prod/
--endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com
--profile r2
# Dizin senkronize et
aws s3 sync ./dist/ s3://myapp-assets-prod/dist/
--endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com
--profile r2
--delete
# Dosya indir
aws s3 cp s3://myapp-assets-prod/backup.tar.gz ./backup.tar.gz
--endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com
--profile r2
Her seferinde --endpoint-url yazmak zahmetli. Bunu kolaylaştırmak için bir bash alias veya fonksiyon oluşturabilirsiniz:
# ~/.bashrc veya ~/.bash_aliases dosyasına ekle
export R2_ENDPOINT="https://<ACCOUNT_ID>.r2.cloudflarestorage.com"
alias r2="aws s3 --endpoint-url $R2_ENDPOINT --profile r2"
alias r2api="aws s3api --endpoint-url $R2_ENDPOINT --profile r2"
# Artık şöyle kullanabilirsiniz:
# r2 ls
# r2 cp dosya.zip s3://mybucket/
# r2api list-objects-v2 --bucket mybucket
rclone ile R2 Entegrasyonu
rclone, R2 gibi S3 uyumlu sistemlerle çalışırken AWS CLI’den çok daha esnek ve güçlü bir araçtır. Özellikle büyük miktarda veri transferi ve senkronizasyon işlemleri için tercih edin.
rclone R2 yapılandırması:
# Interaktif yapılandırma
rclone config
# Adımlar:
# n) New remote
# name> r2-prod
# Storage> s3 (veya numara ile seçin)
# provider> Cloudflare
# env_auth> false
# access_key_id> <R2_ACCESS_KEY_ID>
# secret_access_key> <R2_SECRET_ACCESS_KEY>
# region> auto
# endpoint> https://<ACCOUNT_ID>.r2.cloudflarestorage.com
# Diğer ayarlar için enter ile geçin
Ya da ~/.config/rclone/rclone.conf dosyasını doğrudan düzenleyin:
[r2-prod]
type = s3
provider = Cloudflare
access_key_id = <R2_ACCESS_KEY_ID>
secret_access_key = <R2_SECRET_ACCESS_KEY>
region = auto
endpoint = https://<ACCOUNT_ID>.r2.cloudflarestorage.com
acl = private
rclone temel komutları:
# Bucket içeriğini listele
rclone ls r2-prod:myapp-assets-prod
# Dizin senkronizasyonu (tek yönlü, silme dahil)
rclone sync ./local-backup/ r2-prod:myapp-backups/
--progress
--transfers 20
--checkers 40
--fast-list
# İki R2 bucket arasında kopyalama
rclone copy r2-prod:source-bucket r2-prod:destination-bucket
--progress
--transfers 16
# Büyük dosyaları parça parça yükle (multipart upload)
rclone copy ./large-archive.tar.gz r2-prod:myapp-backups/
--s3-chunk-size 64M
--s3-upload-concurrency 8
--progress
# Uzak bucket'ı mount et (FUSE gerekli)
mkdir -p /mnt/r2-assets
rclone mount r2-prod:myapp-assets-prod /mnt/r2-assets
--daemon
--vfs-cache-mode writes
--vfs-cache-max-size 2G
Bucket Politikaları ve Erişim Yönetimi
R2, S3 benzeri bucket politikalarını destekler. Halka açık okuma erişimi, IP kısıtlamaları veya belirli işlem tiplerini sınırlamak için politika JSON’ları kullanabilirsiniz.
Halka açık okuma politikası:
# bucket-policy.json dosyası oluştur
cat > /tmp/bucket-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myapp-assets-prod/*"
}
]
}
EOF
# Politikayı uygula
aws s3api put-bucket-policy
--bucket myapp-assets-prod
--policy file:///tmp/bucket-policy.json
--endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com
--profile r2
Belirli prefix’e kısıtlı yazma politikası:
cat > /tmp/restricted-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadAll",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::myapp-assets-prod/public/*"
},
{
"Sid": "DenyDeleteAll",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteObject",
"Resource": "arn:aws:s3:::myapp-assets-prod/*"
}
]
}
EOF
R2’nin Custom Domain özelliği de son derece işlevsel. Bucket’ınıza kendi alan adınızı bağlayabilir ve Cloudflare CDN üzerinden servis edebilirsiniz. Dashboard’da R2 > bucket adınız > Settings > Custom Domains bölümünden bu ayarı yapabilirsiniz. Alan adınız Cloudflare’de yönetiliyorsa bu işlem birkaç tıkla tamamlanıyor.
Gerçek Dünya Senaryosu 1: Uygulama Yedeklemelerini R2’ye Taşıma
Bir PostgreSQL veritabanı yedekleme scripti düşünün. Şu anda yedekleri yerel diske yazıyor ve belki bir S3 bucket’ına gönderiyorsunuz. Bunu R2’ye taşımak için şöyle bir script yazabilirsiniz:
#!/bin/bash
# /usr/local/bin/backup-to-r2.sh
set -euo pipefail
# Değişkenler
DB_NAME="myapp_production"
DB_USER="postgres"
BACKUP_DIR="/tmp/pg_backups"
R2_BUCKET="myapp-db-backups"
R2_ENDPOINT="https://<ACCOUNT_ID>.r2.cloudflarestorage.com"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${DATE}.sql.gz"
# Gerekli dizini oluştur
mkdir -p "$BACKUP_DIR"
echo "[$(date)] Yedekleme başlıyor: $DB_NAME"
# PostgreSQL dump al ve sıkıştır
pg_dump -U "$DB_USER" "$DB_NAME" | gzip -9 > "$BACKUP_FILE"
BACKUP_SIZE=$(du -sh "$BACKUP_FILE" | cut -f1)
echo "[$(date)] Yedekleme tamamlandı: $BACKUP_FILE ($BACKUP_SIZE)"
# R2'ye yükle
aws s3 cp "$BACKUP_FILE"
"s3://${R2_BUCKET}/daily/${DATE:0:8}/${DB_NAME}_${DATE}.sql.gz"
--endpoint-url "$R2_ENDPOINT"
--profile r2
--metadata "db-name=${DB_NAME},backup-date=${DATE}"
echo "[$(date)] R2'ye yüklendi"
# Yerel geçici dosyayı sil
rm -f "$BACKUP_FILE"
# R2'deki eski yedekleri temizle (30 günden eski)
CUTOFF_DATE=$(date -d "$RETENTION_DAYS days ago" +%Y%m%d)
echo "[$(date)] $CUTOFF_DATE öncesi yedekler temizleniyor..."
aws s3 ls "s3://${R2_BUCKET}/daily/"
--endpoint-url "$R2_ENDPOINT"
--profile r2 |
awk '{print $2}' |
grep -E '^[0-9]{8}/$' |
sed 's|/$||' |
while read dir_date; do
if [[ "$dir_date" < "$CUTOFF_DATE" ]]; then
echo "[$(date)] Siliniyor: daily/$dir_date/"
aws s3 rm "s3://${R2_BUCKET}/daily/${dir_date}/"
--recursive
--endpoint-url "$R2_ENDPOINT"
--profile r2
fi
done
echo "[$(date)] Yedekleme süreci tamamlandı"
Bu scripti crontab’a ekleyin:
# Her gece 02:00'de çalıştır
0 2 * * * /usr/local/bin/backup-to-r2.sh >> /var/log/r2-backup.log 2>&1
Gerçek Dünya Senaryosu 2: Statik Site Varlıklarını R2’den Servis Etme
Bir web uygulamasının build çıktısını R2’ye deploy edip Cloudflare CDN üzerinden servis etmek son derece yaygın bir kullanım senaryosu. CI/CD pipeline’ınıza şöyle bir adım ekleyebilirsiniz:
#!/bin/bash
# deploy-assets.sh - CI/CD pipeline için
set -euo pipefail
BUILD_DIR="./dist"
R2_BUCKET="myapp-assets-prod"
R2_ENDPOINT="https://<ACCOUNT_ID>.r2.cloudflarestorage.com"
DEPLOY_ENV="${DEPLOY_ENV:-staging}"
echo "=== $DEPLOY_ENV ortamına deploy başlıyor ==="
# Build klasörünün var olduğunu kontrol et
if [[ ! -d "$BUILD_DIR" ]]; then
echo "HATA: Build dizini bulunamadı: $BUILD_DIR"
exit 1
fi
# Cache-Control başlıklarıyla birlikte yükle
# HTML dosyaları için kısa cache süresi
aws s3 sync "$BUILD_DIR" "s3://${R2_BUCKET}/"
--endpoint-url "$R2_ENDPOINT"
--profile r2
--delete
--exclude "*.html"
--cache-control "public, max-age=31536000, immutable"
# HTML dosyaları için cache'siz
aws s3 sync "$BUILD_DIR" "s3://${R2_BUCKET}/"
--endpoint-url "$R2_ENDPOINT"
--profile r2
--exclude "*"
--include "*.html"
--cache-control "no-cache, no-store, must-revalidate"
echo "=== Deploy tamamlandı ==="
# Toplam boyutu raporla
TOTAL_OBJECTS=$(aws s3 ls "s3://${R2_BUCKET}/"
--endpoint-url "$R2_ENDPOINT"
--profile r2
--recursive
--summarize | grep "Total Objects" | awk '{print $3}')
echo "Toplam nesne sayısı: $TOTAL_OBJECTS"
Python SDK ile R2 Kullanımı
Uygulama kodunuzdan R2’ye bağlanmak için boto3 kütüphanesi ideal. S3 ile aynı kod, sadece endpoint ve credentials değişiyor:
import boto3
from botocore.config import Config
# R2 client oluştur
r2_client = boto3.client(
's3',
endpoint_url='https://<ACCOUNT_ID>.r2.cloudflarestorage.com',
aws_access_key_id='<R2_ACCESS_KEY_ID>',
aws_secret_access_key='<R2_SECRET_ACCESS_KEY>',
config=Config(
signature_version='s3v4',
retries={'max_attempts': 3, 'mode': 'adaptive'}
),
region_name='auto'
)
# Presigned URL oluştur (geçici indirme linki)
presigned_url = r2_client.generate_presigned_url(
'get_object',
Params={
'Bucket': 'myapp-assets-prod',
'Key': 'reports/monthly-report-2024-01.pdf'
},
ExpiresIn=3600 # 1 saat geçerli
)
print(f"İndirme linki: {presigned_url}")
# Dosya yükle
def upload_file(local_path: str, bucket: str, key: str, content_type: str = None):
extra_args = {}
if content_type:
extra_args['ContentType'] = content_type
r2_client.upload_file(
local_path,
bucket,
key,
ExtraArgs=extra_args
)
print(f"Yüklendi: {key}")
# Örnek kullanım
upload_file(
'./exports/data-export.csv',
'myapp-assets-prod',
'exports/data-export-2024.csv',
'text/csv'
)
R2’ye Geçişte Dikkat Edilecek Noktalar
Endpoint URL yönetimi: R2 endpoint URL’si hesabınıza özgüdür ve değişmez. Bunu ortam değişkeni olarak tutun, kod içine gömmekten kaçının.
Çok parçalı yükleme sınırları: R2, S3 ile aynı multipart upload limitlerini destekler. 5 GB üzeri dosyalar için multipart upload zorunludur. rclone bunu otomatik hallediyor ama kendi kodunuzu yazıyorsanız buna dikkat edin.
Geçiş stratejisi: S3’ten R2’ye büyük veri taşırken şu yaklaşımı izleyin:
- Önce rclone ile mevcut S3 bucket’ını R2’ye kopyalayın
- Uygulamanızı R2 endpoint’ini kullanacak şekilde güncelleyin
- Bir süre her iki bucket’a da yazın (dual-write)
- S3 bucket’ını okuma yükü kalmayınca kaldırın
CORS yapılandırması: Tarayıcıdan doğrudan R2’ye yükleme yapacaksanız CORS ayarlarını yapmayı unutmayın. Dashboard üzerinden ya da AWS CLI aracılığıyla yapabilirsiniz:
cat > /tmp/cors.json << 'EOF'
{
"CORSRules": [
{
"AllowedOrigins": ["https://myapp.com", "https://www.myapp.com"],
"AllowedMethods": ["GET", "PUT", "POST"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3000
}
]
}
EOF
aws s3api put-bucket-cors
--bucket myapp-assets-prod
--cors-configuration file:///tmp/cors.json
--endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com
--profile r2
Monitoring ve log: R2, Cloudflare dashboard üzerinden temel metrikler sunuyor. Daha detaylı log için R2’nin event notification özelliğini kullanabilir veya uygulama seviyesinde kendi loglama mekanizmanızı kurabilirsiniz. Cloudflare Workers ile R2 event’larını yakalamak da mümkün.
Terraform ile R2 yönetimi: Altyapınızı kod olarak yönetiyorsanız Cloudflare Terraform provider’ı R2 bucket’larını destekliyor. cloudflare_r2_bucket kaynağını kullanarak bucket’larınızı, politikalarınızı ve CORS ayarlarınızı kodla yönetebilirsiniz.
Sonuç
Cloudflare R2, özellikle egress maliyetinin sorun olduğu durumlarda S3’e ciddi bir alternatif sunuyor. Sıfır egress ücreti, S3 API uyumluluğu ve Cloudflare’in global ağıyla entegrasyon bir arada düşününce özellikle medya depolama, yedekleme arşivleri, statik site varlıkları ve kullanıcıya sık sık büyük dosya sunan uygulamalar için son derece cazip bir seçenek.
Geçiş süreci de sanıldığı kadar karmaşık değil. AWS CLI, rclone veya boto3 gibi zaten kullandığınız araçlar minimum konfigürasyon değişikliğiyle R2 ile çalışıyor. Küçük bir pilot bucket ile başlayın, maliyetlerinizi karşılaştırın ve uygun gördüğünüz iş yüklerini aşamalı olarak taşıyın. Büyük hacimli ve sık erişilen veriler için hesaplayacağınız maliyet farkı sizi şaşırtabilir.
