Load Balancing & kube-proxy #

Setiap kali traffic menuju sebuah Service di Kubernetes, ada mekanisme di balik layar yang memutuskan Pod mana yang akan menerima request tersebut. Komponen yang bertanggung jawab adalah kube-proxy — sebuah agen yang berjalan di setiap node dan mengimplementasikan logika routing Service. Memahami cara kerjanya penting untuk mendiagnosis masalah performa dan memilih konfigurasi yang tepat untuk cluster besar.

Apa yang Dilakukan kube-proxy #

kube-proxy tidak memproses traffic secara langsung — ia tidak berada di jalur data. Tugasnya adalah mengatur aturan jaringan di setiap node yang membuat traffic otomatis di-forward ke Pod yang tepat.

Cara kube-proxy bekerja:

1. kube-proxy watch API Server untuk perubahan Service dan Endpoints

2. Saat Service "api" dibuat dengan ClusterIP 10.96.45.12
   dan 3 Pod di belakangnya:

3. kube-proxy menulis aturan di setiap node:
   "Traffic ke 10.96.45.12:80 → forward ke salah satu dari:
    10.244.1.5:8080 (Pod A)
    10.244.2.3:8080 (Pod B)
    10.244.3.7:8080 (Pod C)"

4. Ketika Pod D ditambahkan atau Pod A dihapus,
   kube-proxy memperbarui aturan di semua node secara otomatis

kube-proxy tidak pernah “melihat” paket data yang lewat — aturan yang ia tulis langsung di-eksekusi oleh kernel Linux.


Mode iptables (Default) #

Mode default kube-proxy menggunakan iptables — mekanisme filtering paket di kernel Linux. Setiap Service dan Endpoints menghasilkan serangkaian aturan iptables.

Contoh aturan iptables untuk Service "api":

KUBE-SERVICES chain:
  -d 10.96.45.12/32 -p tcp --dport 80 → jump KUBE-SVC-API

KUBE-SVC-API chain (3 Pod, load balancing 1/3 probability):
  probability 0.33 → jump KUBE-SEP-POD-A
  probability 0.50 → jump KUBE-SEP-POD-B  (0.5 dari 2/3 yang tersisa = 1/3)
  no condition     → jump KUBE-SEP-POD-C  (fallthrough = 1/3)

KUBE-SEP-POD-A chain:
  -j DNAT --to-destination 10.244.1.5:8080

Algoritma load balancing: random dengan probabilitas equal — setiap Pod mendapat peluang yang sama untuk menerima koneksi baru. Ini bukan round-robin murni, tapi secara statistik distribusinya seimbang dalam skala besar.

Keterbatasan mode iptables:

Masalah dengan banyak Service (ribuan):

  Setiap request melewati SEMUA aturan iptables secara linear
  1000 Service = evaluasi ribuan aturan per paket
  10000 Service = puluhan ribu evaluasi → latensi naik signifikan

  Update rules tidak atomik:
  Saat Endpoints berubah, iptables harus di-flush dan ditulis ulang
  → brief period di mana aturan tidak konsisten
  → untuk cluster dengan update Endpoints sangat sering, ini bisa masalah

Mode IPVS #

IPVS (IP Virtual Server) adalah mode alternatif yang jauh lebih efisien untuk cluster besar. Ia menggunakan hash table untuk routing, bukan linear traversal.

Perbedaan kinerja:

Mode iptables:
  100 Service  → O(n) lookup → ~100 rule evaluations per paket
  10000 Service → ~10000 evaluations per paket → latensi tinggi

Mode IPVS:
  100 Service  → O(1) hash lookup → konstan
  10000 Service → O(1) hash lookup → tetap cepat

Update rules:
  iptables: flush semua → tulis ulang → non-atomik
  IPVS: update incremental → atomik → tidak ada downtime

IPVS juga mendukung lebih banyak algoritma load balancing:

Algoritma load balancing IPVS:
  rr   (round-robin)          — bergantian merata
  lc   (least connection)     — Pod dengan koneksi paling sedikit
  dh   (destination hash)     — hash berdasarkan destination
  sh   (source hash)          — hash berdasarkan source IP (session sticky)
  sed  (shortest expected delay)
  nq   (never queue)

