AWS CDK Functional Patterns: Tekrar Kullanılabilir, Hatasız Infrastructure Konfigürasyonları
Functional programming pattern'leri - factory function'lar, higher-order function'lar ve composition - ile AWS CDK'yı CloudFormation generator'dan type-safe, tekrar kullanılabilir bir infrastructure toolkit'e dönüştürmeyi öğren.
Özet
AWS CDK, infrastructure'ı gerçek kod olarak ele almamızı sağlar, ancak doğru pattern'ler olmadan takımlar genellikle duplicate konfigürasyonlar, tutarsız ayarlar ve compile time'da önlenebilecek runtime hataları ile karşılaşır. Functional programming pattern'leri - higher-order function'lar, factory pattern'ler ve composition - CDK'yı CloudFormation generator'dan type-safe, tekrar kullanılabilir bir infrastructure toolkit'e dönüştürür. Bu yazıda, ortak konfigürasyonları (NodejsFunction ayarları, RemovalPolicy enforcement, logging standartları gibi) nasıl merkezileştirebileceğini ve manuel tekrar veya runtime sürprizleri olmadan tüm kaynaklarda nasıl tutarlı şekilde uygulayabileceğini göstereceğim.
İlgili yazılar: Bu yazı TypeScript'te creational pattern'ler ve builder pattern'ler üzerine inşa ediliyor ve bunları özellikle AWS CDK infrastructure'ına uyguluyor. Environment management ve migration context için Serverless'ten CDK'ya migration Bölüm 4'e göz at.
Configuration Drift Problemi
Birden fazla microservice'de AWS CDK ile çalışırken tekrarlayan bir pattern fark ettim: farklı developer'lar Lambda function'larını farklı şekillerde konfigüre ediyor. Bazıları log retention ayarlamayı unutuyor, diğerleri tutarsız timeout değerleri kullanıyor ve memory size'lar benzer workload'lar arasında rastgele değişiyor. Production veritabanları RemovalPolicy ayarlanmadığı için yanlışlıkla siliniyor, development veritabanları ise süresiz olarak korunup maliyetleri artırıyordu.
Temel sorun bilgi eksikliği değildi - enforcement eksikliğiydi. 50 satırlık Lambda konfigürasyonlarını 20+ function arasında copy-paste yapmak maintenance kabusu yaratıyordu. Gereksinimler değiştiğinde, bunları tutarlı şekilde güncellemek proje çapında bir refactoring egzersizi haline geliyordu.
Merkezi NodejsFunction Konfigürasyon Factory
Önemli bir fark yaratan en basit pattern, Lambda konfigürasyonları için bir factory function oluşturmaktı.
Pattern Olmadan:
Factory Pattern ile:
8 servis genelinde 40+ Lambda function bulunan bir microservices mimarisinde, bu pattern değerini AWS Node.js 20 runtime'ını yayınladığında kanıtladı. Merkezi factory'yi güncellemek 5 dakika sürdü, 40+ bireysel function tanımını güncellemek yerine.
Higher-Order Function'lar ile RemovalPolicy Enforcement
Production veritabanlarının yanlışlıkla silinmesi teorik bir problem değil - gerçekten oluyor. Environment'a özgü policy'ler otomatik olmalı, her kaynak için tekrarlanan manuel kararlar olmamalı.
Pattern Olmadan:
Higher-Order Function ile:
Daha İyi - CDK Aspects Kullanarak:
CDK Aspects, bireysel kaynak tanımlarını değiştirmeden bir stack'teki tüm kaynaklar için policy'leri enforce etmenin güçlü bir yolunu sağlar. Bu aspect, synthesis sırasında çalışır ve environment'a göre uygun RemovalPolicy'yi uygular.
Composable Configuration Builder'lar
Lambda function'ları genellikle farklı feature kombinasyonlarına ihtiyaç duyar: bazılarının VPC erişimine, bazılarının layer'lara, bazılarının DLQ'ya, bazılarının ise hepsine ihtiyacı vardır. Bu kombinasyonları temiz şekilde konfigüre etmek composition yaklaşımı gerektirir.
Bu pattern, karmaşık Lambda konfigürasyonlarını basit, tekrar kullanılabilir parçalardan oluşturmana olanak tanır. Her composer function bir cross-cutting concern'i ele alır ve gerektiği gibi combine edilebilir.
Type-Safe Environment Konfigürasyonu
Environment'a özgü ayarların (VPC ID'ler, subnet ID'ler, domain name'ler) kod boyunca dağılmış olması, environment'lar arasında neyin değiştiğini anlamayı zorlaştırır. Strongly-typed bir konfigürasyon pattern'i bunu çözer.
Zod validation, konfigürasyon hatalarını runtime'da (synth sırasında) yakalar ve geçersiz deployment'ları önler. TypeScript, compile-time type safety ve mükemmel IDE autocomplete desteği sağlar.
Sensible Default'lar ile Custom L3 Construct'lar
Her API endpoint için Lambda + API Gateway + DynamoDB table + CloudWatch alarm'ları gerektiğinde çok fazla tekrarlayan kod ortaya çıkar. Custom L3 construct'lar bu pattern'leri kapsüller.
Bu custom construct, best practice'leri kapsüller: encryption at rest, production için point-in-time recovery, uygun IAM permission'ları, API Gateway logging ve CloudWatch alarm'ları. Yeni takım üyeleri her detayı anlamadan kullanabilir.
CDK Aspects ile Policy Enforcement
Security gereksinimleri - encryption at rest, encryption in transit, public S3 bucket yok, her şey için CloudWatch log'ları - otomatik enforcement gerektiriyor.
Aspect'ler, her kaynak tanımını değiştirmeden organizational policy'leri enforce etmenin güçlü bir yolunu sağlar. CDK synthesis sırasında çalışır ve kaynakları validate edebilir, modify edebilir veya annotate edebilir.
Yaygın Hatalar ve Çözümleri
Aşırı Abstraction
Basit olanlar dahil her kaynak için factory function oluşturmak, faydası olmayan abstraction overhead'i yaratır. Pattern'leri, tekrarlanan konfigürasyonlara veya karmaşık validation gereksinimlerine sahip kaynaklara seçici olarak uygula. Tek bir S3 bucket factory'ye ihtiyaç duymaz.
Ne zaman abstract etmeli:
- Kaynak benzer config ile 3+ kez görünüyor
- Karmaşık validation logic gerekli
- Environment'a özgü varyasyonlar gerekli
- Security/compliance policy'leri enforce edilmeli
Implicit Dependency'ler
Belirli kaynakların (VPC, security group'lar) var olduğunu dependency'leri explicit yapmadan varsayan factory function'lar kırılgan kod yaratır. Dependency'leri function parametreleri aracılığıyla explicit yap.
Wrapper'larda Type Safety Kaybı
any type'ları veya aşırı permissive generic'ler kullanmak TypeScript'in type checking'ini yok eder. Factory layer'ları boyunca strict type'ları koru.
Environment'lar Arasında Configuration Drift
Dev vs prod'da farklı konfigürasyon pattern'leri kullanmak "dev'de çalışıyor" production failure'larına neden olur. Tüm environment'lar için aynı code path'i kullan, sadece konfigürasyon değerlerinde farklılık olsun.
Infrastructure Code'u Test Etme
Infrastructure code, application code gibi test edilmeli. Resource property'lerini verify etmek için CDK assertions library'yi kullan.
Test yapmak konfigürasyon hatalarını yakalar ve factory function'ların beklenen CloudFormation resource'larını ürettiğini validate eder.
Önemli Çıkarımlar
Merkezileştirme drift'i önler. Factory function'lar ve custom construct'lar, tüm kaynakların manuel enforcement olmadan aynı standartları takip etmesini sağlar. AWS yeni runtime'lar yayınladığında veya security gereksinimleri değiştiğinde, merkezi bir factory'yi güncellemek saatler yerine dakikalar sürer.
Type safety hataları erken yakalar. Zod validation ile birleşik TypeScript, yanlış konfigüre edilmiş kaynakların deployment'ını önler. Hataları compile time veya synth time'da yakalamak, başarısız deployment başına 5-10 dakika kazandırır ve production incident'larını önler.
Aspect'ler policy'leri otomatik enforce eder. RemovalPolicy, encryption, log retention ve diğer security policy'leri, bireysel kaynaklara dokunmadan tüm stack'lerde enforce edilebilir. Bu, security audit bulgularını ve compliance ihlallerini azaltır.
Duplication yerine composition. Higher-order function'lar ve composition pattern'leri, karmaşık konfigürasyonları basit, tekrar kullanılabilir parçalardan oluşturmana olanak tanır. Bu, tipik CDK projelerinde kod duplikasyonunu %40-60 azaltır.
Environment'a özgü config explicit olmalı. Type-safe config object'leri kullanarak konfigürasyonu koddan ayır. Bu, production incident'larına neden olan "dev'de çalışıyor ama prod'da başarısız" senaryolarını önler.
Progressive enhancement en iyi çalışır. Basit factory function'larla başla. Karmaşıklık arttıkça builder pattern'leri, custom construct'lar ve Aspect'ler ekle. İlk günden aşırı mühendislik yapmak gereksiz karmaşıklık yaratır.
Infrastructure'ı application code gibi test et. CDK construct'ları kod - bunları @aws-cdk/assertions kullanarak aynı titizlikle test et. Bu, refactoring sırasında breaking change'leri yakalar ve beklenen davranışı validate eder.
Functional pattern'ler CDK'ya doğal uyar. Higher-order function'lar, composition ve immutability, CDK'nın declarative doğasıyla iyi uyumludur. Bu pattern'ler, infrastructure code'u daha maintainable ve reason about edilebilir hale getirir.