Selam, başlıktan da anlaşılabileceği gibi bir süredir web podlarına isteklerin eşit bir şekilde dağılmadığının farkına vardık. Açıkcası podların cpu kullanımları durumunu gözlemlediğimizde dengesizlik fark ediliyordu.
Yukarıdaki görseli incelediğinizde en yüksek cpu tüketen 3 pod dışındakiler yatıyor, oluşturulma tarihlerine baktığınızda da belirsizlikler olduğunu gözlemleyebilirsiniz;
TL;DR: Kubernetes doesn’t load balance long-lived connections, and some Pods might receive more requests than others. If you’re using HTTP/2, gRPC, RSockets, AMQP or any other long-lived connection such as a database connection, you might want to consider client-side load balancing.
https://learnk8s.io/kubernetes-long-lived-connections
Kuberneteste isteklerin nasıl ilerilediğini inceleyelim;
3 podlu bir deployment, service oluşturduğumuzda genel şema aşağıdaki gibi;
Curl isteği yaptığımızı düşünelim. Biz isteği podların arkadasındaki servise yapıyoruz. Servis isteği podlara gönderiyor.
Sizde kendi ortamınızda çoklu poda sahip bir ortama a/b testi yapıp deneyebilirsiniz veya netstat ile kontrol sağlayabilirsiniz.
Client istek gönderdiğinde kube-proxy üzerinden podlara aktarılır. Kube proxy varsayılan olarak iptables kullanır.
k8s sunucularınızda teyit edebilirsiniz;
curl -v localhost:10249/proxyMode
Peki bu noktada biz podlara giden trafiği nasıl yöneteceğiz? Nasıl kurtulacağız yatan podlardan 😀
iptables load-balance için değil güvenlik koruması için tasarlanmıştır. Yine de isterseniz TCP load balancer olarak tanımlayabilirsiniz. Bakınız: https://scalingo.com/blog/iptables#load-balancing
3 podu olan bir uygulamamız olduğunu düşündüğünüzde kube-proxy aşağıdaki kuralları izler;
Ayrıca pod2’nin pod1’den sonra seçileceğinin garantisi de yoktur.
Çözüm;
Biz sorunu çözmek için istio ve linkerd denemelerinde bulunduk. Linkerd ilk geçiş için çok daha basit ve hızlı entegre edilebilir oldu.
Getting started ile başlarsanız genel kullanımı hızlıca test edebilirsiniz; https://linkerd.io/2.15/getting-started/
Basitçe anlatmak gerekirse linkerd cli’ı kuruyorsunuz. Sonra da k8s cluster üzerine crds kurulumu başlatmanız gerekiyor.
Mevcut uygulamanızın linkerd tarafından yönetilmesini istiyorsanız inject komutunu kullanabilirsiniz;
cat deployment.yml | linkerd inject - | kubectl apply -f -
veya annotation sizde ekleyebilirsiniz. inject komutu aslında podAnnotations’a bir satır ekliyor;
podAnnotations:
linkerd.io/inject: enabled
Unutmadan eğer hpa’yı aktif kullanıyorsanız; bu inject işlemi podlara 1 container daha bağlıyor (proxy). Fakat bu proxy containerında bir request limit belirlenmediğinden metrikleri çekerken Unknow hatası alabilirsiniz. Uygun config aşağıdaki gibi;
podAnnotations:
linkerd.io/inject: enabled
config.linkerd.io/proxy-cpu-limit: "1"
config.linkerd.io/proxy-cpu-request: "0.2"
config.linkerd.io/proxy-memory-limit: 2Gi
config.linkerd.io/proxy-memory-request: 128Mi
Bu adımdan sonra linkerd-viz ile de uygulamanın istekleri gözlemleyebilirsiniz.
Biraz da öncesi sonrası grafikleri iletip makaleyi sonlandırayım;
Karmaşayı anlayabilmek için kısa açıklama: Üstteki ekran alıntısında bazı podların 0 çizgisinde olduğunu gözlemleyebilirsiniz. Bazısınında yaklaşık 3 core cpu tükettiğini gözlemleyebilirsiniz. 17.05.2024
Bu ekran görüntüsü ise linkerd’e geçtikten sonra, neredeyse 0’da olan pod yok varsa da yeni açılmış pod olarak değerlendirebilirsiniz, genel kullanım ise 0.8’i geçmemiş.
Fark HPA’da da çok açık gözlemleniyor;
Kaynak: https://learnk8s.io/kubernetes-long-lived-connections https://linkerd.io/2.15/tasks/adding-your-service/ https://www.mdpi.com/1424-8220/22/8/2869 https://medium.com/@seifeddinerajhi/kube-proxy-and-cni-the-hidden-components-of-kubernetes-networking-eb30000bf87a https://scalingo.com/blog/iptables#load-balancing