Bulut üzerinde koşan bir kümede type: LoadBalancer yazdığınız servis birkaç saniye içinde dış dünyadan erişilebilir bir adres alır. Bu adresi Kubernetes vermez; bulut sağlayıcısının controller katmanı verir. Bare-metal bir kümede o katman yoktur ve servis EXTERNAL-IP alanında <pending> olarak asılı kalır. MetalLB tam olarak bu boşluğu dolduran, CNCF bünyesinde geliştirilen bir proje.
Beklemede kalan servis
LoadBalancer tipi servis, kontrol düzlemine dış bir yük dengeleyici talebi gönderir. Talebi yerine getirecek cloud-controller-manager bulunmadığında adres atanamaz. NodePort ile idare edilebilir ama yüksek portlar, her node üzerinden açık port yönetimi ve temiz bir giriş adresinin yokluğu zamanla can sıkar. MetalLB, kümeye ait olmayan bir IP aralığını havuz gibi yönetip bu servislere dağıtır.
İki bileşen, iki mod
Kurulumdan sonra metallb-system namespace içinde iki ana parça oluşur. Controller, leader election ile tek kopya çalışır ve hangi servise hangi adresin verileceğine karar verir. Speaker ise DaemonSet olarak her node üzerinde koşar ve adresi ağa duyurur. Duyuru işinin nasıl yapılacağı iki temel moddan birine göre yürür: Layer 2 ve BGP.
Layer 2 modu tek lider üzerine kurulur
Layer 2 modunda speaker, servis adresine gelen isteklere ARP üzerinden (IPv6 tarafında NDP) yanıt verir. Her adres için bir node lider seçilir ve o node kendi MAC adresiyle VIP adına konuşur. Yani trafik önce tek node içine girer, oradan kube-proxy üzerinden podlara dağıtılır. Bu yüzden gerçek anlamda yük dengeleme değildir; adresin yaşadığı node bant genişliği tavanı belirler.
Buna karşılık kurulumu zor değildir. Router tarafında hiçbir yapılandırma istemez, düz Ethernet üzerinde çalışır. Lider node ölürse liderlik devri olur ve bu süre varsayılan ayarlarla on saniye civarındadır. Dahili ağ, lab ortamı ve dış trafik yoğunluğu sınırlı senaryolar için makul bir denge.
BGP tarafı
BGP modunda her speaker, ağ altyapısındaki router ile BGP oturumu kurar ve servis adreslerini route olarak duyurur. Router ECMP yapabiliyorsa trafik kümeye bağlı tüm nodelara yayılır; dağıtım akış bazlı hash ile yapılır, yani tek bir bağlantı hep aynı nodea düşer. BGP oturumları TCP 179 üzerinden kurulur. Node kaybolduğunda route withdraw edilene kadar küçük bir kesinti penceresi yaşanabilir, bu yüzden altyapı tarafında zamanlama ayarlarına dikkat etmek gerekir. Güncel sürümlerde BGP yığını FRR üzerinden yürür; en yeni sürümlerde bu katman frr-k8s olarak ayrıştı. Sürümler arası fark burada hızla değiştiği için kendi yüklediğiniz sürümün dokümanına bakın.
Kurulum
Helm en kestirme yol:
helm repo add metallb https://metallb.github.io/metallb
helm repo update
helm install metallb metallb/metallb -n metallb-system --create-namespace Alternatif olarak resmi depadaki native manifest uygulanabilir. Adres biçimi sürüme göre değişir: raw.githubusercontent.com/metallb/metallb altında, ilgili sürüm etiketine ait config/manifests/metallb-native.yaml dosyası hedeflenir. Sürümü sabitlemeden kopyalamak yerine kurduğunuz sürümün dokümanından adresi alın.
Adres havuzu tanımı
MetalLB 0.13 sonrasında havuz ve duyuru tanımı CRD üzerinden yapılır. Daha eski sürümlerde aynı iş ConfigMap ile yürütülüyordu; eski rehberleri okurken bu farkı akılda tutmak gerekir. Güncel API düzeninde önce bir IPAddressPool tanımlanır:
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ilk-havuz
namespace: metallb-system
spec:
addresses:
- 192.0.2.10-192.0.2.30 Sonra bu havuzun Layer 2 ile duyurulacağı belirtilir:
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ilk-duyuru
spec:
ipAddressPools:
- ilk-havuz Örneklerdeki 192.0.2.0/24 bloğu bilinçli olarak RFC 5737 belge aralığından seçildi. Kendi ortamınızda router tarafından kümeye yönlendirilen ya da dahilide serbest gerçek bir aralık vermeniz gerekir. Havuz tanımından sonra yeni bir LoadBalancer servisi oluşturulduğunda adres anında atanır.
BGP komşusu ve duyuru
BGP modunda router komşuluğu ve duyuru ayrı nesnelerle tanımlanır:
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
name: cekirdek-router
spec:
myASN: 64500
peerASN: 64512
peerAddress: 203.0.113.1 apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgp-duyuru
spec:
ipAddressPools:
- ilk-havuz ASN değerleri için 64512 ile 65534 arası RFC 6996 özel kullanım aralığıdır; lab ortamında serbestçe kullanılabilir. Router tarafında da aynı parametrelerle komşu tanımı yapılmalıdır. Topolojiye birden fazla komşu ve community etiketi eklenebilir; community için ayrı bir CRD mevcut.
Dağıtımı doğrulamak
Basit bir test servisi oluşturup kubectl get svc çıktısına bakmak yeterli. Dış adres artık pending değil, havuzdan atanmış bir IP olmalı. Layer 2 modunda istemci makinede ARP tablosuna bakıldığında VIP altında lider node MAC adresi görünür. Kontrol için kubectl describe svc çıktısındaki eventler de adres atama sürecini gösterir.
Küçük ama can sıkıcı notlar
kube-proxy IPVS modunda çalışıyorsa strictARP ayarı sorun çıkarabilir; resmi kurulum rehberi kube-system namespace indeki kube-proxy ConfigMap üzerinde strictARP: true değişikliğini tarif eder. Servis tarafında externalTrafficPolicy Local yapılırsa kaynak IP korunur, node üzerinde yerel pod yoksa trafik düşer. MetalLB katman dördüncü seviyede çalışır; host bazlı HTTP yönlendirmesi için Ingress controller gerekir, MetalLB adrese o controller için adres sağlar. Prometheus metrikleri de mevcut.
Layer 2 ile başlayıp trafik büyüdüğünde BGP tarafına geçmek yaygın bir yol. MetalLB iki modda da aynı havuz mantığını koruduğu için geçiş büyük bir yapı değişikliği değil, duyuru katmanını değiştirmek anlamına geliyor. Dış IP yönetimini küme içine almak isteyen herkes için el atması kolay bir proje.