Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Asp.NET Core Web API Uygulamasını Amazon EC2’de Host Etme

Merhaba,

Amazon EC2(Elastic Compute Cloud), Amazon Web Service’leri tarafından sunulan yüksek oranda ölçeklenebilir ve esnek bir cloud servisidir. Bu servis üzerinde kendi uygulamalarımızı çalıştırabileceğimiz, uygulamanın bellek veya CPU gibi gereksinimlerine uygun çeşitli türler üzerinden seçim yapabilecek olan instance adında sanal sunucular kiralanabilmekte ve ihtiyaç doğrultusunda da scale-up ya da scale-down ölçeklendirme yaklaşımları uygulanabilmektedir. Bizler, bu içeriğimizde bir Asp.NET Core Web API uygulamasını Amazon EC2’de host etme sürecini adım adım inceleyecek ve böylece DevOps ile ilgili çeşitli uygulamaların anlaşılmasına yardımcı olacak pek çok etkili kavramı ele alıyor olacağız.

AWS, bir yıl boyunca orta ölçekli uygulamaları host edebilmek için her ay 750 saate kadar Linux ve Windows instance’ını ücretsiz olarak sunmaktadır.

EC2 ismindeki 2, Amazon’un ikinci nesil bulut bilişim hizmetini ifade etmektedir. Bu hizmet, ilk nesil sabit ve esnek olamayan çözümlerden farklı olarak; dinamik ve elastik bir yapıda tasarlanmıştır ve kullanıcılara daha fazla esneklik, ölçeklenebilirlik ve maliyet optimizasyonu sağlamaktadır. Bu nedenle 2 sayısı, EC2’nin teknolojik gelişimini ve sunduğu yenilikleri vurgulamak için kullanılmıştır.

Uygulamayı Geliştirelim

Öncelikle bir Asp.NET Core Web API uygulaması geliştirerek içeriğimize giriş yapalım. Bizlerin geliştireceği uygulama basit bir ürün yönetim sistemi olacaktır. Şimdi adım adım bu uygulamayı geliştirmeye odaklanalım;

  • Adım 1 (Product Entity’sini Oluşturalım)
        public record Product(Guid Id)
        {
            public string Name { get; set; }
            public string? Description { get; set; }
            public decimal Price { get; set; }
        }
    
  • Adım 2 (Veritabanı & Migration İşlemlerini Yapalım)
    Veritabanı olarak PostgreSQL’i tercih ediyorum. Tabi ki de sizler, uygulamayı özelleştirebileceğiniz gibi veritabanını da kendinize özel seçebilirsiniz.

    Öncelikle aşağıdaki gibi bir DbContext nesnesi oluşturalım.

        public class ApplicationDbContext : DbContext
        {
            public ApplicationDbContext(DbContextOptions options) : base(options)
            {
            }
    
            public DbSet<Product> Products { get; set; }
        }
    

    Ve ‘Program.cs’ dosyasında aşağıdaki gibi veritabanı tanımlamasında bulunalım.

    builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("PostgreSQL")));
    

    Ardından Package Manager Console üzerinden add-migration mig_1 talimatı eşlinde bir migration oluşturalım. Şimdi bu migration’ı ister update-database komutuyla migrate edebilirsiniz, isterseniz de aşağıdaki gibi dinamik bir yaklaşım sergileyebilirsiniz.

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("PostgreSQL")));
    
    var app = builder.Build();
    
    #region Dynamic Migration
    using IServiceScope scope = app.Services.CreateScope();
    ApplicationDbContext dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    if (dbContext.Database.GetPendingMigrations().Any())
        await dbContext.Database.MigrateAsync();
    #endregion
    
    .
    .
    .
    
    app.Run();
    
  • Adım 3 (Operasyonel Endpoint’leri Oluşturalım)
    Temel ürün işlemlerini yürütecek operasyonlara sahip endpoint’leri aşağıdaki gibi minimal api olarak oluşturalım.

    .
    .
    .
    
    app.MapGet("/products", async (ApplicationDbContext dbContext) =>
    {
        return await dbContext.Products.ToListAsync();
    });
    
    app.MapGet("/products/{id}", async (ApplicationDbContext dbContext, string id) =>
    {
        Product? product = await dbContext.Products.FindAsync(id);
        if (product is null)
            return Results.NotFound();
        return Results.Ok(product);
    });
    
    app.MapPost("/products", async (ApplicationDbContext dbContext, CreateProductVM createProductVM) =>
    {
        Product product = new(Guid.NewGuid())
        {
            Name = createProductVM.Name,
            Description = createProductVM.Description,
            Price = createProductVM.Price
        };
    
        await dbContext.Products.AddAsync(product);
        await dbContext.SaveChangesAsync();
    });
    

