Asp.NET Core Web API Uygulamasını AWS App Runner’a ECR ve GitHub Aracılığıyla Deploy Etme
Merhaba,
Bu içeriğimizde AWS’de, önceden incelediğimiz EC2, ECS, Elastic Beanstalk ve Lambda deploy yöntemlerinden farklı bir seçenek olan, ECR ve GitHub aracılığıyla App Runner’a deploy sürecini inceliyor olacağız.
AWS App Runner Nedir?
AWS App Runner, Amazon’un tam yönetilen(fully managed) bir servisidir ve geliştiricilere konteyner tabanlı uygulamaları(container-based applications) kolayca deploy edebilme, yönetme ve ölçeklendirme imkanı sunmakta ve AWS Fargate gibi altyapı yönetimiyle uğraşmaksızın uygulamaların çalıştırmasını sağlamaktadır. Hatta AWS Fargate’e nazaran daha soyut ve basit bir deploy yolu sunduğu için Fargate’in halefi olarak yorumlanabilmekte ve daha çok tercih edilebilmektedir.
AWS App Runner’ın Özellikleri
AWS App Runner’ın bir kaç kritik özelliğini aşağıda madde madde bir kaç satırda ele alarak vurgulamakta fayda görmekteyim;
- Fully Managed Service(Tam Yönetilen Servis) : AWS App Runner’da; altyapı yönetimi(infrastructure management), yük dengeleme(load balancing) ve ölçeklendirme(scaling) AWS tarafından otomatik olarak yapılandırılmaktadır. Yani sorumluluğu geliştiricilerden ziyade AWS tarafı tam olarak üstlenmektedir.
- Easy Deployment(Kolay Deploy) : Docker container image üzerinden ECR ve Docker Hub kullanarak ya da GitHub gibi bir source code repository üzerinden kolayca deploy süreci yönetilebilmektedir.
- Auto Scaling(Otomatik Ölçeklendirme) : AWS App Runner, trafiğe ya da yoğunluğa bağlı olarak uygulamayı otomatik olarak ölçeklendirir.
- Continuous Deployment (CI/CD) : AWS App Runner, kaynak kodda bir değişiklik meydana geldiğinde otomatik olarak yeniden deploy sürecini gerçekleştirir. Haliyle böylece, yeni sürüm çıkışları otomatik ve hızlı bir şekilde cereyan edecektir.
- IAM Integration : AWS servisleriyle güvenli kimlik doğrulama ve yetkilendirme sağlar.
Bu ve bunlara benzer mühim özellikleri sayesinde AWS App Runner, AWS Fargate’e nazaran daha basit bir sistem ortaya koymaktadır. Evet; AWS Fargate, daha esnek olsa da bazı altyapı yönetimlerinin manuel yapılmasını gerektirmektedir. Ancak AWS App Runner, hızlı deploy süreçlerinde ve basit ya da orta ölçekli uygulamalarda daha çok tercih sebebimizdir. Daha karmaşık container yönetimi gerektiren iş yüklerinde ise AWS App Runner’dan ziyade AWS Fargate’e yönelerek elle yapılandırmalarda bulunabilir ve böylece de uygulamanın gereksinimlerine uygun seçenekleri daha detaylı bir şekilde optimize edebilirsiniz.
AWS App Runner; şu anda ap-south-1, eu-west-2, ap-northeast-1, us-east-1, us-west-2 vs. gibi bölgelerde kullanılmaktadır. Tam liste için şuraya göz atabilirsiniz.
Neden AWS App Runner’ı Kullanmalıyız?
AWS App Runner’ı tercih nedeni için her şeyden önce basitlik ve kullanım kolaylığını öne sürebiliriz. Yukarıdaki satırlarda bahsedildiği gibi altyapı yapılandırması, yük dengeleme, otomatik ölçeklendirme vs. gibi tüm yapılandırma sorumluluğu AWS tarafından üstlenilmekte ve ayrıca maliyet açısından da tüm bu süreç oldukça verimli seyretmektedir. App Runner, kullandıkça öde fiyatlandırma modelini uygulamaktadır ve bir yandan da sadece uygulama tarafından tüketilen bellek ve CPU için ücretlendirme durumu söz konusudur. Yani herhangi bir T zamanda, gelen bir request söz konusu değilse işte o taktirde size ayrılan CPU boşta kalacak ve dolayısıyla bunun için bir ücret ödemenize gerek kalmayacaktır. Öte yandan size ayrılan belleğin yanında deploy tetikleyicileri(deployment triggers) ve derleme zamanları(build times) için elbet ek ücretler söz konusu olacaktır. Bu da genel olarak, küçük bir uygulama için ayda yaklaşık $5’lık bir ücretlendirmeye tekabül edecektir. Gayet iyi değil mi? 🙂
Ne İnşa Edeceğiz?
İçeriğimiz süresince, herhangi bir alanda hizmet veren Asp.NET Core Web API uygulaması geliştirecek ve bu uygulama için AWS App Runner Service’de kaynak olarak kullanacağımız bir docker dosyası oluşturacağız. Devamında ise uygulamanın docker image’ını Elastic Container Registry‘ye göndereceğiz. Ayrıca, uygulamanın GitHub üzerinden nasıl source deploy edilebileceğini de keşfediyor olacağız. O halde hade başlayalım.
Bir Asp.NET Core Web API Uygulaması Geliştirme ve Dockerize Etme
İlk olarak bir Asp.NET Core Web API projesi oluşturalım ve içeriğine aşağıdaki gibi bir minimal api ekleyelim;
using Scalar.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi();
var app = builder.Build();
app.UseHttpsRedirection();
app.MapOpenApi();
app.MapScalarApiReference();
app.MapGet("/", () => "Hello World!");
app.Run();
Evet, üzerinde çalışacağımız uygulamamız bundan ibarettir diyebiliriz 🙂 Şimdi bu uygulama için bir Dockerfile dosyası oluşturup image tasarlayalım ve ardından bu image’i AWS ECR repository’sine gönderelim.
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src COPY *.csproj . RUN dotnet restore COPY . . RUN dotnet publish -c Release -o /app FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime WORKDIR /app EXPOSE 80 EXPOSE 443 COPY --from=build /app . ENTRYPOINT ["dotnet", "AWS.App.Runner.Example.dll"]
Görüldüğü üzere basit bir Dockerfile talimat dizisi oluşturmuş bulunuyoruz. Şimdi Dockerfile hazır olduğuna göre bir image oluşturup AWS repository’e gönderebiliriz.
Docker Image’i Private Amazon ECR’ye Publish Etme
Oluşturacağımız image’ı AWS repository’e gönderebilmek için öncelikle boş bir Elastic Container Repository oluşturmamız gerekmektedir. Bunun için aşağıdaki görselde olduğu gibi AWS Console üzerinden ECR’ye girelim.
Ve açılan sayfadan ‘Create a repository’ butonuna tıklayarak aşağıdaki gibi bir repository oluşturalım.
Evet, görüldüğü üzere AWS repository’i oluşturmuş bulunuyoruz. Şimdi oluşturduğumuz Dockerimage dosyasından bir image oluşturalım ve ardından bu image’ı Amazon ECR’de ki bu repository’e gönderelim. Bunun için proje dizinine odaklı bir terminal penceresinden aşağıdaki talimatları sırayla girelim;
-
aws ecr get-login-password | docker login --username AWS --password-stdin 905418427199.dkr.ecr.us-west-2.amazonaws.com/example-api
AWS ECR’de Docker ile oturum açıyoruz.
-
docker build -t awsapprunnerexample .
Bulunulan dizindeki Dockerfile dosyasından bir Docker image’ı oluşturuyoruz.
-
docker tag awsapprunnerexample:latest 905418427199.dkr.ecr.us-west-2.amazonaws.com/example-api
Oluşturulan Docker image’ını ECR repository’sine yüklemek için etiketliyoruz.
-
docker push 905418427199.dkr.ecr.us-west-2.amazonaws.com/example-api
Etiketlediğimiz Docker image’ını hedef ECR repository’sine gönderiyoruz.
Bu talimatlarda sırasıyla bulunduğunuzda aşağıdaki görseldeki gibi çıktılar edinilecektir;
Ve AWS Management Console’a geri dönüp ECR servisine tekrar göz atarsanız eğer, image’in repository’e yüklendiğini görebilirsiniz;
Güzel… Artık bu aşamadan sonra bu image’i AWS App Runner instance’ını başlatmak için kaynak olarak kullanabiliriz.
Uygulamayı Docker Image Üzerinden AWS App Runner’a Deploy Etme
AWS Management Console üzerinden AWS App Runner servisine gelelim,
ve açılan sayfadan ‘Create an App Runner service’ butonuna tıklayarak bir App Runner hizmeti oluşturalım.
Ardından sonraki açılacak sayfada hizmetin kaynağını tanımlamamız gerekecektir. Bunun için aşağıdaki ekran görüntüsünü inceleyebilirsiniz;
Dikkat ederseniz ‘Source and deployment’ altındaki ‘Repository type’ kısmında default olarak Container registry seçili gelmektedir. Burada Source code repository‘i seçerek isteğe bağlı bir şekilde Docker image’larını doğrudan GitHub repository’sinden veya herhangi bir başka source control sisteminden build edebilme şansına sahip olduğunuzu da bilmenizi isterim. Tabi bunun için de ekstradan iş yükü olacağını söylemekte fayda var. Misal olarak, GitHub repository’sini seçtiyseniz, GitHub hesabınızı AWS’ye bağlamanız gerekecek ve hesaptaki bir repository’i seçerek, uygulamayı çalıştırması için build komutlarını eklemeniz gerekecektir 🙂 Bizler bu noktada tüm bu uğraşları es geçiyor ve Container registry ile devam ediyoruz.
‘Provider’ kısmında ise Amazon ECR‘yi seçerek private ECR’de tutulan container image’larını seçip yolumuza devam ediyoruz. Container image URI‘de ise biraz önce oluşturduğumuz image’i bulup, seçiyoruz. Deployment ayarlarını ise Automatic olarak ayarlayıp, yeni bir image sürümü gönderildiği vakit AWS App Runner tarafından otomatik bir şekilde deploy’u gerçekleştiriyoruz. Tüm bunların dışında ECR erişimi için temel bir politikaya sahip IAM rolünü direkt kıssadan hisse yaparak oluşturuyoruz. Tabi bu noktada gereksinimlerimize göre gerekli izinlere sahip olan yeni bir IAM rolü oluşturarak da yola devam edebileceğinizi de söylemeden geçmeyelim.
Son olarak servisi, 1 vCPU(Virtual CPU) ve 2 GB(Virtual memory) olacak şekilde minimum değerlerde yapılandırıyor ve Dockerfile’da belirttiğimizin aksine port’u 8080 olarak ayarlıyoruz. Bunların dışında geri kalan her şeyi varsayılan ayarlarında bırakıp, deploy’u başlatıyoruz.
Bu deploy sürecinde; pipeline’ın oluşturulması, gerekli kaynakların sağlanması ve docker image’ının pull edilmesi için birkaç dakika gerekecektir. Her şey bittiği taktirde oluşturulan servis aşağıdaki gibi default domain’i eşliğinde ‘Running’ olarak gözükecektir.
Evet, hiç vakit kaybetmeksizin Default domain linkine tıklayarak testimizi gerçekleştirirsek,
böylece uygulamamızın AWS App Runner aracılığıyla başarıyla deploy edildiğini görmüş olacağız…
GitHub’ı Kullanarak Uygulamayı AWS App Runner’a Deploy Etme
Şimdi de, aynı uygulamayı GitHub’ı kullanarak tekrar deploy etmeyi inceleyeceğiz. Bunun için öncelikle uygulamayı GitHub’a gönderelim, ardından aşağıdaki gibi yeni bir servis create edelim.
Tabi bu sefer Source code repository‘i seçerek devam ediyoruz. Böylece seçtiğimiz ilgili GitHub repository’sine her yeni bir commit gönderildiğinde, pipeline otomatik tetiklenecek ve AWS App Runner, oluşturulan servise en son değişiklikleri otomatik deploy edecektir.
Velhasıl, devamında ise GitHub’a dair build ve start yapılandırmasında bulunmamız gerekmektedir. Bunun için de aşağıdaki görseldeki gibi bir yapılandırmada bulunalım;
Burada dikkat ederseniz eğer runtime olarak sadece .NET 6’yı görmekteyiz. Ne tuhaftır ki AWS, App Runner servisinde .NET 6’nın üst versiyonlarını hala runtime’da desteklememektedir (bknz : supported runtime versions) Haliyle bu durumda yapabileceklerimiz, ya uygulamanın altyapısını .NET 6’ya göre uyarlamak ya da hiç GitHub source’a bulaşmaksızın Dockerfile yapısından yani biraz önce gördüğümüz Container registry yönteminden istifade etmektir. Tabi bizler GitHub source’u burada içerik kalitesi için tecrübe edeceğimizden dolayı uygulamanın uygun versiyona dönüşümüyle devam edeceğiz.
Burada ayrıca dikkat ederseniz Build command ve Start command alanlarında uygulamanın build ve start yapılandırmalarını vermiş bulunuyoruz. Burada verilen kodlar sırasıyla aşağıdaki gibidir;
Build command
dotnet publish -c Release -o release
Start command
dotnet release/AWS.App.Runner.Example.dll --urls=http://0.0.0.0:8080
Bu yapılandırmalardan sonraki adımda, oluşturulacak bu servise bir isim verip;
ardından deploy’u gerçekleştirelim… Birkaç dakika daha bekledikten sonra servisimiz hazır olacaktır.
Böylece artık deploy edilmiş bu uygulamanın GitHub repository’sine yeni bir değişiklik/comment göndermeyi denediğimizde, AWS App Runner’ın tepkisini ve otomatik bir şekilde yeniden deploy sürecini başlattığını gözlemleyebilirsiniz.
Otomatik Ölçeklendirme
Son olarak otomatik ölçeklendirmeyi de test edip içeriğimizi sonlandıralım istiyorum. Bunun için aşağıdaki ekran görüntüsünde olduğu gibi App Runner üzerinden oluşturduğumuz servisi açalım ve Configuration sekmesine gelip Edit butonuna tıklayalım. Açılan sayfadan biraz aşağıdan Auto scaling alanına gelip, ‘Create new ASC’ butonuna tıklayıp otomatik ölçeklendirme yapılandırmasında bulunalım.
Yapılandırmamız aşağıdaki gibi olacaktır;
Burada görüldüğü üzere instance başına 5 request alınmakta ve maksimum 25 instance’a kadar ölçeklendirme gerçekleştirilmektedir.
Nihai olarak;
Tüm bunların dışında, oluşturduğumuz AWS App Runner servisine özel domain’imizi ekleyebilir ve uygulamanın health check yapılandırmasını HTTP ya da TCP protokolleri üzerinden sağlayabiliriz. Böylece küçük ve orta ölçekli uygulamalar için AWS App Runner’dan, kolay yapılandırılabilecek şekilde, container tabanlı desteği tam tadında alabiliriz. Ama tekrar söylemekte fayda vardır ki, büyük kapsamlı uygulamaların, teferruatlı yapılandırma ve optimizasyon ihtiyaçları söz konusu olacağı için işte bu taktirde AWS App Runner doğru seçenek olmayacaktır. Basitlik, otomasyon ve kullanım kolaylığı öncelikse ve web uygulamalarını hızlı bir şekilde deploy etmek ve yönetmek isteniyorsa AWS App Runner en uygun seçimdir diyebiliriz.
İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…
Not : Örnek çalışmaya aşağıdaki GitHub adresinden erişebilirsiniz.
https://github.com/gncyyldz/AWS.App.Runner.Example

Mac Os’ta build alıyorsanız
docker build --platform linux/amd64 -t apim/mainapi --platform linux/amd64kısmını belitrmeniz lazım yoksa healtcheck failed hatası alırsınız