AWS Türkçe Blog

Daha büyük sunucusuz uygulamaları düzenlemek için en iyi uygulamalar

Orijinal makale: Link (James Beswick)

İyi tasarlanmış sunucusuz uygulamalar ayrıştırılır (decoupled), durumsuzdur (stateless) ve minimum kod kullanır. Projeler büyüdükçe, geliştirme yöneticileri için bir hedef, tasarımın basitliğini ve düşük kodlu uygulamayı sürdürmektir. Bu blog gönderisi, daha büyük sunucusuz projelerde kod depolarının tasarlanması ve yönetilmesi için öneriler ve üretim sistemlerinin sürümlerini dağıtmak için en iyi uygulamalar sağlar.

Kod depolarınızı düzenleme

Birçok sunucusuz uygulama, monolitik uygulamalar olarak başlar. Bu, basit bir uygulamanın zaman içinde daha karmaşık hale gelmesi veya geliştiricilerin mevcut geliştirme uygulamalarını izlemesi nedeniyle olabilir. Monolitik bir uygulama, birden çok görevi gerçekleştiren tek bir AWS Lambda işleviyle temsil edilir ve mono-repo, tüm uygulama mantığını içeren tek bir havuzdur.

Monolitler, tek amaçlı işlevleri gerçekleştiren en basit sunucusuz uygulamalar için iyi çalışır. Bunlar cron işleri, veri işleme görevleri ve bazı asenkron işlemler gibi küçük uygulamalardır. Bu uygulamalar iş akışlarına dönüştükçe veya yeni özellikler geliştirdikçe, kodu daha küçük hizmetlere dönüştürmek önemli hale geliyor.

AWS Serverless Application Model (SAM) veya Serverless Framework gibi çerçevelerin kullanılması, ortak işlevsellik parçalarını daha küçük servisler halinde gruplamayı kolaylaştırabilir. Bunların her birinin ayrı bir kod deposu olabilir. SAM için template.yaml dosyası, bir uygulama için gereken tüm kaynakları ve işlev tanımlarını içerir. Sonuç olarak, bir uygulamayı ayrı şablonlarla mikroservislere bölmek, depoları ve kaynak gruplarını ayırmanın basit bir yoludur.

Separate templates for microservices

Sunucusuz bir uygulamanın en küçük biriminde, işlev başına bir depo oluşturmak da mümkündür. Bu işlevler bağımsızsa ve diğer AWS kaynaklarını paylaşmıyorsa bu uygun olabilir. Yardımcı işlevler ve basit olay işleme kodu, bu tür depo yapısı için aday örnekleridir.

Çoğu durumda, bir mikroservisi tanımlayan işlev ve kaynak grupları etrafında depolar oluşturmak mantıklıdır. Bir e-ticaret örneğinde, “Ödeme işleme”, ortak kaynakları paylaşan çok sayıda daha küçük ilgili işleve sahip bir mikroservistir.

Herhangi bir yazılımda olduğu gibi, depo tasarımı, geliştirme ekiplerinin kullanım durumuna ve yapısına bağlıdır. Büyük bir depo, geliştirici ekiplerinin farklı özellikler üzerinde çalışmasını, test edip dağıtmasını zorlaştırır. Çok fazla depoya sahip olmak, yinelenen kodlar oluşturabilir ve kaynakları depolar arasında paylaşmada zorluklara neden olabilir. Projeniz için dengeyi bulmak, uygulama mimarinizi tasarlamada önemli bir adımdır.

Kod kitaplıkları yerine AWS hizmetlerini kullanma

AWS hizmetleri, sunucusuz uygulamalarınız için önemli yapı taşlarıdır. Bunlar, benzer işlevlere sahip demet kod paketlerinden sıklıkla daha fazla ölçek, performans ve güvenilirlik sağlayabilir.

Örneğin, Lambda’ya taşınan birçok web uygulaması Flask (Python için) veya Express (Node.js için) gibi web çerçevelerini kullanır. Her iki paket de, uygulama bir web sunucusunda çalışıyorsa çok uygun olan yönlendirmeyi ve ayrı kullanıcı bağlamlarını destekler. Bu paketleri Lambda işlevlerinde kullanmak aşağıdaki gibi mimarilerle sonuçlanır:

Web servers in Lambda functions

Bu durumda Amazon API Gateway, yönlendirmeyi işlemek için Lambda işlevine yapılan tüm isteklerin proxy’sini gönderir. Uygulama daha fazla rota geliştirdikçe, Lambda işlevinin boyutu büyür ve yeni sürümlerin dağıtımları tüm işlevin yerini alır. Bu bağlamda birden fazla geliştiricinin aynı proje üzerinde çalışması zorlaşıyor.

