2025-09-04
AWS Fargate 104: CDK, Terraform ve SAM ile Deploy
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 hakkında üç yazıdan sonra (101, 102, 103), “güzel de, bunları AWS Console’da tıklayarak değil de nasıl deploy edeceğim, 2015’te değiliz” diye düşünüyor olabilirsiniz.
Fargate servislerini deploy etmek, ekibiniz ve gereksinimleriniz için doğru Infrastructure as Code (IaC) aracını seçmeyi gerektirir. Her yaklaşım karmaşıklık, bakım yapılabilirlik ve geliştirici deneyiminde farklı trade-off’lar sunar.
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,
});
Her yaklaşımda neyin iyi çalıştığını keşfedelim.
CDK ile Fargate Deploy Etmek
AWS CDK (Cloud Development Kit) altyapıyı TypeScript, Python, Java veya C# ile yazmanıza izin veriyor. CDK, Fargate deploymentları için yüksek seviye soyutlamalar sağlar.
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,
});
}
}
20 satır CDK’nın aslında yarattığı:
- ~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,
});
// Task count alarmı
new cloudwatch.Alarm(this, 'TaskCountAlarm', {
metric: service.service.metricDesiredCount(),
threshold: 1,
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN,
});
}
}
2. CDK ile Fargate Spot İşleme
// CDK high-level construct'larda Fargate Spot'u doğrudan desteklemiyor
// Escape hatch'ler kullanman gerekiyor
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
// CDK ENI'leri tüketen birçok kaynak yaratır
// İzle ve alert'ler kur
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"
# Otomatik task definition güncellemeleri için track_latest kullan
task_definition_track_latest = 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]
}
Aklımızı Kurtaran 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ı:
- Öncelikli olarak Lambda tabanlıysanız, biraz 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 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:
$ terraform import aws_ecs_service.app production-app-service
Import successful!
$ terraform plan
~ 147 kaynak değiştirilecek # Kaynak drift tespiti
! 23 kaynak yeniden yaratılacak # Breaking değişiklikler
Error: Resource already exists # Import çakışmaları
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
Doğru IaC aracını seçmek için rehber:
CDK’yı seçin eğer:
- Ekibiniz TypeScript/Python’u iyi biliyor
- Sıfırdan başlıyorsunuz (legacy yok)
- High-level abstraction’lar istiyorsunuz
- AWS’ye all-in’siniz
- Uçta yaşamayı seviyorsunuz
Terraform’u seçin eğer:
- Multi-cloud potansiyeline ihtiyacınız var
- Ekibiniz declarative syntax tercih ediyor
- Mevcut Terraform module’leriniz var
- Stabilite > En son özellikler
- Büyük community desteğine değer veriyorsunuz
SAM’i seçin eğer:
- Lambda-first mimarideyseniz
- Step Functions’a ihtiyacınız var
- Minimal tooling istiyorsunuz
- Fargate kullanımınız minimal
Hala CloudFormation kullanın eğer:
- Acıdan hoşlanıyorsanız (şaka!)
- AWS Support’un debug etmesine ihtiyacınız var
- AWS Service Catalog kullanıyorsunuz
- Kurumsal zorunluluk (başınız sağ olsun)
Her Yerde İşe Yarayan Pattern’ler
Tool’dan bağımsız, bu pattern’ler bizi kurtardı:
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@v6
with:
script: |
// Plan output'u PR comment olarak post et
apply:
needs: plan
if: github.ref == 'refs/heads/main'
steps:
- name: Terraform Apply
run: |
terraform apply tfplan
Her Yaklaşımın Maliyeti
Para konuşalım, çünkü cloud faturaları yalan söylemez:
| Tool | Öğrenme Eğrisi | Bakım Maliyeti | Esneklik | AWS Özellik Gecikmesi |
|---|---|---|---|---|
| CDK | 2 hafta | Orta | Yüksek | 0-2 hafta |
| Terraform | 1 hafta | Düşük | Yüksek | 2-4 hafta |
| SAM | 3 gün | Düşük | Düşük | 0 hafta |
| CloudFormation | 1 hafta | Yüksek | Orta | 0 hafta |
Ama gerçek maliyet? Developer mutluluğu.
Ekip hızımız:
- CloudFormation ile: 5 story point/sprint
- Terraform ile: 8 story point/sprint
- CDK ile: 12 story point/sprint
Sonuç
Farklı senaryolar için iyi çalışan:
- Yeni projeler: TypeScript ile CDK
- Mevcut projeler: Zaten orada olan (mecbur kalmadıkça migrate etmeyin)
- Multi-cloud potansiyeli: Terraform
- Hızlı prototip: SAM
- Bir daha asla: Raw CloudFormation
Kirli sır? Hepsi zaten CloudFormation üretiyor. Ekibinizi üretken yapan abstraction seviyesini seçin.
Unutmayın: En iyi IaC tool’u ekibinizin gerçekten kullanacağı tool’dur. Mükemmelin, deploy edilenin düşmanı olmasına izin vermeyin.
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.
Serideki tüm yazılar
İlgili yazılar
Nested stack'ler, cross-stack referanslar, SSM Parameter Store ve microstack mimarisi kullanarak CloudFormation'un 500 kaynak sınırını aşmak için kanıtlanmış stratejiler. TypeScript CDK örnekleri ve karar çerçeveleri ile.
Çok fazla EC2 instance yöneten birinden AWS Fargate'e pratik bir rehber. Serverless container'ların ne zaman mantıklı olduğunu öğrenin.
Production workload'ları çalıştırırken öğrenilen gelişmiş Fargate pattern'leri. Maliyet optimizasyonundan stateful container'lara, dokümantasyonun size söylemeyecekleri.
AgentCore Runtime üzerinde minimal bir Strands agent'ı CDK ile deploy etme rehberi — parametrize stack, arm64 build, deploy ve invoke akışı, ve ilk çağrıdan önce gereken IAM ve Marketplace ön koşulları.
OU yapısı, SCP, RCP, Account Factory for Terraform, IAM Identity Center ve merkezi güvenlik mimarisi konularını kapsayan AWS Control Tower çoklu hesap stratejisi tasarımı ve uygulaması için pratik bir rehber.