İşte bu kadar… Bu adımlar sürecinde kullanılan viewmodel gibi teferruatlara ve istifade edilen kütüphanelere içeriğimizin sonunda paylaşmış olduğumuz github adresinden göz atabilirsiniz. Makalenin hacmini artık yersiz şişirmemek için bu detayları sizlere bırakıyorum.

Dockerizing

Ayrıca .NET’te gelen built-in container desteğinden de istifade edelim istiyorum. Bunun için aşağıdaki tanımları uygulamanın ‘.csproj’ dosyasındaki ilgili alana ekleyelim.

	<PropertyGroup>
		.
		.
		.

		<ContainerImageName>products-api</ContainerImageName>
		<ContainerImageTags>latest</ContainerImageTags>
		<PublishProfile>DefaultContainer</PublishProfile>
		<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
	</PropertyGroup>

Bu yapılandırmadan sonra uygulamanın Docker image’ını oluşturmak için aşağıdaki talimatın verilmesi yeterli olacaktır.

dotnet publish -c Release --self-contained

İçeriğimizin devamında Amazon EC2 instance’ında da aynı işlemleri gerçekleştirecek ve orada da bir Docker image’ı oluşturacağız. Şimdi Docker Compose ile bu oluşturduğumuz uygulamayı PostgreSQL ile ayağa kaldıracak bir talimat dizisi oluşturarak devam edelim.

PostgreSQL Container’ı İle Docker Compose

version: '3.8'
services:
    api:
        container_name: product-api
        image: products-api:latest
        environment:
            - ASPNETCORE_ENVIRONMENT=docker
            - ASPNETCORE_URLS=http://+:80
        ports:
            - 80:80
        depends_on:
            postgres:
                condition: service_healthy
    postgres:
        container_name: postgres
        image: postgres:15-alpine
        environment:
          - POSTGRES_USER=postgres
          - POSTGRES_PASSWORD=123456
        ports:
          - 5432:5432
        volumes:
          - postgres-data:/data/db
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U postgres"]
          interval: 10s
          timeout: 5s
          retries: 5
volumes:
  postgres-data:

Yukarıdaki docker compose içeriğine göz atarsanız eğer iki adet servisin yapılandırıldığını göreceksiniz. İlki, biraz önce oluşturduğumuz product-api isimli built-in container’dır. Bu ilk etapta local docker instance’ından çekilecektir. İçeriğimizin devamında Amazon EC2 instance’larında da çalıştırıldığını göreceğiz. İkinci servis ise PostgreSQL yapılandırmasını barındırmaktadır.

appsettings.docker.json

Bu işlem tamamlandıktan sonra uygulamamız için docker’a uygun yapılandırmayı barındıracak appsettings.docker.json dosyasını ekleyerek devam edelim.

{
  "ConnectionStrings": {
    "PostgreSQL": "Host=postgres;Port=5432;Database=ProductDB;Username=postgres;Password=123456;Include Error Detail=true"
  }
}

Böylece ASPNETCORE_ENVIRONMENT değeri docker olarak ayarlandığı taktirde uygulama bu dosya üzerinden yapılandırılacaktır.

Şimdi ise sıra EC2 container’ı oluşturmaya gelmiştir.

Amazon EC2 Linux Instance Oluşturma

Artık herşey hazır olduğuna göre bir Amazon EC2 Linux instance’ını ayağa kaldırabiliriz. Bunun için AWS Management Console üzerinden EC2’yi aratalım.
Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeArdından açılan sayfada ‘Launch instance’ butonuna tıklayalım.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeVe ardından ilgili instance’ı aşağıdaki gibi yapılandıralım.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeAsp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeBurada Key pair alanında ‘Create new key pair’ diyerek aşağıdaki gibi yeni bir tane oluşturalım.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeBurada key pair name olarak ‘admin’ değerini veriyoruz. Ayrıca dosya biçimi olarak .ppk’yı seçiyoruz. ‘Create key pair’ butonuna tıkladığımızda admin.ppk adında bir dosya indirilecektir. Bu daha sonradan tarafımızca Amazon EC2 instance’ına uzaktan bağlanmak için kullanılacağından dolayı bu dosyanın güvenli bir şekilde tutulduğundan emin olunmalıdır.

Devamında ise instance yapılandırmasını aşağıdaki gibi yapıp, ardından ‘Launch instance’ butonuna tıklayalım.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeAsp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeEvet, tüm bu işlemlerden sonraki adımımız ise makinemizden bu EC2 instance’ına bağlanmaktır. Bizler bunun için PuTTY’i kullanıyor olacağız. O halde buyurun devam edelim.

PuTTY İle EC2 Instance’ına SSH

Öncelikle bilmeyenler için PuTTY ne la? sorusunu cevaplandırarak devam edelim.

PuTTY, çeşitli ağ protokolleri için bir client yazılımıdır ve özellikle SSH(Secure Shell), Telnet, rlogin ve seri port bağlantıları gibi protokoller için kullanılmaktadır.

PuTTY’i kullanabilmek için https://www.putty.org adresinden indirilip, kurulması gerekmektedir.

PuTTY’i kurduktan sonra açalım ve ‘Connection’ -> ‘SSH’ -> ‘Auth’ -> ‘Credentials’ sekmesinden PPK dosyasını yükleyerek gerekli kimlik bilgileri yapılandırmasında bulunalım.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeDevamında ise ‘Session’ sekmesinden host bilgisini yazalım ve ‘Open’ diyerek bağlantıyı başlatalım.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeBu işlemden sonra aşağıdaki gibi ‘login as’ kısmı gelecektir.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeBurada ‘ec2-user’ değerini yazalım ve enter diyelim.

Vee gözümüz aydın 🙂 Artık Linux Instance’ına giriş yapmış bulunuyoruz…
Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeŞimdi bu instance’a Git, Docker, .NET Runtime vs. gibi ihtiyacımız olan tüm ortam kurulumlarını gerçekleştireceğiz.

Bunun için öncelikle sudo su talimatı eşliğinde super user’a geçiş yapalım.

Ardından yum install git talimatıyla git’in kurulumunu başlatalım.

yum install docker
sudo systemctl start docker.service
docker ps talimatları eşliğinde Docker’ı kuralım.

sudo yum install aspnetcore-runtime-7.0
sudo yum install dotnet-sdk-7.0
dotnet tool install --global dotnet-ef --version 7.0.19
. /etc/profile.d/dotnet-cli-tools-bin-path.sh
dotnet sdk check talimatları eşliğinde de .NET 7 runtime’ı ve SDK’yi kuralım.

Burada eğer ki yüklenen paketlerde bir hata, erişememe ya da tanımama durumu söz konusu olursa, Microsoft paket deposunu aşağıdaki talimatla eklemeli;
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
ve ardından depo listesini sudo yum update talimatıyla güncellemelisiniz.

Devamında ise docker-compose dosyasının çalışması için aşağıdaki talimatlar eşliğinde gerekli araçları yükleyelim.
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose version

