Linkerd ile Service Mesh

Ömer Burak Demirpolat
5 min readJul 27, 2022

Selamlar, bu yazı Linkerd ile Service Mesh konusunu ele alacak.

Linkerd Kubernetes üzerindeki mikro servislerimizin birbirleri ile olan trafiğini güvenli hale getiren, servisler arası iletişimi gözlemlememizi sağlayan bir service mesh aracı. Bunun yanında mikro servislerimizin iletişimde timeout, request retry, load balancing gibi durumları da yönetmemize imkan sağlıyor.

Bu yazı basit bir tutorial içerek yani detaylı olarak Linkerd nedir, service mesh nedir, servisler arası iletişim ve gözlemlenebilirlik nedir gibi konuları ele almayacak.

Gereksinimler:

  • Erişiminizin olduğu bir Kubernetes cluster’ı. Ben minikube kullanacağım.
  • Temel Docker ve Kubernetes bilgisi. İlk başta bahsettiğim gibi 2 adet servis yaratacağız ve bu servislerin Docker ile image yaratıp Kubernetes üzerine deploy edeceğiz.
  • Docker CLI, kubectl

Bu yazıda yapılacak işleri detaylandıralım.

  • Go ile bir adet HTTP server yazmak.
  • Go ile HTTP server’a belli aralıklarla istek atan/bağlanan bir client yazmak.
  • Docker ile server ve client’ın image’larını yazmak.
  • Yarattığımız imajı bir image registry yerine minikube’e yüklemek.
  • Linkerd CLI’ını kurmak.
  • Server ve client’ın Kubernetes için Deployment ve Service nesnelerini yazmak ve iki uygulamayı da deploy etmek.
  • Linkerd arayüzünde servisler arasındaki trafiği izlemek.

Şimdi gelelim Go ile ilk servisimizi yazmaya başlamaya.

Bu bir HTTP server olacak ve bu HTTP server 8081 portundan gelen bağlantıları dinleyecek. Ayrıca server 2 adet route’a sahip olacak.

“/” ve “/health” şeklinde.

Oldukça basit bir server 2 route’a gelen isteği de 200 status code’u ile yanıtlaycak. Response dönerken ise body içerisine hostname değişkeni ile bu yanıtın hangi pod’dan geldiğini basacak.

Şimdi sırada client uygulamamız var. Client uygulaması da epey basit. Bu uygulamanın amacı server’daki var olan iki adet route’a aralıklarla istek göndermek. Basit şekilde iki servis arasında bir trafik yaratmış olacağız.

Burada client’ın istek gönderdiği adres http://simple-server-svc.default:8081 şeklinde gözüküyor. Bu uygulamayı çalıştırdığımızda tabi DNS’imiz bu adresi tanımayacağı için ulaşamayacak ama ilerleyen kısımlarda Linkerd’ye bu servisleri eklediğimiz zaman Kubernetes pod’ları bu adrese ulaşabilecekler. Burada verilen servis isimlerinin detayını ilerleyen kısımlarda aktaracağım.

Şimdi iki uygulama için aşağıdaki Dockerfile sayesinde ayrı ayrı image yaratıyorum.

Bu arada çalışma dizinim son hali şu şekilde:

├── Dockerfile
├── client
│ ├── go.mod
│ ├── k8s.yaml
│ └── main.go
└── server
├── go.mod
├── k8s.yaml
└── main.go

Server ve Client için de Dockerfile aynı.

Server için:

docker build --file=./server/Dockerfile -t simple-server ./server

Client için:

docker build --file=./client/Dockerfile -t simple-client ./client

Şimdi bu yarattığımız image’ları minikube içerisine yükleyelim. Bir sonraki aşamada uygulamalarımızı minikube üzerindeki cluster’a deploy edeceğiz ve deploy ettiğimiz uygulamalar bu yarattığımız simple-server ve simple-client adlı image’lar ile podları yaratacak. Normalde bu image’ları bir image registry’e atıp podların bu remote registry’den üretilmesini sağlayabilirdik. Bunun için hub.docker.com veya GCR, ECR kullanmak gerekiyor. Ben lokalde işi çözmeyi tercih ettim.

minikube image load simple-server && minikube image load simple-client

Bu komut image’ların minikube’un cache’ine eklenmesini sağlayacak.

Sırada Linkerd CLI’ını kurmak ve Linkerd’yi Kubernetes cluster’ımıza eklemek var. Uygulamamızın Kubernetes deployment’ını yapmadan önce kurulumları yapmak iyi olacaktır.

Bu aşamada Linkerd’in web sitesinde yer alan kurulum talimatlarını izleyeceğim.

Brew ile linkerd CLI’ı cihazıma kuruyorum ve check komutu ile yüklemeyi doğruluyorum

brew install linkerd && linkerd check --pre

Şimdi ise Linkerd’yi cluster’ıma kurmalıyım. Bu aşama Linkerd CLI’ının install komutu cluster’ımıza kurulmak üzere bir çok obje getiriyor. Bu objeleri kubectl apply ile cluster’ımıza kuracağız. Tüm bu nesneler linkerd adındaki bir namespace’e yapılacak.

