Serverless Framework mi AWS CDK mi? Geçiş Yapmalı mısınız? (Bölüm 1)
Serverless Framework'ten AWS CDK'ya geçiş rehberinin ilk bölümü. Neden geçiş yapmalı, temel kavramlar ve ilk adımlar.
Serverless Framework ve AWS CDK, örtüşen sorunları farklı felsefelerle çözer. Serverless Framework, Lambda merkezli bir deploy birimi üzerinde YAML güdümlü, sağlayıcıdan bağımsız bir soyutlamadır; CDK ise CloudFormation üzerinde tip güvenli, AWS-native bir sentez katmanıdır. Serverless Framework ücretli lisans modeline geçtiğinde, olduğun yerde kalmak artık bedelsiz varsayılan olmaktan çıktı ve karşılaştırmayı yeniden yapmak anlamlı hale geldi.
AWS’e zaten bağlanmış ve bir avuçtan fazla fonksiyon çalıştıran bir ekip için varsayılan tercih CDK: tip güvenli cross-stack referanslar, Serverless Framework’ün plugin ile ulaştığı servisler için native construct’lar ve unit test edilebilir altyapı. Bedeli ise daha derin AWS bağımlılığı ve TypeScript öğrenme eğrisi. Tek şikayeti lisans maliyeti olan küçük ve oturmuş bir Lambda + API Gateway uygulaması, bu bedeli genelde geri kazandırmaz.
Bu altı bölümlük seri tüm geçiş sürecini kapsıyor:
- Bölüm 1: Neden geçmeli? Trade-off’ları anlama (bu yazı)
- Bölüm 2: CDK environment ve proje yapısı kurulumu
- Bölüm 3: Lambda fonksiyonları ve API Gateway migrate etme
- Bölüm 4: Veritabanı kaynakları ve environment yönetimi
- Bölüm 5: Authentication, authorization ve IAM
- Bölüm 6: Migration stratejileri ve Best Practice’ler
Lisans Maliyeti ve Operasyonel Maliyet#
Lisans ücreti görünen maliyettir. Kararı belirleyen ise çoğu zaman altındaki operasyonel maliyetlerdir. Ekipleri CDK’ya yönlendiren iki katman da burada:
Doğrudan Maliyetler#
Serverless Framework’ün Pro katmanı deployment başına ücretlendirir ve ekip büyüdükçe bu maliyet de büyür; daha fazla özellik ücretli seviyelerin arkasına taşınır. CDK’da ayrı bir lisans ücreti yok: AWS CLI’nın parçası olarak gelir, infrastructure’ı standart uygulama kodu gibi ele alır ve AWS servislerini native destekler.
Gizli Operasyonel Maliyetler#
Her iki araç da faturada görünmeyen sürekli maliyetler taşır. YAML syntax’ı büyüdükçe bakımı zorlaşır, üçüncü taraf plugin’ler kendi uyumluluk sorunlarını getirir, cross-service referanslar tip güvenli objeler yerine string’e dayanır, debugging ise compile-time yerine runtime’da ortaya çıkar.
Pratikte Compile-Time Güvenliği#
Günlük çalışmada öne çıkan farklar kararı şekillendirir:
Konfigürasyon Hataları ve Plugin Yükü#
YAML’da konfigürasyon typo’ları production’a kadar ulaşabilir. TypeScript bunları compile time’da durdurur. Serverless Framework, webhook secret’ını doğrudan environment’tan okur:
# serverless.yml
provider:
environment:
STRIPE_API_KEY: ${env:STRIPE_API_KEY}
STRIPE_WEBHOOK_SECRET: ${env:STRIPE_WEBHOOK_SECRET}
CDK, STRIPE_WEBHOOK_SECRET’ı application kodunda okur ve eksikse deploy’dan önce hata fırlatır:
// Environment variable'lar compile time'da validate ediliyor
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
if (!webhookSecret) {
throw new Error('STRIPE_WEBHOOK_SECRET environment variable gerekli');
}
Gelişmiş özellikler Serverless Framework’ü community plugin’lere yöneltir; her plugin, Node.js güncellemeleri sırasında takip edilmesi gereken kendi uyumluluk yükünü getirir:
plugins:
- serverless-webpack
- serverless-offline
- serverless-step-functions
custom:
webpack:
webpackConfig: webpack.config.js
CDK tarafında bu yüke gerek yok:
// Native bundling ve servis entegrasyonu
const bundling = {
target: 'node20',
minify: true,
sourceMap: true,
};
Cross-Stack Tip Güvenliği#
CDK, CloudFormation export’larının yerine tip güvenli obje referansları koyar. Bağımlılıklar açık ve tip kontrollü kalır, bu da refactoring’i daha güvenli kılar:
// Compile-time validation ile doğrudan obje referansları
const authStack = new AuthStack(this, 'AuthStack', {
userTable: databaseStack.userTable, // TypeScript bunun var olduğunu garanti eder
});
Serverless Framework’te bağımlılığı CloudFormation export’ları ve string interpolation kurar:
# auth-service/serverless.yml
provider:
environment:
USER_TABLE_ARN: ${cf:database-stack-${opt:stage}.UserTableArn}
Tek Fonksiyonun Ötesinde Ölçeklenme#
İki yaklaşım arasındaki fark, uygulama tek bir endpoint’in ötesine büyüdükçe açılır. Bir createUser route bu farkı pratikte gösterir. Serverless Framework onu YAML’da tanımlar:
# serverless.yml
provider:
name: aws
runtime: nodejs20.x
environment:
TABLE_NAME: ${self:service}-${opt:stage}-users
functions:
createUser:
handler: src/handlers/users.create
events:
- http:
path: users
method: post
cors: true
CDK, fonksiyonu ve route’unu kodda doğrudan bağlar:
// lib/api-stack.ts
import { RestApi, LambdaIntegration } from 'aws-cdk-lib/aws-apigateway';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
const createUserFn = new NodejsFunction(this, 'CreateUserFunction', {
entry: 'src/handlers/users.ts',
handler: 'create',
environment: {
TABLE_NAME: userTable.tableName,
},
});
// Tip güvenli entegrasyon
const api = new RestApi(this, 'UserApi');
api.root.addResource('users').addMethod('POST',
new LambdaIntegration(createUserFn)
);
Plugin Olmadan Step Functions ve AppSync#
CDK, ekstra bir bağımlılık olmadan Step Functions, AppSync ve CloudWatch alarmlarının üçüne de kendi construct’ları üzerinden ulaşır:
import { DefinitionBody, StateMachine } from 'aws-cdk-lib/aws-stepfunctions';
import { LambdaInvoke } from 'aws-cdk-lib/aws-stepfunctions-tasks';
import { Definition, GraphqlApi } from 'aws-cdk-lib/aws-appsync';
import { Alarm } from 'aws-cdk-lib/aws-cloudwatch';
// Plugin olmadan doğrudan servis entegrasyonu
const workflow = new StateMachine(this, 'UserWorkflow', {
definitionBody: DefinitionBody.fromChainable(
new LambdaInvoke(this, 'ProcessUser', {
lambdaFunction: processUserFn,
})
),
});
const api = new GraphqlApi(this, 'UserGraphQL', {
name: 'user-api',
definition: Definition.fromFile('schema.graphql'),
});
new Alarm(this, 'ProcessUserErrors', {
metric: processUserFn.metricErrors(),
threshold: 1,
evaluationPeriods: 1,
});
Serverless Framework’te bunların her biri ayrı bir plugin gerektirir:
plugins:
- serverless-step-functions
- serverless-appsync-plugin
- serverless-plugin-aws-alerts
custom:
alerts:
stages:
- production
topics:
alarm:
topic: ${self:service}-${opt:stage}-alerts
Yeniden Kullanılabilir API Construct’ı#
API construct’ını yeniden kullanılabilir bir class içinde sarmalamak, CDK’ya gerçek object-oriented infrastructure kazandırır:
// lib/constructs/serverless-api.ts
export class ServerlessApi extends Construct {
public readonly api: RestApi;
public readonly functions: Map<string, NodejsFunction>;
constructor(scope: Construct, id: string, props: ServerlessApiProps) {
super(scope, id);
// Kapsüllenmiş, yeniden kullanılabilir infrastructure kalıpları
this.api = new RestApi(this, 'Api', {
restApiName: props.apiName,
deployOptions: this.createDeployOptions(props.stage),
});
this.functions = this.createFunctions(props.routes);
this.setupRoutes(props.routes);
this.setupAlarms(props.monitoring);
}
}
// Birden fazla stack'te kullanım
new ServerlessApi(this, 'UserApi', {
apiName: 'users',
routes: userRoutes,
monitoring: productionMonitoring,
});
Serverless Framework bunu include’lar ve paylaşılan variable dosyalarıyla yaklaşık olarak sağlar:
# serverless.yml
custom:
userTableConfig: ${file(./config/tables.yml):userTable}
resources:
Resources:
UserTable: ${self:custom.userTableConfig}
Stack İçin Unit Test Yazmak#
Serverless Framework’te test etmek genellikle şunları içerir:
- Framework davranışını mocklama
- Deploy edilmiş kaynakları test etme
- Sınırlı unit test seçenekleri
Synthesize edilmiş template’in kendisine karşı, CDK testleri doğrudan çalışır:
// test/api-stack.test.ts
import { Match, Template } from 'aws-cdk-lib/assertions';
const template = Template.fromStack(stack);
test('API Gateway CORS etkin', () => {
template.hasResourceProperties('AWS::ApiGateway::Method', {
Integration: {
IntegrationResponses: [{
ResponseParameters: {
'method.response.header.Access-Control-Allow-Origin': "'*'",
},
}],
},
});
});
test("Lambda doğru environment variable'lara sahip", () => {
template.hasResourceProperties('AWS::Lambda::Function', {
Environment: {
Variables: {
TABLE_NAME: { Ref: Match.anyValue() },
STAGE: 'production',
},
},
});
});
Her Aracın Üstün Olduğu Durumlar#
CDK’nın Öne Çıktığı Noktalar#
CDK, AWS yüzeyi karmaşıklaştıkça öne çıkar: Step Functions, EventBridge ve AppSync entegrasyonları; ekipler arası yeniden kullanılabilir kalması gereken infrastructure kalıpları; custom CloudFormation kaynakları üzerinde ince taneli kontrol; stack boyunca TypeScript typing; infrastructure’ın kendisi için unit ve entegrasyon testleri; ve birden fazla ekip aynı koda dokunduğunda açık bağımlılıklar ve interface’ler.
Serverless Framework birkaç durumda hâlâ kazanıyor:
- Basit bir Lambda + API Gateway CRUD API’si
- Mevcut plugin ecosystem’ine ağır bağımlılığı olan bir ekip
- TypeScript yerine YAML’ı tercih eden geliştiriciler
- Hızlı prototipler
- Infrastructure karmaşıklığının önem taşımayacağı kadar küçük uygulamalar
Geçişin Kapsamını Belirleme#
Geçişten önce işin boyutunu mevcut kurulumuna göre ölç. Eforu belirleyen beş sinyal var:
| Sinyal | Düşük efor | Yüksek efor |
|---|---|---|
| Fonksiyon sayısı | Tek serviste onlarca fonksiyon | Birkaç serviste yüzlerce fonksiyon |
| Custom kaynaklar | Yok veya düz CloudFormation | Custom resource ve macro’lar |
| Plugin’ler | Sadece lokal geliştirme ve bundler plugin’leri | CDK karşılığı olmayan plugin’ler |
| Ortamlar | Bir veya iki stage | Geliştirici ve bölge başına stage |
| CI/CD | Tek bir deploy pipeline’ı | Serverless Framework CLI çıktısına bağlı pipeline |
Teknik Değerlendirme#
- Lambda fonksiyonları ve servislerin sayısı
- Custom kaynaklar ve CloudFormation kullanımı
- Cross-service bağımlılıkları
- Plugin bağımlılıkları ve bakım yükü
Ekip ve Geçiş Hazırlığı#
Beceri, infrastructure boyutu kadar önemlidir: mevcut TypeScript deneyim seviyesi, infrastructure as code’a aşinalık, gerçekte ne kadar öğrenme zamanı olduğu ve deklaratif YAML yerine programatik infrastructure ile kurulan rahatlık. Geçiş planının kendisi de ayrı bir karar: kademeli geçiş mi tam geçiş mi, rollback prosedürleri ve test etme, geçiş sırasında paralel infrastructure ve ekip eğitimi ile bilgi transferi için ayrılan zaman.
Sonraki Bölüm#
Geçiş kararını verdikten sonra asıl iş başlıyor: güvenli ve kademeli geçişi destekleyen bir CDK proje yapısı kurmak.
Bölüm 2 bu kurulum adımlarını ele alıyor: proje mimarisi kalıpları, geliştirme iş akışları ve geçişi yönetilebilir kılan environment konfigürasyonu.
Kaynaklar#
- AWS CDK nedir? - AWS CDK v2 (yeni sekmede açılır) - CDK’nın AWS altyapısını tanımlamak için programatik, tip güvenli yaklaşımına giriş
- Serverless Framework Dokümantasyonu (yeni sekmede açılır) - YAML yapılandırması, sağlayıcılar ve eklentileri kapsayan resmi Serverless Framework referansı
- AWS CDK Construct’ları (yeni sekmede açılır) - Serverless Framework kaynak tanımlarının yerini alan L1/L2/L3 construct hiyerarşisinin açıklaması
- TypeScript ile Lambda fonksiyonu oluşturma (yeni sekmede açılır) - Lambda’nın TypeScript’i nasıl çalıştırdığı, CDK’nın NodejsFunction construct’ını değerlendirmede ilgili
- Serverless Uygulamalar Lens - AWS Well-Architected (yeni sekmede açılır) - Serverless iş yükleri için migration kararlarını şekillendiren mimari rehber
- AWS CDK ile başlarken (yeni sekmede açılır) - Migration’ı değerlendiren ekipler için önkoşullar, kurulum ve ilk CDK uygulaması
Serverless Framework'ten AWS CDK'ya Geçiş Rehberi
Serverless Framework'ten AWS CDK'ya tam geçiş sürecini kapsayan 6 bölümlük kapsamlı rehber. Kurulum, uygulama pattern'leri ve best practice'ler dahil.
Bu serideki tüm yazılar
İlgili yazılar
Lambda fonksiyonlarını ve API Gateway konfigürasyonlarını CDK'ya taşıma: bundling optimizasyonu, memory ayarı, hata yönetimi pattern'leri.
api-gateway · aws · aws-cdk +2
Stateful infrastructure'ı CDK'ya taşıma: DynamoDB migration, secrets management, parameter store ve VPC konfigürasyonu.
aws · aws-cdk · dynamodb +4
E-posta, şifre ve SMS OTP kullanan SaaS ekipleri için Cognito passkey geçiş rehberi: yapılandırma, enrollment ve SMS'in yerini alan dört basamaklı recovery merdiveni.
authentication · security · aws +2
İç servis katmanı kurmadan önce kurup kurmayacağınıza karar verin. Katmanın çağrı başına maliyeti, VPC Lattice'in kazandığı hacim ve direct invoke'un hâlâ kazandığı an.
aws · aws-cdk · lambda +4
Private REST API gRPC’yi yapısal olarak taşıyamaz ve gRPC konuşan her AWS yüzeyi Lambda hedeflerini dışlar. gRPC’den neyi tutmalı, neyi bırakmalı.
aws · aws-cdk · lambda +4