Evet, şu ana kadar gerekli olan tüm araçlar yüklenmiştir. Şimdi sırada Github repository’sini instance volume içerisine klonlamak var. Bunun için yukarıdaki satırlarda geliştirdiğimiz ürün yönetim sistemi uygulamasını github’da yeni bir repository oluşturarak depolayalım. (bknz: https://github.com/gncyyldz/Amazon.EC2.Hosting.Example) Ardından aşağıdaki talimatlar eşliğinde hem uygulamayı github’dan çekelim hem de docker image’ını oluşturalım.
mkdir repos
cd repos
git clone https://github.com/gncyyldz/Amazon.EC2.Hosting.Example
cd Amazon.EC2.Hosting.Example
dotnet publish -c Release --self-contained
docker images
Burada yaptığımız çalışmayı özetlememiz gerekirse eğer; öncelikle ‘repos’ adında bir klasör oluşturduk ve ardından repository’mizi bu klasöre kopyaladık. Klonlama tamamlandıktan sonra proje klasörüne giderek uygulamayı publish ettik. Hatırlarsanız eğer önceki satırlarda .csproj dosyasında uygulama yayınlandığında docker image’ını oluşturacak spesifikasyonlarda bulunmuştuk. Haliyle bu işlem neticesinde gerekli docker image’ını oluşturmuş olduk.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeBu aşamadan sonra artık uygulama içerisindeki docker-compose dosyasını
docker-compose up -d talimatıyla çalıştırabiliriz. Tabi bunun için uygulamanın dizinine tam gelindiğinden emin olmalıyız…Asp.NET Core Web API Uygulamasını Amazon EC2’de Host Etme

Uygulamayı Herkes Tarafından Erişime Açık Hale Getirme

Bu aşamadan sonra artık yapılması gereken uygulamanın herkes tarafından erişime açık hale getirilmesidir. Bunun için aşağıdaki ekran görüntüsünde olduğu gibi AWS Management Console üzerinden EC2 instance’ına gelelim ve ‘Security’ üzerinden 80 portuna gelecek olan trafiğe izin verelim.Asp.NET Core Web API Uygulamasını Amazon EC2'de Host Etme

Dikkat!

Github’dan uygulamayı klonlama aşamasında aşağıdakine benzer hata alıyorsanız eğer;

unable to access ‘https://github.com/gncyyldz/Amazon.EC2.Hosting.Example/’: Failed to connect to github.com port 443 after 131206 ms: Couldn’t connect to server

İlgili EC2 instance’ının security groups alanından ‘Outbound rules’ sekmesine gelerek gelen tüm trafiğe aşağıdaki gibi rule tanımında bulunulması gerekmektedir!
Asp.NET Core Web API Uygulamasını Amazon EC2’de Host Etme

Test Etme

Artık yaptığımız bu çalışmayı test edebiliriz. Bunun için EC2 instance’ının public adresini kopyalayalım ve Postman üzerinden endpoint’lere testlerimizi gerçekleştirelim.Asp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeAsp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeAsp.NET Core Web API Uygulamasını Amazon EC2’de Host EtmeBurada özellikle dikkat edilmesi gereken nokta şudur ki, request atacağınız public adresin https değil http protokolüne sahip olmasına özen gösterilmelidir. Aksi taktirde istek neticesinde connect ECONNREFUSED hatası alırsınız.

Nihai olarak;
Bu içeriğimizde Asp.NET Core Web API mimarisinde geliştirdiğimiz bir uygulamayı Amazon EC2 Linux instance’ında host etmiş ve bunun için gerekli olan yapılandırmaları ele almış bulunuyor ve bunların yanında .NET 7’de gelmiş olan built-in container desteğini de tecrübe etmiş oluyoruz.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek projeye aşağıdaki github adresinden erişebilirsiniz.
https://github.com/gncyyldz/Amazon.EC2.Hosting.Example/

Bunlar da hoşunuza gidebilir...

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir