İçeriğe geç

Playing with Service Mesh – Linkerd ve Azure Kubernetes Service

Bildiğimiz gibi Microsoft, bu yıl Barcelona KubeCon‘da bir çok yeniliklerini duyurdu. Bence bunlardan önemli bir tanesi ise SMI(Service Mesh Interface) idi.

İncelediğim kadarıyla SMI‘ın tanımı için kısaca, tıpkı AMQP‘de olduğu gibi “interoperability” konusunu service mesh’ler arasında sağlayabilmek diyebilirim. Özünde service mesh’ler için Kubernetes üzerinde standart bir interface sunmaktadır. Böylece service mesh için provider-lock durumuna düşmeden, istediğimiz teknolojiyi kullanabilmemiz için bir olanak, abstraction sağlamaktadır.

SMI‘ın duyurulmasının ardından, uzun süredir incelemek için aklımda olan Linkerd service mesh’i inceleyebilmek için bir fırsat buldum ve hakkında bir şeyler yazmak istedim.

Service Mesh, huh?

İlk olarak service mesh nedir ve bize neler sağlıyor, kısaca değinmek istiyorum.

Bildiğimiz gibi bir çok organizasyon günümüz teknolojisine ve marketine ayak uydurabilmek ve o marketten büyük bir pay alabilmek için, microservice mimarisine ayak uydurmaya, adapte olmaya çalışıyor.

Bu adaptasyon sürecinde ise asıl önemli olan nokta, birbirlerinden decoupled hale getirilmiş olan servislerin, birbirleriyle nasıl hızlı, resilient ve secure bir şekilde iletişim içerisinde olacaklarıdır. Elbette load-balancing, traffic management ve health monitoring de cabası. Bu gereksinimlerin bir çoğunu, zaten farklı tool’lar vasıtasıyla implemente ediyoruz. Örneğin resiliency konusunu, gerek API Gateway’ler, gerekse de Polly gibi bazı framework’ler vasıtasıyla uygulamaların içerisinde implemente ediyoruz.

Peki, service mesh ne sunuyor?

Service mesh ise, service-to-service communication’ını manage ederek, “resiliency“, “scalability“, “security” ve “monitoring” gibi bazı kavramları farklı çözümler ile ele almamız yerine, bu tarz network işlemlerini kodumuzdan decoupled etmemize olanak sağlıyor. Ayrıca bu gereksinimleri bize kendisi tek bir elden sunuyor.

Peki, Linkerd?

Linkerd, CNCF tarafından desteklenen kubernetes için open source bir service mesh’dir.

Çalışma şekline baktığımızda ise, transparent bir sidecar proxy instance’ı olarak her bir servis’in yanında konumlandığını görebiliriz. A servis’inden B servisini direkt olarak çağırmak yerine, B servis’inin local proxy’sini çağırarak, buradaki “service-to-service” communication complexitiy’lerini bizim için encapsulate etmektedir.

Genel hatlarıyla Linkerd’nin bazı key özellikleri:

  • Intelligent Load Balancing (HTTP/HTTP2, gRPC): Request’leri en hızlı endpoint’e gönderebilmek için EWMA (Exponentially Weighted Moving Average) adında bir algoritma kullanmaktadır
  • Automatic Retries and Timeouts
  • Automatic mTLS
  • Powerfull Telemetry and Monitoring features: Observability için önemli özelliklerinden bir tanesi)
  • Dashboard and Grafana

Mimarisi hakkında daha detaylı bilgiye, buradan erişebilirsiniz.

Ön Hazırlık

Linkerd‘nin kurulum işlemine geçmeden, öncelikle bir kubernetes cluster’ına ihtiyacımız var. Ben bu noktada, Azure‘un managed Kubernetes Service‘inden yararlanacağım. Eğer Azure Kubernetes Service‘e sahip değilseniz, buradan oluşturabilirsiniz.

İlk önce aşağıdaki komut satırı ile Azure‘a login olalım.

NOT: Bu işlemler için Azure CLI‘ın kurulu olması gerekmektedir. Değilse, buradan erişebilirsiniz.

Ardından aşağıdaki komut satırı ile de, cluster’a erişebilmek için gerekli credential’ları alalım.

Şimdi linkerd‘nin kurulumu için hazırız.

Kurulumu gerçekleştirebilmek için, buradaki ilk 3 adımı tamamlamamız gerekiyor. Adımları tamamladıktan sonra her şeyin yolunda gittiğinden emin olabilmek için ise, aşağıdaki komut satırını kullanalım.