linkerd install | kubectl apply -f - && linkerd check

check komutu ile de kurulumu kontrol ediyoruz. Burada çıktıyı bir kontrol edebilirsiniz. Cluster’a kurulum aşamasında bir hata var ise check komutu bunu görmenizi sağlayacaktır.

Şimdi Linkerd arayüzünü cluster’ımıza kuralım ve erişmeyi deneyelim.

linkerd viz install | kubectl apply -f - && linkerd viz dashboard &

http://localhost:50750/ adresine giderek Linkerd arayüzüne ulaşabiliyorum. Bir sorun gözükmüyor. Artık uygulamalarımızın Kubernetes cluster’ı üzerine deployment işlemlerini yapabilirim.

Linkerd install aşaması esnasında cluster’ımıza bir mutation webhook kurulumu yapıyor. Kısaca bu webhook sayesinde biz bir deployment nesnesi yarattığımızda bu deployment tarafından üretilen pod’ların içerisine bir adet proxy container yerleştiriyor. Normalde bir deployment yaratıldığında ekstra bir annotation söz konusu değil ise sadece kendi uygulamamızın container’ı bulunur fakat mutation webhook sayesinde pod yaratılmadan önce bu webhook tarafından podumuza bir adet proxy container inject ediliyor. Peki ne iş yapıyor bu proxy container? Proxy container service mesh’in önemli elemanlarından birisi, normalde gelen istekler Kubernetes servisimizden direkt olarak uygulamamızın containerına giderken bu proxy container uygulamamıza gelen trafiği alıyor ve container’a gönderiyor. Tabi bu aşamada load balancing, routing, pod’un ayakta olmaması durumunda izlenecek senaryo gibi durumları da yönetiyor.

Şimdi uygulamalarımızın Kubernetes deployment’ları için gerekenleri yapalım.

Server için gerekli yaml dosyamız. İçerisinde Deployment ve Service nesneleri bulunuyor.

Burada göze çarpan, normal Kubernetes Deployment nesnelerinden ayıran bir bir tane durum var. Metadata altında bir tane annotation bulunuyor.

linkerd.io/inject: enabled

Bu annotation sayesinde podumuza proxy container inject etmek istediğimizi belirtiyoruz.

Şimdi server uygulamımzı deploy edelim.

kubectl apply -f serverk8s.yaml

Uygulamam çalışıyor mu kontrol etmek için önce pod’u bulup ardından port forwarding ile localhost’umdan erişmeyi deneyeceğim.

kubectl get pods
// simple-server-deployment-6bcb7cb655-7zmfw 2/2 Running

Pod’umun adı simple-server-deployment-6bcb7cb655–7zmfw şeklindeymiş.

Aslında pod içerisindeki 2 container’ında ayakta olduğunu görüyorum status’leri Running ama yine de uygulamama erişebiliyor muyum kontrol edeceğim.

kubectl port-forward simple-server-deployment-6bcb7cb655-7zmfw 8081:8081

Şimdi bir request oluşturalım ve yanıta bakalım.

curl localhost:8081// hi from simple-server-deployment-6bcb7cb655-7zmfw

Evet herhangi bir sorun gözükmüyor.

Şimdi client uygulamamız için deployment işlemlerini gerçekleştirelim.

Client uygulamamızdan giden trafiğin proxy üzerinden gerçekleşmesi için inject annotation’ını yine ekledim. Yine bu dosya hem Deployment hem de Service nesneleri içeriyor.

kubectl apply -f clientk8s.yaml

Artık deployment için gereken tüm işlemleri tamamladım. Linkerd arayüzüne giderek trafiği gözlemlemeye başlayabilirim.

http://localhost:50750/

adresine gittiğimde beni şöyle bir arayüz karşılıyor. Bu arayüzde namespace bazında Success Rate ve RPS bilgilerini görüntüleyebiliyorum.

Ben uygulamalarımı default namespace’ine deploy ettim. default namespace’ine tıklıyorum ve beni daha anlamlı bir ekran karşılıyor.

Burada simple-client-deployment podlarından simple-server-deployment tarafından üretilmiş olan servera bir trafik olduğunu görebiliyorum. Yine burada deployment bazında mesh olan servis sayısı ve success rate görebiliyorum.

Devamında deployment ve pod detaylarına giderek canlı olarak servisler arasındaki trafiği gözlemleyebilirsiniz.

Ayrıca Linkerd built-in Grafana ve Prometheus ile birlikte geliyor. Bu da böyle bir bilgi yani.

Bir sonraki yazıda yazdığımız server’ın 2. versiyonunu yazarak client tarafından gelen isteklerin bir kısmını simple-server’a bir kısmını da simple-server-v2'ye aktararak Canary Deployment aşamalarını uygulamaya çalışacağım.

Okuduğunuz için teşekkürler.

Bu yazıdaki ifadeler ve talimatların hiç biri official talimat/bilgi değildir, benim öğrendiğim kadarıyla aktardığım cümleleri okudunuz tamamı yanlış veya tamamı doğru olabilir.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response