AWS Fargate Deploy Etmek: CDK vs Terraform vs SAM
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.
Fargate servislerini CDK, Terraform veya SAM ile deploy etmek çalışan bir altyapı üretir; ancak yanlış araç seçimi her yeni servisle katlanarak büyüyen bir bakım yükü yaratır. Yalnızca AWS üzerinde yaşayacak yeni bir servis için varsayılan CDK’dır: üst düzey construct’ları düzinelerce CloudFormation kaynağını birkaç satıra indirir. Terraform’a geçmek, aynı değişim yüzeyini birden fazla ekip paylaştığında ya da ikinci bir bulut ihtimali gerçekçiyse anlam kazanır. SAM ise ancak Fargate, Lambda’nın yanında küçük bir ayrıntı kaldığında uygundur.
Aradaki fark ilk deployment’ta pek görünmez. Bir yıl sonra görünür: bir değişiklik nasıl inceleniyor, drift nasıl fark ediliyor ve her yeni servis kaç satır koda mal oluyor.
Fargate için IaC Araç Karşılaştırması#
CloudFormation - Temel
# Verbose ama kapsamlı
Resources:
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: my-app
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
Cpu: '256'
Memory: '512'
# Detaylı konfigürasyon gerektirir
Terraform - Endüstri Standardı
# Deklaratif ve açık
resource "aws_ecs_task_definition" "app" {
family = "my-app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "256"
memory = "512"
# Okunabilirlik ve kontrol arasında iyi denge
}
CDK - Programlama Yaklaşımı
// Programlama yapılarıyla high-level soyutlamalar
const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDef', {
memoryLimitMiB: 512,
cpu: 256,
});
Üç snippet de aynı task definition’ı farklı soyutlama seviyelerinde tanımlıyor.
CDK ile Fargate Deploy Etmek#
AWS CDK, programatik kontrol ve üst düzey soyutlama istediğinizde Fargate deployment’larında öne çıkar.
Fargate için CDK Avantajları#
import * as cdk from 'aws-cdk-lib';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsPatterns from 'aws-cdk-lib/aws-ecs-patterns';
export class FargateStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Bu tek construct şunları yaratıyor:
// - VPC, Subnet'ler, NAT Gateway'ler
// - ECS Cluster
// - Fargate Service
// - Application Load Balancer
// - Task Definition
// - Security Group'lar
// - CloudWatch Logs
const fargateService = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', {
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry('nginx'),
containerPort: 80,
environment: {
NODE_ENV: 'production',
API_URL: 'https://api.example.com'
}
},
desiredCount: 3,
domainName: 'app.example.com',
domainZone: hostedZone,
certificate: certificate,
});
// Auto-scaling ekle
const scaling = fargateService.service.autoScaleTaskCount({
maxCapacity: 10,
minCapacity: 2,
});
scaling.scaleOnCpuUtilization('CpuScaling', {
targetUtilizationPercent: 50,
});
// CloudWatch alarm'ları ekle
new cloudwatch.Alarm(this, 'HighMemory', {
metric: fargateService.service.metricMemoryUtilization(),
threshold: 80,
evaluationPeriods: 2,
});
}
}
Bu CDK construct’ının yarattıkları:
- ~300 satır CloudFormation
- 15+ AWS kaynağı
- Tüm IAM role ve policy’ler
- Düzgün security group kuralları
- CloudWatch log group’ları
Fargate-Spesifik CDK Pattern’leri#
1. Ortam Varyasyonlarıyla Servis Template’leri
interface FargateServiceProps {
serviceName: string;
image: string;
environment: 'dev' | 'staging' | 'prod';
port?: number;
}
class FargateService extends Construct {
constructor(scope: Construct, id: string, props: FargateServiceProps) {
super(scope, id);
// Ortam-spesifik boyutlandırma
const configs = {
dev: { cpu: 256, memory: 512, desiredCount: 1 },
staging: { cpu: 512, memory: 1024, desiredCount: 2 },
prod: { cpu: 1024, memory: 2048, desiredCount: 5 }
};
const config = configs[props.environment];
const service = new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', {
taskImageOptions: {
image: ecs.ContainerImage.fromRegistry(props.image),
containerPort: props.port || 80,
},
cpu: config.cpu,
memoryLimitMiB: config.memory,
desiredCount: config.desiredCount,
// ALB, VPC, subnet'ler, security group'ları otomatik yapılandır
});
// Fargate-spesifik monitoring ekle
this.addFargateMonitoring(service);
}
private addFargateMonitoring(service: ecsPatterns.ApplicationLoadBalancedFargateService) {
// Memory utilization alarmı
new cloudwatch.Alarm(this, 'MemoryAlarm', {
metric: service.service.metricMemoryUtilization(),
threshold: 80,
evaluationPeriods: 2,
});
// Çalışan task sayısı alarmı (cluster'da Container Insights gerekir)
new cloudwatch.Alarm(this, 'TaskCountAlarm', {
metric: new cloudwatch.Metric({
namespace: 'ECS/ContainerInsights',
metricName: 'RunningTaskCount',
dimensionsMap: {
ClusterName: service.cluster.clusterName,
ServiceName: service.service.serviceName,
},
}),
threshold: 1,
evaluationPeriods: 2,
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
});
}
}
2. CDK ile Fargate Spot İşleme
// Önce cluster üzerinde capacity provider'ları etkinleştirin:
// cluster.enableFargateCapacityProviders();
const service = new ecs.FargateService(this, 'Service', {
cluster,
taskDefinition,
capacityProviderStrategies: [
{
capacityProvider: 'FARGATE_SPOT',
weight: 4,
base: 0,
},
{
capacityProvider: 'FARGATE',
weight: 1,
base: 2, // Her zaman 2'sini normal Fargate'te tut
}
],
});
Fargate için CDK Tuzakları#
Sorun: ENI Limitleri
// awsvpc modundaki her task bir network interface tutar ve
// bölge başına kota 5000'den başlar. AWS bunun için metrik
// yayınlamaz; zamanlanmış bir job ile kendi metriğinizi basın.
const eniUsageMetric = new cloudwatch.Metric({
namespace: 'Custom/VPC',
metricName: 'ENIsInUse',
});
new cloudwatch.Alarm(this, 'ENIUsage', {
metric: eniUsageMetric,
threshold: 4500, // Default 5000 limitinin %90'ı
});
Terraform ile Fargate Deploy Etmek#
Terraform mükemmel state yönetimiyle açık, öngörülebilir Fargate deploymentları sağlar. Fargate altyapınızı etkili şekilde nasıl yapılandıracağınız:
Terraform Fargate Temelleri#
resource "aws_ecs_cluster" "main" {
name = "production"
setting {
name = "containerInsights"
value = "enabled"
}
}
resource "aws_ecs_task_definition" "app" {
family = "my-app"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
cpu = "512"
memory = "1024"
execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
task_role_arn = aws_iam_role.ecs_task_role.arn
container_definitions = jsonencode([{
name = "app"
image = "nginx:latest"
portMappings = [{
containerPort = 80
protocol = "tcp"
}]
logConfiguration = {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.app.name
awslogs-region = var.aws_region
awslogs-stream-prefix = "ecs"
}
}
environment = [
{
name = "NODE_ENV"
value = "production"
}
]
}])
}
resource "aws_ecs_service" "app" {
name = "my-app-service"
cluster = aws_ecs_cluster.main.id
task_definition = aws_ecs_task_definition.app.arn
desired_count = var.app_count
launch_type = "FARGATE"
enable_execute_command = true
network_configuration {
security_groups = [aws_security_group.ecs_tasks.id]
subnets = aws_subnet.private[*].id
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_alb_target_group.app.arn
container_name = "app"
container_port = 80
}
depends_on = [aws_alb_listener.front_end]
}
Yeniden Kullanılabilir Module Pattern’i#
# modules/fargate-service/main.tf
variable "service_name" {}
variable "image" {}
variable "cpu" { default = "256" }
variable "memory" { default = "512" }
variable "desired_count" { default = 2 }
# ... 200 satır tekrar kullanılabilir Terraform ...
output "service_url" {
value = aws_alb.main.dns_name
}
# Ana konfigürasyonunuzda
module "api_service" {
source = "./modules/fargate-service"
service_name = "api"
image = "myapp/api:latest"
cpu = "512"
memory = "1024"
desired_count = 3
}
module "worker_service" {
source = "./modules/fargate-service"
service_name = "worker"
image = "myapp/worker:latest"
cpu = "256"
memory = "512"
desired_count = 5
}
Temel State Yönetimi#
Düzgün state yönetimi Terraform deploymentları için kritiktir. Eski state dosyaları istenmeyen kaynak yok etmeye yol açabilir.
# Plan output'unu her zaman dikkatli inceleyin
$ terraform plan
Terraform will perform the following actions:
# aws_ecs_service.app will be destroyed
- resource "aws_ecs_service" "app" {
- name = "production-api" -> null
# ... 50 kaynak yok edilecek
}
Plan: 0 to add, 0 to change, 52 to destroy.
# Production'da asla auto-approve kullanmayın
$ terraform apply # Manuel olarak inceleyin ve onaylayın
Gerekli: Ekip ortamları için her zaman remote state kullanın.
terraform {
backend "s3" {
bucket = "terraform-state-prod"
key = "fargate/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
encrypt = true
}
}
SAM: Lambda-First Yaklaşım#
AWS SAM (Serverless Application Model) Lambda için harika, ama Fargate için? Çivi çakmak için tornavida kullanmak gibi.
# template.yaml
Transform: AWS::Serverless-2016-10-31
Resources:
FargateCluster:
Type: AWS::ECS::Cluster
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
RequiresCompatibilities:
- FARGATE
NetworkMode: awsvpc
Cpu: '256'
Memory: '512'
# CloudFormation verbosity'sine geri dönüş
# SAM Lambda'yı Fargate ile karıştırdığınızda parlıyor
ProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: python3.12
Events:
ECSTask:
Type: CloudWatchEvent
Properties:
Pattern:
source:
- aws.ecs
detail-type:
- ECS Task State Change
SAM Fargate için ne zaman mantıklı:
- Ağırlıklı olarak Lambda tabanlısınız, yanında az miktarda Fargate var
- Step Functions orchestration’a ihtiyacınız var
- Diğer servisler için zaten SAM’e yatırım yapmışsınız
Ne zaman uygun değil:
- Fargate birincil compute’unuz
- Karmaşık networking’e ihtiyacınız var
- Programlama dili özelliklerini istiyorsunuz
Migration Stratejileri#
CloudFormation’dan Terraform Migration’ı#
Mevcut altyapıyı migrate etmek dikkatli planlama gerektirir. Bu zorlukları göz önünde bulundurun:
Migration Süreci:
- Mevcut kaynakları export et
- Eşdeğer Terraform yaz
- Kaynakları dikkatli şekilde import et
- CloudFormation’ı kaldırmadan önce doğrula
Yaygın Sorunlar:
# Import ID'si servis adı değil, cluster-adı/servis-adı biçimindedir
$ terraform import aws_ecs_service.app production/production-app-service
Import successful!
# Import edilen state, config'inizde yazmayan tüm AWS varsayılanlarını taşır
$ terraform plan
Plan: 0 to add, 12 to change, 3 to destroy.
# State'in zaten izlediği bir adresi tekrar import etmek
$ terraform import aws_ecs_cluster.main production
Error: Resource already managed by Terraform
En İyi Uygulamalar:
- Kritik olmayan kaynaklarla başla
- Hedeflenen apply’lar kullan:
terraform apply -target=resource - Geçiş sırasında paralel stack’ler çalıştır
- Kaynak keşfi ve import için script’ler
Terraform’dan CDK Migration’ı#
CDK migration’ları import sınırlarıyla karşılaşır:
class MigrationStack extends cdk.Stack {
constructor(scope: Construct, id: string) {
super(scope, id);
// Sınırlı import desteği
const cluster = ecs.Cluster.fromClusterArn(
this,
'ImportedCluster',
'arn:aws:ecs:us-east-1:123456789:cluster/production'
);
// CDK import sınırları:
// - Task definition'lar yeniden yaratım gerektirir
// - Karmaşık servis konfigürasyonları
// - Service discovery entegrasyonu
}
}
Migration Stratejisi: Karmaşık geçişler için her iki aracı da geçici olarak çalıştırmayı düşünün.
Karar Matrisi#
CDK Tercih Koşulları#
- Ekibiniz TypeScript veya Python’u iyi biliyor
- Sıfırdan başlıyorsunuz; import edilecek legacy stack yok
- High-level abstraction’lar istiyorsunuz
- AWS’ye all-in’siniz
- Yeni AWS özelliklerini üçüncü parti provider’lar yetişmeden kullanmak istiyorsunuz
Terraform Tercih Koşulları#
- Multi-cloud potansiyeline ihtiyacınız var
- Ekibiniz declarative syntax tercih ediyor
- Mevcut Terraform module’leriniz var
- Stabilite en yeni özelliklerden daha önemli
- Geniş provider ve module ekosistemine değer veriyorsunuz
SAM Tercih Koşulları#
- Mimariniz Lambda-first
- Step Functions’a ihtiyacınız var
- Minimal tooling istiyorsunuz
- Fargate kullanımınız marjinal
CloudFormation Tercih Koşulları#
- Deployment yolunu AWS Support’un debug etmesine ihtiyacınız var
- AWS Service Catalog üzerinden yayınlıyorsunuz
- Kurumsal bir zorunluluk alternatifleri kapatıyor
Her Yerde İşe Yarayan Pattern’ler#
Üç pattern araçtan bağımsız olarak işe yarar:
1. Environment Abstraction’ı#
// CDK
interface EnvironmentConfig {
cpu: number;
memory: number;
desiredCount: number;
environment: Record<string, string>;
}
const configs: Record<string, EnvironmentConfig> = {
dev: { cpu: 256, memory: 512, desiredCount: 1 },
staging: { cpu: 512, memory: 1024, desiredCount: 2 },
prod: { cpu: 1024, memory: 2048, desiredCount: 5 }
};
# Terraform
locals {
env_config = {
dev = { cpu = 256, memory = 512, count = 1 }
staging = { cpu = 512, memory = 1024, count = 2 }
prod = { cpu = 1024, memory = 2048, count = 5 }
}
config = local.env_config[var.environment]
}
2. Service Template Pattern’i#
Kod kopyalamak yerine, template’ler yaratın:
// CDK: Base service construct
export class BaseEcsService extends Construct {
public readonly service: ecs.FargateService;
constructor(scope: Construct, id: string, props: BaseEcsServiceProps) {
super(scope, id);
// 100 satır boilerplate
this.service = new ecs.FargateService(this, 'Service', {
// Ortak konfigürasyon
});
// Standart alarm'lar
this.setupAlarms();
// Standart dashboard
this.setupDashboard();
}
}
// Kullanım
new BaseEcsService(this, 'ApiService', {
image: 'api:latest',
port: 3000,
cpu: 512
});
3. GitOps Pipeline#
# .github/workflows/deploy.yml
name: Deploy Infrastructure
on:
push:
branches: [main]
paths:
- 'infrastructure/**'
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Terraform Plan
run: |
cd infrastructure
terraform init
terraform plan -out=tfplan
- name: Post Plan to PR
uses: actions/github-script@v7
with:
script: |
// Plan output'u PR comment olarak post et
apply:
needs: plan
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Terraform Apply
run: |
terraform apply tfplan
Her Yaklaşımın Maliyeti#
AWS faturası araç seçimiyle değişmez; dördü de sonunda aynı ECS kaynaklarına dönüşür. Maliyet ekip zamanına biner.
| Tool | Öğrenme eğrisi | Bakım maliyeti | Esneklik | AWS özellik gecikmesi |
|---|---|---|---|---|
| CDK | En dik | Orta | Yüksek | L1 construct’larda yok; L2’ler geriden gelir |
| Terraform | Orta | Düşük | Yüksek | Provider sürümlerine bağlı |
| SAM | En düşük | Düşük | Düşük | Yok |
| CloudFormation | Orta | Yüksek | Orta | Yok |
Asıl maliyet günlük işteki sürtünmede:
- CloudFormation: daha yavaş iterasyon, daha çok debug
- Terraform: öngörülebilir ama uzun soluklu akışlar
- CDK: ekip construct kütüphanesine alıştıktan sonra daha hızlı
Sonuç#
- Yeni projeler: TypeScript ile CDK
- Mevcut projeler: hâlihazırda ne varsa o; ancak mevcut araç somut bir şeyi engelliyorsa migrate edin
- Multi-cloud potansiyeli: Terraform
- Hızlı prototip: SAM
- Raw CloudFormation: yalnızca kurumsal bir zorunluluk başka seçenek bırakmadığında
Servis AWS içinde kaldığı ve tanımların sahibi tek bir ekip olduğu sürece varsayılan CDK’dır. İki durumda varsayılan olmaktan çıkar: altyapı değişikliklerini o ekibin dışındaki kişiler okuyup onaylamak zorunda kaldığında ve yeni bir servisin bir öğleden sonrada katılabileceği bir module kütüphanesi zaten mevcut olduğunda. Her iki durumda da inceleme yüzeyi satır sayısından daha önemlidir.
Kaynaklar#
- Best practices for developing and deploying cloud infrastructure with the AWS CDK (yeni sekmede açılır) - IaC organizasyonu, construct yeniden kullanımı ve ortama göre değişen deployment pipeline’ları için CDK en iyi uygulamaları.
- Best practices for using the AWS CDK in TypeScript to create IaC projects (yeni sekmede açılır) - TypeScript CDK proje yapısı, test pattern’leri ve construct sürüm yönetimi üzerine AWS’nin prescriptive rehberi.
- Learn AWS CDK core concepts - AWS Cloud Development Kit (AWS CDK) v2 (yeni sekmede açılır) - Construct’lar, stack’ler, app’ler, ortamlar ve synth’ten CloudFormation’a dönüşüm sürecinin temel kavramları.
- Architect for AWS Fargate for Amazon ECS (yeni sekmede açılır) - IaC tanımlarının doğru modellemesi gereken Fargate mimari temelleri: task definition’lar, servisler ve networking.
- Amazon ECS task definition parameters for Fargate (yeni sekmede açılır) - Fargate task definition’ları için eksiksiz parametre referansı; geçerli CDK property değerlerinin yetkili kaynağı.
- AWS CDK API Reference (v2) (yeni sekmede açılır) - Fargate IaC’de kullanılan aws-ecs, aws-ecs-patterns ve ilgili construct’lar için tam API referansı.
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
CloudFormation'un 500 kaynak sınırını nested stack, cross-stack referans, SSM Parameter Store ve microstack mimarisiyle aşmayı TypeScript CDK örnekleriyle öğren.
aws-cdk · infrastructure-as-code · aws +2
CDK stack düzeni için yaşam döngüsü testi: bir kaynağın ömrü tek bir dağıtımdan uzunsa kendi uzun ömürlü stack'ine koyun, ona bilinen bir adla erişin.
aws-cdk · infrastructure-as-code · typescript +3
Ölçekte karşılaşacağınız IAM boyut, ekleme ve kota limitleri; ve hepsinden uzak tutan dar kapsamlı politika, izin sınırı ve SCP yapısı.
aws · iam · security +2
AgentCore Runtime üzerinde minimal bir Strands agent'ı CDK ile deploy etme rehberi: parametrize stack, arm64 build, deploy ve invoke, IAM ve Marketplace ön koşulları.
aws-bedrock · ai-agents · aws-cdk +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