Ardından aşağıdaki gibi bir sonuç görüyor olmalıyız.

Let’s Play!

Artık mesh’lemeye hazırız. Örnek gerçekleştirebilmek adına, aşağıdaki gibi 3 adet içerisinde swagger barındıran basit API’lar geliştirdim.

Yukarıda görmüş olduğumuz product response’unu alabilmemiz için, “Product.Gateway.API” bizim için hem “Product.API” a hem de “Price.API” a request gönderecek. İlgili response’ları aggregate ettikten sonra ise bize full product response’unu dönüyor olacak.

API‘lara buradan erişebilirsiniz.

İlk olarak “Product.Gateway.API” ın “ProductsController” ını inceleyelim.

Get” method’u içerisinde basit olarak, product detay’larını ve fiyat bilgilerini alabilmek için, ilgili API‘lara request gönderiyoruz. API base URL‘lerini ise, configuration üzerinden okuyoruz. Kubernetes üzerine API‘ları deloy edeceğimiz zaman, bu API URL‘lerini environment variable olarak set ediyoruz olacağız.

API‘ları dockerize edebilmek için ise, buradaki ilgili Dockerfile‘ları kullanalım.

Product.Gateway.API” için örnek Dockerfile:

Ben container registry olarak Azure Container Registry servis’ini kullanacağım.

Aşağıdaki komut satırı ile image’leri oluşturalım ve container registry’e push edelim.

Kubernetes üzerine deployment işlemi için ise, buradaki yaml file’larını kullanacağız.

Product.Gateway.API” için örnek deployment ve service file’ı:

API‘ları, “linkerd-test” isimli namespace altına deploy edeceğiz. “Product.Gateway.API” içerisinde ilgili API URL‘lerini environment variable olarak set edeceğimizi söylemiştik. Dikkat edersek “env” section’ı altında, hem “Product” hem de “PriceAPI‘ının service adreslerini set ettik.

Şimdi 3 API‘ın da deployment işlemlerini, ilgili yaml file’ları ile gerçekleştirelim.

Deployment’ların başarıyla gerçekleşip gerçekleşmediğini aşağıdaki gibi kontrol edelim.

Şimdilik her şey yolunda görünüyor.

Birde API‘ları test edelim. Bunun için “Product.Gateway.API” ının dışarıya expose olduğu service adresini almamız gerekiyor.

NOT: External IP adresi alması bir kaç dakika sürebilir.

Test işlemini gerçekleştirebilmek için, “Product.API” ve “Price.API” içerisine id’si “1” olan dummy bir product eklemiştim.

Test edebilmek için, “Product.Gateway.API” a aşağıdaki gibi bir request gönderelim ve sonucuna bir bakalım.

Harika, API‘lar da çalışıyor.

Şimdi mesh’leyebilmek için tek yapmamız gereken, linkerd‘yi API‘lara inject etmek. Bu işlemi gerçekleştirebilmek için ise, aşağıdaki gibi linkerd‘nin CLI‘ından faydalanacağız.

Yukarıdaki komut satırı ile, “linkerd-test” namespace’i altındaki uygulamalarımıza, linkerd’yi inject ediyoruz.

Şimdi linkerd‘nin dashboard’u üzerinden, neler oluyor bir bakalım.

Dashboard’a erişebilmek için:

Overview kısmında bizi yukarıdaki gibi bir ekranla karşılıyor. Burada deployment ve pod’ları görebiliyoruz. Ayrıca hangi service’leri mesh’lediğimizi de görebilmek mümkün.

En sevdiğim kısımlardan birisi ise metric‘ler. Her service’e özel “Success Rate“, “RPS” ve “Latency” gibi bilgilerini görebiliyoruz.

Şimdi ilk giriş noktası olan “Product.Gateway.API” için, “Deployments” bölümü altındaki “product-gateway-api-deploy” deployment’ına tıklayalım ve detaylarına bir bakalım.

Ardından biraz metric görebilmek için, aşağıdaki gibi “Product.Gateway.API” a biraz request gönderelim. Ben bu işlem için ApacheBench kullanacağım.

En sevdiğim diğer bir kısım ise, automatic service dependency map‘i ve live traffic bilgilerini bize sunması. Dependency map’ine bakarsak, “product-gateway-api” ın hem “price-api” hem de “product-api” ile bağlantılı olduğunu görebiliriz.

Ayrıca “LIVE CALLS” sekmesinden, o anda gerçekleşen call’ların sample’larını da görebiliriz.

