Calico ile Production'da QoS Ayarı
Selamlar, bu yazımda Calico üzerinde pod bazında bandwidth ve QoS (Quality of Service) ayarlarına bakacağız. Multi-tenant cluster'larda gürültücü komşuyu (noisy neighbor) susturmak için en pratik yollardan biri bu, ama altta neyin döndüğünü bilmeden annotation eklemek bazen sandığınız sonucu vermiyor. Hadi adım adım gidelim.
QoS neden lazım?
Bir Kubernetes node'unda onlarca pod aynı fiziksel NIC'i paylaşır. Tek bir pod'un backup job'u, log shipper'ı veya bozuk bir retry döngüsü kalkıp 1 Gbps'lik hattı doldurursa, aynı node'daki diğer pod'ların latency'si bozulur. Şahsi kanaatim, çoğu prod cluster'ında en az iki sınıf trafik vardır: kritik (API, DB sync) ve geri kalan herkes. QoS bu ikisini ayırmaya yarıyor.
Calico, bu işi sıfırdan icat etmiyor. Linux'un eski dostu tc (traffic control) ile pod'un veth interface'ine token bucket filter (TBF) takıyor. Yani altta gerçekten klasik Linux trafik sekmesi var; Calico sadece bunu Kubernetes annotation'larına bağlıyor.
Annotation ile bandwidth limit
En basit kullanım, pod'a ya da deployment template'ine standart Kubernetes annotation'larını eklemek. Calico v3.20+ ve bandwidth CNI plugin'i etkinse bu kadarı yeter:
apiVersion: v1
kind: Pod
metadata:
name: log-shipper
annotations:
kubernetes.io/ingress-bandwidth: '10M'
kubernetes.io/egress-bandwidth: '10M'
spec:
containers:
- name: app
image: nginx
Burada 10M saniyede 10 megabit demek, megabyte değil. İlk başlarda ben de bunu karıştırmıştım, fark ettiğimde limit dediğim değerin 8 katı geçtiğini gördüm. Bir başka detay: bu değerler veth pair'ine TBF olarak yazılır, yani burst için ekstra bir buffer da otomatik hesaplanır. Çok kısa süreli sıçramalara izin verir, sürekli üst üste gönderirseniz hız sabit limitte kalır.
tc tarafında ne oluyor?
Pod ayağa kalkınca Calico, node üzerinde cali<hash> adıyla bir veth interface yaratıyor. Annotation varsa CNI bandwidth plugin bu interface'e tc qdisc takıyor. Görmek için node'a girip şunu çalıştırabilirsiniz:
tc qdisc show dev cali1234abcd
tc class show dev cali1234abcd
Çıktıda tbf qdisc'ini ve rate 10Mbit burst <Burst> latency <Lat> satırını görmelisiniz. Burst değeri otomatik seçiliyor; çok küçük olursa kısa TCP burst'lerinde drop yer, çok büyük olursa limit gevşek davranır. Pratikte default'lar makul; agresif bir tuning ihtiyacın yoksa karıştırmayın.
iperf3 ile doğrulamak da kolay:
kubectl run iperf-srv --image=networkstatic/iperf3 -- iperf3 -s
SRV_IP=$(kubectl get pod iperf-srv -o jsonpath='{.status.podIP}')
kubectl exec log-shipper -- iperf3 -c ${SRV_IP} -t 10
10 saniyelik testte throughput'un 10 Mbit civarına oturduğunu görmelisiniz. Gözlemlediğiniz değer 9.5-9.9 Mbit arasındaysa her şey yolunda; TBF tam tepe değeri vermez, hep biraz altında dolaşır.
Multi-tenant cluster icin oneriler
Tek tek pod'lara annotation eklemek küçük cluster'da iş görür, ama 50 takımın yaşadığı yerde sürdürülemez. Bana sorarsanız şu üç şeyi standartlaştırın:
- Namespace bazlı varsayılanlar: Mutating admission webhook ile namespace label'ına göre annotation enjekte edin.
tier=batchnamespace'leri 50M,tier=critical500M gibi. - Deployment template'lerine zorunlu kılın: OPA/Kyverno ile annotation'sız pod kabul etmeyin. Annotation yoksa varsayılan limit uygulansın.
- Egress'i ingress'ten daha sıkı tutun: Çoğu noisy neighbor sorunu egress kaynaklı, içeri gelen trafiği bu kadar sıkı kısmak zorunda değilsiniz.
Tabii bu kuralları yazmadan önce bir hafta cluster'ı sadece izleyin; hangi pod'un ne kadar harcadığını bilmeden limit basmak çoğu zaman gerçek workload'u kırar.
Sik karsilasilan tuzaklar
10Mile10Mikaristirmak: Kubernetes bandwidth annotation'larında binary suffix (Mi) yok, hep decimal.10M= 10 Mbit/s.- CNI bandwidth plugin kapali olmasi: Calico kurulumunda
bandwidthplugin etkin degilse annotation'lar sessiz sedasiz yok sayilir.tc qdisc showciktisi bos geliyorsa kontrol edin. - HostNetwork pod'lara uygulamaya calismak: HostNetwork modunda pod node'un kendi interface'ini kullanir, veth yoktur, dolayisiyla TBF takilacak yer de yok. Annotation gorunur ama etkisiz.
- Burst'u sifira cekmek: 'Limit cok sikiysa daha temiz olur' diye burst'u kucultmek TCP'yi yere serer. Default'a guvenin.
Izleme
Limit koyduktan sonra ne kadar drop olduğunu görmek isteyebilirsiniz. Node üzerinde tc -s qdisc show dev caliXXXX komutu cumulative dropped ve overlimits sayaçlarını verir. Prometheus tarafında node_exporter varsa tc collector'unu açın; ya da daha derli toplu bir veri için topluluk tarafından yazılan tc-exporter benzeri çözümlere bakın. Kritik servislerde overlimits artıyorsa limiti gevşetmek ya da workload'u başka node'a almak gündeme gelir.
Kapanis
Bu yazıda Calico'nun pod bandwidth annotation'larıyla nasıl QoS uyguladığına, altta tc token bucket filter'ının nasıl devreye girdiğine ve multi-tenant cluster'larda neye dikkat edilmesi gerektiğine baktık. Bence küçük cluster'larda annotation yeter; iş büyüdükçe webhook + policy ile zorlamak şart oluyor. Umarım faydalı olur, bir sonraki yazıda görüşmek üzere.
