AWS Fargate Production Pattern'leri: Maliyet, İzleme, Blue-Green
Production workload'ları çalıştırırken öğrenilen gelişmiş Fargate pattern'leri. Maliyet optimizasyonundan stateful container'lara, dokümantasyonun size söylemeyecekleri.
Fargate 101’de temelleri ele aldık. Aşağıdaki pattern’ler, o temelden sonra bozulan şeylerden geliyor: fatura, Fargate’in sizden sakladığı altyapı katmanı ve geri dönüş yolu olması gereken deployment’lar. Sırasıyla maliyet optimizasyonu, stateful container’lar, monitoring ve blue-green deployment.
Maliyet Optimizasyonu#
Fargate’in aynı compute için EC2’den daha pahalı olduğunu söylemiştik. Bu farkın büyük kısmını dört kaldıraç kapatır: Spot kapasite, right-sizing, ARM ve Savings Plans.
Kesintiye Dayanıklı İşler için Fargate Spot#
Fargate Spot %70’e varan tasarruf sağlar; karşılığında AWS container’larınızı 2 dakikalık uyarıyla sonlandırabilir. Kulağa riskli gelse de, doğru kurgulandığında birçok workload için sorunsuz çalışır.
Karma capacity provider stratejisi bu riski sınırlar:
resource "aws_ecs_service" "batch_processor" {
name = "batch-processor"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.batch.arn
capacity_provider_strategy {
capacity_provider = "FARGATE_SPOT"
weight = 4
base = 0
}
capacity_provider_strategy {
capacity_provider = "FARGATE"
weight = 1
base = 2 # Her zaman 2'sini normal Fargate'te tut
}
desired_count = 10
}
Baseline’ın üzerindeki her beş task’tan dördü Spot’a düşer. desired_count = 10 ve base = 2 ile bu, kabaca 6 task Spot’ta ve 4 task normal Fargate’te demek; yani tüm Spot kapasitesi geri alınsa bile servis ayakta kalır. Bu pattern özellikle şunlar için uygundur:
- Batch işleme job’ları
- Development ve staging ortamları
- Restart’ı kaldırabilen async worker’lar
- CI/CD runner’ları
Kritik bir ders: Her zaman Spot kesintileri için CloudWatch alarm’ları kurun. Kesinti oranları arttığında, trafiği geçici olarak normal Fargate’e kaydırın:
// Spot kesintilerini ele alan Lambda fonksiyonu
import { ECSClient, PutClusterCapacityProvidersCommand } from "@aws-sdk/client-ecs";
export const handleSpotInterruption = async (event: any) => {
const ecs = new ECSClient({ region: process.env.AWS_REGION });
// Geçici olarak normal Fargate ağırlığını artır
const command = new PutClusterCapacityProvidersCommand({
cluster: 'production',
capacityProviders: ['FARGATE', 'FARGATE_SPOT'],
defaultCapacityProviderStrategy: [
{ capacityProvider: 'FARGATE', weight: 10, base: 5 },
{ capacityProvider: 'FARGATE_SPOT', weight: 1, base: 0 }
]
});
await ecs.send(command);
// 30 dakika sonra geri almak için timer ayarla
await scheduleReversion();
};
Doğru Boyutlandırma: Dengeyi Bulmak#
Birçok ekip OOM kill’lerden kaçınmak için Fargate task’larını fazla provision’lar. İşte doğru kaynak tahsisi için sistematik bir yaklaşım:
-
Büyük başla, ölç, sonra küçült
# Önce cömert kaynaklarla deploy et: CPU 1024, Memory 2048 # Bir hafta sonra, gerçek kullanımı kontrol et aws cloudwatch get-metric-statistics \ --namespace ECS/ContainerInsights \ --metric-name MemoryUtilized \ --dimensions Name=ServiceName,Value=my-service \ --statistics Average,Maximum \ --start-time 2024-01-01T00:00:00Z \ --end-time 2024-01-08T00:00:00Z \ --period 3600 -
%80 kuralını kullan: %100 değil, peak kullanımın %80’i için boyutlandır. O %20 buffer spike’ları halleder.
-
Farklı ortamlar için farklı boyutlar:
locals { task_sizes = { production = { cpu = "512" memory = "1024" } staging = { cpu = "256" memory = "512" } development = { cpu = "256" memory = "512" } } } resource "aws_ecs_task_definition" "app" { cpu = local.task_sizes[var.environment].cpu memory = local.task_sizes[var.environment].memory # ... }
ARM + Savings Plans: Çifte İndirim#
AWS Graviton (ARM) işlemciler task başına %20 daha ucuz ve genelde daha hızlı. Savings Plans ile birleştirin, %20 daha indirim:
# Multi-arch Dockerfile
FROM --platform=$BUILDPLATFORM node:18-alpine AS builder
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "Building on $BUILDPLATFORM for $TARGETPLATFORM"
# Build adımlarınız burada...
FROM node:18-alpine
COPY --from=builder /app /app
CMD ["node", "index.js"]
Her iki mimari için build edin:
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag myapp:latest \
--push .
Sonra task definition’ınızda:
{
"runtimePlatform": {
"cpuArchitecture": "ARM64",
"operatingSystemFamily": "LINUX"
}
}
Not: Fargate ARM task’larını Graviton2 üzerinde çalıştırır; bu da çoğu workload’ın fiyat/performans ihtiyacını karşılar.
Node.js servisleri için geçiş genelde bir rebuild ve task definition değişikliğinden ibaret; tasarruf da bu %20’lik fiyat farkını ve workload’ın kazandığı throughput’u takip eder. Uyumluluk sorunları x86’ya özel JNI kütüphaneleri kullanan eski Java uygulamalarında yoğunlaşır; modern imajların çoğu değişiklik gerektirmeden geçer.
Stateful Container’larla Çalışmak#
Genel kanı container’ların stateless olması gerektiği yönünde ve bu çoğunlukla doğru bir tavsiye. Yine de kalıcı state’e ihtiyaç duyduğunuz durumlar var; EFS bu noktada hem işinizi görür hem başınızı ağrıtır.
EFS: İyi, Kötü ve Çirkin#
Fargate ile EFS kurulumu:
resource "aws_efs_file_system" "shared" {
creation_token = "shared-storage"
performance_mode = "generalPurpose" # veya daha fazla operasyon için "maxIO"
throughput_mode = "bursting" # veya tutarlı performans için "provisioned"
lifecycle_policy {
transition_to_ia = "AFTER_30_DAYS" # Soğuk veride tasarruf
}
}
resource "aws_ecs_task_definition" "app" {
# ... diğer konfigürasyon ...
volume {
name = "shared-storage"
efs_volume_configuration {
file_system_id = aws_efs_file_system.shared.id
root_directory = "/"
transit_encryption = "ENABLED"
transit_encryption_port = 2999
authorization_config {
access_point_id = aws_efs_access_point.app.id
iam = "ENABLED"
}
}
}
container_definitions = jsonencode([{
name = "app"
# ...
mountPoints = [{
sourceVolume = "shared-storage"
containerPath = "/data"
}]
}])
}
Tipik performans karakteristikleri:
- EFS gecikmesi: Operasyona göre 0.25-10ms (okuma yazmadan hızlıdır; yerel SSD ~0.1ms)
- Throughput: 100MB/s’ye burst, general purpose modda sürdürülen ~10MB/s
- Maliyet: Yaklaşık $0.30/GB/ay (EBS’te $0.10)
- Not: Ocak 2024 itibarıyla Fargate, daha hızlı kalıcı depolama gerektiğinde EBS volume desteği de sunuyor
EFS nerede işe yarar:
- Birden fazla container’ın erişmesi gereken paylaşılan konfigürasyon dosyaları
- Container’lar arası erişilebilir olması gereken kullanıcı yüklemeleri
- Build cache’leri (kilitleme kısmı zor olabilir)
- Dosya sistemine sıkı bağımlılığı olan eski uygulamalar
Nerede alternatife yönelmeli:
- Veritabanı depolama (RDS veya yönetilen veritabanları daha iyi çalışır)
- Yüksek frekanslı yazma işlemleri
- Geçici dosyalar (container’ın ephemeral storage’ını kullanın)
- Cache katmanları (ElastiCache kullanın)
Session Affinity Pattern’i#
Bazen sticky session’lara ihtiyacınız olur. Fargate ile nasıl yapılır:
resource "aws_lb_target_group" "app" {
name = "app-tg"
port = 80
protocol = "HTTP"
vpc_id = aws_vpc.main.id
target_type = "ip"
stickiness {
type = "app_cookie"
cookie_duration = 86400
cookie_name = "FARGATE_SESSION"
}
health_check {
enabled = true
path = "/health"
matcher = "200"
}
}
Ancak sticky sessions ve auto-scaling iyi anlaşmaz. Task’lar beklenmedik şekilde sonlandığında, o session’lar kaybolur. Daha iyi bir yaklaşım:
- Session verisini ElastiCache Redis’te sakla
- Sunucu session’ları yerine JWT token’ları kullan
- Deployment sırasında session kaybını zarif karşılayacak şekilde tasarla
Fargate Workload’larını İzleme#
Fargate’in altyapıya görünürlüğü azaltması debugging’i zorlaştırır. İşte etkili bir monitoring yaklaşımı:
Fargate Gözlemlenebilirliğinin Üç Direği#
-
CloudWatch Container Insights (Temeller)
aws ecs put-account-setting \ --name containerInsights \ --value enabledBu size CPU, bellek, network ve disk metriklerini verir. Temeller için iyi ama application-level şeyleri kaçırır.
-
Distributed Tracing için X-Ray (Bağlantılar)
// Node.js uygulamanıza ekleyin const AWSXRay = require('aws-xray-sdk-core'); const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3'); // Client'ı bir kez sarın; gönderdiği her komut trace edilir const s3 = AWSXRay.captureAWSv3Client(new S3Client({})); await s3.send(new GetObjectCommand({ Bucket: 'my-bucket', Key: 'file.txt' })); -
StatsD ile Custom Metrikler (Detaylar)
// StatsD için sidecar container çalıştırın const taskDef = { containerDefinitions: [ { name: "app", // uygulama config'iniz }, { name: "datadog-agent", image: "datadog/agent:latest", environment: [ { name: "DD_API_KEY", value: process.env.DD_API_KEY }, { name: "ECS_FARGATE", value: "true" } ] } ] };
ECS Exec ile Debug#
SSH yapabileceğiniz bir host yok, dolayısıyla içeri girmenin tek yolu ECS Exec. İçeri girdiğinizde ihtiyaç duyacağınız araçları imaja önceden koymak işinizi kolaylaştırır:
# Dockerfile'ınıza bunu ekleyin (netstat net-tools'ta, ps procps'te gelir)
RUN apk add --no-cache \
curl \
net-tools \
procps \
htop \
strace \
tcpdump
# Task definition'da ECS Exec'i etkinleştirin
aws ecs update-service \
--cluster production \
--service my-service \
--enable-execute-command
# Çalışan bir task'ta shell aç
aws ecs execute-command \
--cluster production \
--task abc123 \
--container app \
--interactive \
--command "/bin/sh"
# Container içinde:
> netstat -tulpn # Neyin dinlediğini kontrol et
> ps aux # Tüm process'leri gör
> strace -p 1 # System call'ları trace et
> tcpdump -i any # Network trafiğini izle
Blue-Green Deployment’lar: Güvenli Yol#
Fargate ve CodeDeploy birlikte, otomatik geri dönüş yolu olan zero-downtime deployment sağlar. İşi yapan deployment group şöyle:
resource "aws_codedeploy_deployment_group" "app" {
app_name = aws_codedeploy_app.app.name
deployment_group_name = "production"
deployment_config_name = "CodeDeployDefault.ECSLinear10PercentEvery1Minutes"
deployment_style {
deployment_option = "WITH_TRAFFIC_CONTROL"
deployment_type = "BLUE_GREEN"
}
auto_rollback_configuration {
enabled = true
events = ["DEPLOYMENT_FAILURE", "DEPLOYMENT_STOP_ON_ALARM"]
}
blue_green_deployment_config {
terminate_blue_instances_on_deployment_success {
action = "TERMINATE"
termination_wait_time_in_minutes = 5
}
deployment_ready_option {
action_on_timeout = "CONTINUE_DEPLOYMENT"
}
}
ecs_service {
cluster_name = aws_ecs_cluster.main.name
service_name = aws_ecs_service.app.name
}
load_balancer_info {
target_group_pair_info {
prod_traffic_route {
listener_arns = [aws_lb_listener.prod.arn]
}
target_group { name = aws_lb_target_group.blue.name }
target_group { name = aws_lb_target_group.green.name }
}
}
}
Kopyalanan örneklerin çoğunda green_fleet_provisioning_option geçer, ama o blok yalnızca EC2 ve on-premises deployment’lar için geçerli. ECS tarafında green task set’i CodeDeploy kendisi oluşturur; sizden beklediği şey target group çiftidir.
Asıl işe yarayan kısım, CloudWatch alarm’ında otomatik rollback:
const errorRateAlarm = new cloudwatch.Alarm(this, 'ErrorRate', {
metric: new cloudwatch.Metric({
namespace: 'MyApp',
metricName: 'Errors',
statistic: 'Sum'
}),
threshold: 10,
evaluationPeriods: 2
});
// Deployment group'a bağla
deploymentGroup.addAlarm(errorRateAlarm);
Multi-Region Fargate#
İkinci bir region’da Fargate ayağa kaldırmak kolay; asıl zor olan ikisini senkron tutmak. Emek de veri tutarlılığı, failover testi ve maliyete (her region ayrı faturalanır) gidiyor. Sağlam duran yapı şöyle:
Dikkat edilmesi gereken tuzaklar:
- Region başına environment variable’lar: Endpoint’leri hardcode etmeyin; her region kendi RDS, S3 ve servis endpoint’lerine sahip olmalı.
- S3 bucket isimleri global olarak benzersiz olmalı: Region veya account suffix ekleyin.
- Cross-region gecikme: Region çiftine göre 80-150ms; transatlantik hatlar bu aralığın alt ucunda kalır.
- Failover anında değil: Route 53 health check’lerinin devreye girmesi 30-60 saniye alır. Bu süreyi disaster recovery planınıza yazın.
Production Fargate için Temel Pattern’ler#
Sidecar Pattern’i#
{
"containerDefinitions": [
{
"name": "app",
"dependsOn": [{
"containerName": "envoy",
"condition": "HEALTHY"
}]
},
{
"name": "envoy",
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:9901/ready || exit 1"]
}
}
]
}
Init Container Pattern’i (Bir Nevi)#
Fargate’in gerçek init container’ları yok, ama taklit edebilirsiniz:
# Entrypoint script'inizde
#!/bin/sh
echo "Initialization çalıştırılıyor..."
/app/init-db.sh
if [ $? -ne 0 ]; then
echo "Init başarısız, çıkılıyor"
exit 1
fi
echo "Ana uygulama başlatılıyor..."
exec node index.js
Circuit Breaker Pattern’i#
Harici servis çağrılarını circuit breaker ile sarın. Timeout ve retry ile birlikte, hata veren tek bir bağımlılığın task’ın geri kalanını da aşağı çekmesini engeller.
class FargateCircuitBreaker {
private failures = 0;
private lastFailTime = 0;
private readonly threshold = 5;
private readonly timeout = 60000; // 1 dakika
async call<T>(fn: () => Promise<T>): Promise<T> {
if (this.isOpen()) {
throw new Error('Circuit breaker açık');
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
private isOpen(): boolean {
return this.failures >= this.threshold &&
Date.now() - this.lastFailTime < this.timeout;
}
private onSuccess(): void {
this.failures = 0;
}
private onFailure(): void {
this.failures++;
this.lastFailTime = Date.now();
}
}
Bu pattern’ler, sürekli çalışan ve faturada görünen servislerde karmaşıklığını hak eder. Kısa ömürlü bir job’da ya da hiçbir zaman birkaç task’ı geçmeyen bir serviste, normal kapasitede cömert boyutlandırılmış düz Fargate’i işletmek yukarıdaki mekanizmaların hepsinden ucuza gelir. Kesintiye dayanıklı işlerde Spot ve her yerde right-sizing ile başlayın; EFS, blue-green veya ikinci bir region’ı ancak somut bir gereksinim zorladığında ekleyin.
Kaynaklar#
- Optimizing Amazon ECS service auto scaling (yeni sekmede açılır) - Aşırı kaynak tahsisi yapmadan trafik artışlarını karşılamak için ECS Hizmet Otomatik Ölçekleme yapılandırması en iyi uygulamaları.
- Use historical patterns to scale Amazon ECS services with predictive scaling (yeni sekmede açılır) - Fargate’te beklenen trafik artışından önce görevleri ölçeklendiren tahmine dayalı ölçekleme.
- Fargate security considerations for Amazon ECS (yeni sekmede açılır) - Görev izolasyonu, IAM görev rolleri ve gizli bilgi yönetimi dahil güvenlik sertleştirme rehberi.
- Network security best practices for Amazon ECS (yeni sekmede açılır) - Fargate iş yükleri için ağ segmentasyonu, güvenlik grubu kuralları ve VPC Flow Logs kullanımı.
- Amazon ECS service quotas and API throttling limits (yeni sekmede açılır) - Yüksek görev sayılarında ölçekleme davranışını etkileyen hizmet kotaları ve limit artırma talepleri.
- Run message-driven workloads at scale by using AWS Fargate (yeni sekmede açılır) - SQS tabanlı Fargate görev otomatik ölçekleme için AWS Prescriptive Guidance çözüm deseni.
- Theoretical cost optimization by Amazon ECS launch type: Fargate vs EC2 (yeni sekmede açılır) - Farklı kullanım oranlarında Fargate’in EC2’ya göre ne zaman daha uygun maliyetli olduğunu inceleyen AWS Containers blog analizi.
AWS Fargate Derinlemesine Serisi
AWS Fargate'e temellerden production'a tam rehber. Gerçek dünya deneyimleri ile serverless container'ları, maliyet optimizasyonu, debugging tekniklerini ve Infrastructure-as-Code deployment pattern'lerini öğrenin.
Bu serideki tüm yazılar
İlgili yazılar
AWS Fargate'e pratik bir rehber: task definition, awsvpc network modu, maliyet dengesi ve serverless container'ların ne zaman mantıklı olduğu.
aws · fargate · ecs +3
Global uygulamalar için AWS edge computing çözümlerini seçme ve uygulama üzerine pratik örnekler ve maliyet optimizasyonu stratejileri içeren kapsamlı teknik rehber.
aws · cloudfront · lambda +6
Secrets Manager ve Parameter Store'u karşılaştıran teknik rehber: hangi servisi ne zaman seçmeli ve production implementation pattern'leri.
aws · secrets-management · security +7
Yeşil dashboard'ların gizlediği Fargate arızaları: ENI kotasının tükenmesi, subnet route sorunları, memory leak'ler ve her birini bulan kontroller.
aws · fargate · debugging +4
Fargate'i farklı IaC araçlarıyla nasıl etkin şekilde deploy edersiniz. Pratik pattern'ler, yaygın tuzaklar ve her yaklaşım için en iyi çalışan yöntemler.
aws · fargate · aws-cdk +4