Peki, değinmek istediğim güzel bir konu daha var. Route-based runtime metric‘leri ve retry‘lar.

Service Profiles

Linkerd içerisinde önemli konulardan bir tanesi de service profile’larıdır. Service profile’ları, linkerd‘ye ilgili service hakkında ek bilgiler sunan custom bir kubernetes resource’udur.

Service profile’larını tanımlayarak, linkerd‘nin bize her bir service için “route-based runtime metrics” verebilmesini sağlayabiliriz. Ayrıca “retries” ve “timeouts” gibi feature’larını da etkinleştirebiliriz.

Service profile’larını tanımlayabilmenin “Swagger“, “Protobuf“, “Auto-Creation” ve “Template” gibi bir kaç farkı yöntemi mevcut. Ben API‘ları geliştirirken swagger implemente ettiğim için, service profile tanımlayabilmek için swagger yöntemini kullanacağım.

API‘ların ilgili swagger file’larına, buradan erişebilirsiniz.

Route-based Metrics

Profile tanımlayabilmek için, aşağıdaki komut satırını kullanacağız.

Evet, service profile’ları oluşmuş durumda. Şimdi route-based metric’leri görebileceğiz.

Tekrardan “Product.Gateway.API” a biraz request gönderelim. Bu sefer deployments ekranından “price-api-deploy” un “ROUTE METRICS” tab’ına bir bakalım.

Gördüğümüz gibi, service profile ile route-based metric’leri görebiliyoruz. Şimdi birde retry’ları nasıl tanımlayabiliriz, ona bir bakalım.

Retries

Örneğin, “Price.API” ın “Get” endpoint’ine gelen request’lerin bazılarının faile’a düştüğünü varsayalım ve otomatik olarak retry özelliğini etkinleştirmek istiyoruz.

Bunu gerçekleştirebilmek için, aşağıdaki gibi oluşturmuş olduğumuz service profile’ını edit’leyerek, ilgili route için “isRetryable” variable’ını eklememiz gerekmektedir.

Hepsi bu kadar.

Dilerseniz customize edebilmek için, “Retry Budget” mekanizmasını da kullanabilirsiniz. Detaylı bilgiye, buradan ulaşabilirsiniz. API kodlarına herhangi bir müdehale etmeden, “retry” ve “timeouts” gibi fonksiyonalite’leri ekleyebilmek, güzel bir capability.

Son olarak değinmek istediğim bir diğer konu ise, Grafana desteği. Live metric’lerin yanında, geçmiş metricleri’de Prometheus ve Grafana desteği ile visualize edebilmek mümkündür.

Sonuç

Service mesh, microservice mimarileri için önemli bir infrastructure layer’dır. Network’ü abstract ederek, distributed mimarilerin challenge’larını (reliability, security, monitoring, etc…), kodumuz içerisindeki complexity’i arttırmadan handle etmemize yardımcı olmaktadır. Linkerd2 diğer service mesh’lere göre henüz tüm özelliklere sahip olmasa da, özellikle intelligent load balancing’i (low-latency) ile kullanabileceğimiz iyi bir service mesh seçeneğidir.

Demo app: https://github.com/GokGokalp/service-mesh-linkerd-sample

Kaynaklar

https://linkerd.io/2/getting-started/
https://www.zdnet.com/article/what-is-a-service-mesh-and-why-would-it-matter-so-much-now/

Bu makale toplam (353) kez okunmuştur.

10
0



Tarih:.NET CoreArchitecturalASP.NET CoreAzureContainerizingMicroservices

3 Yorum

  1. Mehmet Mehmet

    Hocam şöyle bir durumda nasıl bir yol izlememiz lazım. price ve product servislerinin authorize ile erişmemiz gerektiğini düşünürsek authorize işlemini ProductGateway üzerinde mi yapmamız lazım yoksa güvenlik açısından product ve price servislerinde ayrı ayrı yapmak mı daha doğru?

    • Selam, benim görüşüm ilgili API’lar ayrı ayrı authorization işlemini kendisi gerçekleştirmeli. Örneğin, Price API içerisinde kullanıcının fiyat bilgisini alabilme claim’i olabilir, fakat update etme claim’i olmayabilir. O yüzden ilgili API’ın kendisinin gerçekleştirmesi daha doğru olacaktır.

  2. bilal islam bilal islam

    nacizane detayli bilgi meraklisina docker routing mesh loadbalancer algoritmasi …

    Bu arada yalin bir anlatim olmus emegine saglik 🙂

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.