Bu yaklaşım genellikle gereksizdir ve API Gateway’de bulunan yerel yönlendirme işlevinden yararlanmak genellikle daha iyidir. Çoğu durumda, dağıtım paketinin boyutunu artıran Lambda işlevinde web çerçevesine gerek yoktur. API Gateway ayrıca parametreleri doğrulama yeteneğine sahiptir, bu da parametreleri özel kodla kontrol etme ihtiyacını azaltır. Ayrıca yetkisiz erişime karşı koruma ve hizmet düzeyinde ele alınmaya daha uygun bir dizi başka özellik de sağlayabilir. API Gateway bu şekilde kullanıldığında yeni mimari şöyle görünür:

Using API Gateway for routing

Ek olarak, Lambda işlevleri daha az kod ve daha az paket bağımlılığından oluşur. Bu, testi kolaylaştırır ve kod kitaplığı sürümlerini koruma ihtiyacını azaltır. Bir ekipteki farklı geliştiriciler, ayrı yönlendirme işlevleri üzerinde bağımsız olarak çalışabilir ve gelecekteki projelerde kodu yeniden kullanmak daha kolay hale gelir. Uygulamanın SAM şablonunda API Gateway’de rotaları yapılandırabilirsiniz:

Resources:
  GetProducts:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: getProducts/
      Handler: app.handler
      Runtime: nodejs12.x
      Events:
        GetProductsAPI:
          Type: Api 
          Properties:
            Path: /getProducts
            Method: get
YAML

Benzer şekilde, genellikle Lambda işlevleri içinde iş akışı düzenlemeleri yapmaktan kaçınmalısınız. Bunlar, diğer hizmetlere ve işlevlere seslenen ve başarılı yürütme veya başarısızlığa bağlı olarak sonraki eylemleri gerçekleştiren kod bölümleridir.

Lambda functions with embedded workflow orchestrations

Bu iş akışları hızla kırılgan hale gelir ve yeni gereksinimler için değiştirilmesi zorlaşır. Lambda işlevinde boşta çalışmaya neden olabilirler; bu, işlevin harici kaynaklardan dönüş değerleri beklediği anlamına gelir, bu da yürütme maliyetini artırır.

Genellikle daha iyi bir yaklaşım, uygulamanın SAM şablonunda karmaşık iş akışlarını JSON tanımları olarak gösterebilen AWS Step Functions’ı kullanmaktır. Bu hizmet, gereken özel kod miktarını azaltır ve Lambda işlevlerinde boşta kalmayı en aza indiren uzun ömürlü iş akışları sağlar. Ayrıca, iş akışları yükseltilirken yürütmeleri de yönetir. Step Functions iş akışıyla yeniden tasarlanmış yukarıdaki örnek şuna benzer:

Using Step Functions for orchestration

Geliştirme ekipleri için birden çok AWS hesabı kullanma

Sunucusuz uygulamaları üretime dağıtmanın birçok yolu vardır. Uygulamalar büyüdükçe ve işiniz için daha önemli hale geldikçe, geliştirme yöneticileri genellikle dağıtım sürecinin sağlamlığını geliştirmek ister. AWS’te sunucusuz uygulamaların geliştirilmesini ve dağıtımını yönetmek için bir dizi seçeneğiniz vardır.

İlk olarak, birden fazla AWS hesabı kullanmanız önemle tavsiye edilir. AWS Organizations‘ı kullanarak bu hesapların faturalandırmasını, uyumluluğunu ve güvenliğini merkezi olarak yönetebilirsiniz. Özel komut dosyalarından ve manuel işlemlerden kaçınmak için hesap gruplarına politikalar ekleyebilirsiniz. Basit bir yaklaşım, her geliştiriciye bir AWS hesabı sağlamak ve ardından beta dağıtım aşaması ve üretim için ayrı hesaplar kullanmaktır:

Multiple AWS accounts in a deployment pipeline

Geliştirici hesapları, üretim kaynaklarının kopyalarını içerebilir ve geliştiriciye bu kaynaklar için yönetici düzeyinde izinler sağlayabilir. Her geliştiricinin hesap için kendi sınırları vardır, bu nedenle kullanımları üretim ortamınızı etkilemez. Bireysel geliştiriciler, üretim varlıkları için minimum riskle CloudFormation yığınlarını ve SAM şablonlarını bu hesaplara dağıtabilir.

Bu yaklaşım, geliştiricilerin Lambda işlevlerini geliştirme makinelerinde yerel olarak bireysel hesaplarındaki canlı bulut kaynaklarına karşı test etmelerine olanak tanır. Sağlam bir birim test süreci oluşturmaya yardımcı olabilir ve geliştiriciler daha sonra hazır olduklarında AWS CodeCommit gibi bir havuza kod gönderebilirler.

AWS Secrets Manager ile entegre ederek, her ortamda farklı gizli dizi kümeleri depolayabilir ve kodda depolanan kimlik bilgilerine olan ihtiyacı ortadan kaldırabilirsiniz. Kod, geliştirici hesabından beta ve üretim hesaplarına yükseltildiğinden, doğru kimlik bilgileri kümesi otomatik olarak kullanılır. Ortam düzeyinde kimlik bilgilerini bireysel geliştiricilerle paylaşmanız gerekmez.

Kod dağıtıldığında ardışık düzenler oluşturmaya başlamak için bir CI/CD işlemi uygulamak da mümkündür. Çok hesaplı dağıtım akışı kullanarak örnek bir uygulama dağıtmak için bu sunucusuz CI/CD öğreticisini izleyin.

Sunucusuz uygulamalarda özellik sürümlerini yönetme

Üretim sunucusuz uygulamalarınız için CI/CD ardışık düzenlerini uygularken, tüm uygulama yükseltmeleri yerine güvenli dağıtımları tercih etmek en iyi uygulamadır. Geleneksel yazılım dağıtımlarından farklı olarak sunucusuz uygulamalar, Lambda işlevlerindeki özel kod ile AWS servis yapılandırmalarının bir birleşimidir.

Bir özellik sürümü, bir Lambda işlevindeki bir sürüm değişikliğinden oluşabilir. API Gateway’de farklı bir bitiş noktasına (endpoint) sahip olabilir veya DynamoDB tablosu gibi yeni bir kaynak kullanabilir. Dağıtılan özelliğe erişim, uygulamaya bağlı olarak kullanıcı yapılandırması ve özellik geçişleri aracılığıyla kontrol edilebilir. AWS SAM, YAML yapılandırmasında kanarya dağıtımlarını yapılandırmanıza olanak tanıyan yerleşik AWS CodeDeploy‘a sahiptir:

Resources:
 GetProducts:
   Type: AWS::Serverless::Function
   Properties:
     CodeUri: getProducts/
     Handler: app.handler
     Runtime: nodejs12.x

     AutoPublishAlias: live

     DeploymentPreference:
       Type: Canary10Percent10Minutes 
       Alarms:
         # A list of alarms that you want to monitor
         - !Ref AliasErrorMetricGreaterThanZeroAlarm
         - !Ref LatestVersionErrorMetricGreaterThanZeroAlarm
       Hooks:
         # Validation Lambda functions run before/after traffic shifting
         PreTraffic: !Ref PreTrafficLambdaFunction
         PostTraffic: !Ref PostTrafficLambdaFunction
YAML

CodeDeploy, bir işlevin eski sürümlerine işaret eden takma adları otomatik olarak oluşturur. Kanarya dağıtımı, yeni sürümün beklendiği gibi çalıştığından emin olduğunuz zaman trafiği kademeli olarak eski takma addan yeni takma adına kaydırmanıza olanak tanır. Veya gerekirse güncellemeyi geri alabilirsiniz. Ayrıca trafik kaymasından önce ve sonra Lambda işlevlerini çağırmak için PreTraffic ve PostTraffic kancaları ayarlayabilirsiniz.

Sonuç

Herhangi bir yazılım uygulamasının boyutu büyüdükçe, geliştirme yöneticilerinin kod depolarını düzenlemesi ve sürümleri yönetmesi önemlidir. Daha büyük uygulamaların yönetilmesine yardımcı olmak için sunucusuzda yerleşik kalıplar vardır. Genel olarak, monolitik işlevlerden ve mono depolardan kaçınmak en iyisidir ve depoları mikroservis veya işlev düzeyine göre kapsamanız gerekir.

İyi tasarlanmış sunucusuz uygulamalar, yönetilen hizmetlere bağlanmak için Lambda işlevlerinde özel kod kullanır. Dağıtım boyutunu en aza indirmek ve kod tabanını basitleştirmek için hizmetlerle değiştirilebilecek kitaplıkları ve paketleri belirlemek önemlidir. Bu, özellikle sunucu tabanlı ortamlardan taşınan uygulamalar için geçerlidir.

AWS Organizations’ı kullanarak, geliştiricilerinizin geliştirme için kendi AWS hesaplarına sahip olmalarını sağlamak için hesap gruplarını yönetirsiniz. Bu, mühendislerin kod yazarken ve hata ayıklarken üretim varlıklarını klonlamasına ve AWS Cloud’a karşı test etmesine olanak tanır. Secrets Manager’ı kullanarak gizli dizileri korurken kodu bir beta ortamından üretime göndermek için bir CI/CD ardışık düzeni kullanabilirsiniz. Ayrıca, kanarya dağıtımlarını kolayca yönetmek için CodeDeploy’u kullanabilirsiniz.

SAM ve CodeDeploy ile Lambda işlevlerini dağıtma hakkında daha fazla bilgi edinmek için bu öğreticideki adımları izleyin.