Untuk mengaktifkan mode IPVS:

# ConfigMap kube-proxy (biasanya di kube-system)
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
data:
  config.conf: |-
    mode: "ipvs"
    ipvs:
      scheduler: "lc"    # algoritma least connection    
IPVS membutuhkan kernel module ip_vs, ip_vs_rr, dll yang harus tersedia di node. Di cloud managed Kubernetes (GKE, EKS, AKS), ini biasanya sudah tersedia. Untuk cluster on-premise, pastikan node sudah menginstall ipvsadm dan module tersebut di-load.

Session Affinity #

Secara default, kube-proxy mendistribusikan koneksi secara random. Untuk aplikasi yang membutuhkan sesi yang konsisten ke Pod yang sama (session stickiness), kamu bisa mengaktifkan session affinity:

apiVersion: v1
kind: Service
spec:
  selector:
    app: api
  sessionAffinity: ClientIP     # sticky berdasarkan IP client
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 3600      # session timeout: 1 jam
  ports:
  - port: 80
    targetPort: 8080

Session affinity bekerja dengan cara: koneksi dari IP client yang sama selalu dikirim ke Pod yang sama, selama Pod tersebut masih tersedia dan dalam periode timeout.

Keterbatasan session affinity berbasis ClientIP:

Masalah:
  → Client di belakang NAT atau load balancer eksternal
    terlihat punya IP yang sama → semua traffic ke satu Pod
  → Pod target mati → session break, koneksi ke Pod baru

Alternatif yang lebih baik untuk session:
  → Gunakan session store berbasis Redis/Memcached
     (lebih reliabel, tidak bergantung pada IP affinity)
  → Desain aplikasi sebagai stateless (session di client via JWT)

External Traffic Policy #

Untuk Service tipe NodePort dan LoadBalancer, ada pengaturan tambahan yang mempengaruhi bagaimana traffic dari luar cluster diproses:

spec:
  type: LoadBalancer
  externalTrafficPolicy: Cluster   # default
  # atau:
  externalTrafficPolicy: Local
externalTrafficPolicy: Cluster (default):
  Traffic masuk ke Node-1 bisa di-forward ke Pod di Node-2
  Pro: load balancing merata ke semua Pod
  Con: SNAT terjadi → Pod kehilangan IP asli client
       Tambahan network hop untuk traffic lintas node

externalTrafficPolicy: Local:
  Traffic hanya di-forward ke Pod di node yang sama
  Pro: Tidak ada SNAT → Pod bisa lihat IP asli client
       Tidak ada network hop tambahan
  Con: Load balancing tidak merata jika distribusi Pod tidak merata
       Node tanpa Pod tidak bisa serve traffic

Untuk aplikasi yang butuh IP asli client (untuk geolocation, logging, rate limiting), gunakan Local.


Ringkasan #

  • kube-proxy menulis aturan, tidak memproses traffic — ia tidak berada di jalur data; kernel Linux yang mengeksekusi aturan routing yang ditulis kube-proxy.
  • Mode iptables default, IPVS untuk cluster besar — iptables tidak efisien untuk ribuan Service karena traversal linear; IPVS menggunakan hash table dengan lookup O(1).
  • Load balancing random berbasis probabilitas — distribusi statistik merata di skala besar; bukan round-robin murni tapi hasilnya serupa.
  • IPVS mendukung lebih banyak algoritma — round-robin, least connection, source hash untuk session affinity yang lebih fleksibel.
  • Session affinity berbasis ClientIP punya keterbatasan — NAT dan load balancer eksternal bisa membuat semua client terlihat dari IP yang sama; lebih baik desain stateless atau gunakan external session store.
  • externalTrafficPolicy: Local untuk IP asli client — mencegah SNAT sehingga Pod bisa melihat IP asli client; tapi distribusi traffic bisa tidak merata.

← Sebelumnya: Network Policy   Berikutnya: CNI Plugin →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact