Author SHA1 Message Date
josh 1a26a28876 feat(chart): release 1.2.6 with lb source ranges
Release Chart / release (push) Successful in 5s
deploy / build (push) Successful in 2m29s
2026-08-04 20:30:49 +03:30
josh d2b1a21a07 fix(lb): honor lb owner node annotation
deploy / build (push) Successful in 3m51s
2026-08-03 03:08:49 +03:30
7 changed files with 66 additions and 18 deletions
-4
View File
@@ -1,4 +0,0 @@
owner: KubelanCloud
git-repo: kks-provider-plugin
pages-branch: gh-pages
pages-index-path: index.yaml
+7 -8
View File
@@ -1,18 +1,17 @@
apiVersion: v2 apiVersion: v2
name: kks-provider-plugin name: kks-provider-plugin
description: Combined Kloud provider plugin chart (LoadBalancer + CSI) for kks clusters description: Combined Kloude provider plugin chart (LoadBalancer + CSI) for kks clusters
type: application type: application
version: 1.2.5 version: 1.2.6
appVersion: "1.1.2" appVersion: "1.2.0"
kubeVersion: ">=1.28.0-0" kubeVersion: ">=1.28.0-0"
home: https://github.com/KubelanCloud/kks-provider-plugin home: https://git.kloude.ir/kloude/kks-provider-plugin
sources: sources:
- https://github.com/KubelanCloud/kks-provider-plugin - https://git.kloude.ir/kloude/kks-provider-plugin
keywords: keywords:
- provider
- loadbalancer - loadbalancer
- csi - csi
- storage - storage
- kloud - kloude
maintainers: maintainers:
- name: Kloud Team - name: Kloude Tech Team
+1
View File
@@ -5,6 +5,7 @@ const (
AnnotationIP = "lb.kloude.ir/ip" AnnotationIP = "lb.kloude.ir/ip"
AnnotationVIP = "lb.kloude.ir/vip" AnnotationVIP = "lb.kloude.ir/vip"
AnnotationLBID = "lb.kloude.ir/id" AnnotationLBID = "lb.kloude.ir/id"
AnnotationNode = "lb.kloude.ir/node"
Namespace = "kube-system" Namespace = "kube-system"
) )
+22
View File
@@ -174,6 +174,7 @@ func (c *Controller) sync(ctx context.Context, key string) error {
Namespace: namespace, Namespace: namespace,
Name: name, Name: name,
Ports: ports, Ports: ports,
LoadBalancerSourceRanges: serviceLoadBalancerSourceRanges(svc),
}) })
if err != nil { if err != nil {
return err return err
@@ -191,6 +192,9 @@ func (c *Controller) sync(ctx context.Context, key string) error {
patch.Annotations[kloudlb.AnnotationIP] = ingressIP patch.Annotations[kloudlb.AnnotationIP] = ingressIP
patch.Annotations[kloudlb.AnnotationVIP] = vip patch.Annotations[kloudlb.AnnotationVIP] = vip
patch.Annotations[kloudlb.AnnotationLBID] = lb.ID patch.Annotations[kloudlb.AnnotationLBID] = lb.ID
if node := strings.TrimSpace(lb.Node); node != "" {
patch.Annotations[kloudlb.AnnotationNode] = node
}
patch.Status = corev1.ServiceStatus{ patch.Status = corev1.ServiceStatus{
LoadBalancer: corev1.LoadBalancerStatus{ LoadBalancer: corev1.LoadBalancerStatus{
Ingress: []corev1.LoadBalancerIngress{{IP: ingressIP}}, Ingress: []corev1.LoadBalancerIngress{{IP: ingressIP}},
@@ -276,6 +280,24 @@ func servicePortsToAllocateRules(svc *corev1.Service) ([]provisioner.AllocatePor
return out, nil return out, nil
} }
func serviceLoadBalancerSourceRanges(svc *corev1.Service) []string {
if svc == nil || len(svc.Spec.LoadBalancerSourceRanges) == 0 {
return nil
}
out := make([]string, 0, len(svc.Spec.LoadBalancerSourceRanges))
for _, item := range svc.Spec.LoadBalancerSourceRanges {
trimmed := strings.TrimSpace(item)
if trimmed == "" {
continue
}
out = append(out, trimmed)
}
if len(out) == 0 {
return nil
}
return out
}
func containsString(items []string, target string) bool { func containsString(items []string, target string) bool {
for _, item := range items { for _, item := range items {
if item == target { if item == target {
+17
View File
@@ -45,3 +45,20 @@ func TestServicePortsToAllocateRulesRejectsNoPorts(t *testing.T) {
t.Fatal("expected error for empty ports") t.Fatal("expected error for empty ports")
} }
} }
func TestServiceLoadBalancerSourceRanges(t *testing.T) {
svc := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{Namespace: "default", Name: "web"},
Spec: corev1.ServiceSpec{
LoadBalancerSourceRanges: []string{"203.0.113.0/24", " 198.51.100.8/32 ", ""},
},
}
ranges := serviceLoadBalancerSourceRanges(svc)
if len(ranges) != 2 {
t.Fatalf("ranges count = %d, want 2", len(ranges))
}
if ranges[0] != "203.0.113.0/24" || ranges[1] != "198.51.100.8/32" {
t.Fatalf("unexpected ranges: %#v", ranges)
}
}
+11
View File
@@ -147,6 +147,10 @@ func (s *Speaker) sync(ctx context.Context, key string) error {
s.stopLeading(key, vip) s.stopLeading(key, vip)
return nil return nil
} }
if owner := serviceOwnerNode(svc); owner != "" && owner != s.nodeName {
s.stopLeading(key, vip)
return nil
}
leaseName := leaseNameFor(key) leaseName := leaseNameFor(key)
leader, err := s.acquireLease(ctx, leaseName, vip) leader, err := s.acquireLease(ctx, leaseName, vip)
@@ -161,6 +165,13 @@ func (s *Speaker) sync(ctx context.Context, key string) error {
return s.ensureVIP(vip) return s.ensureVIP(vip)
} }
func serviceOwnerNode(svc *corev1.Service) string {
if svc == nil || svc.Annotations == nil {
return ""
}
return strings.TrimSpace(svc.Annotations[kloudlb.AnnotationNode])
}
func serviceExternalVIP(svc *corev1.Service) string { func serviceExternalVIP(svc *corev1.Service) string {
if svc.Annotations != nil { if svc.Annotations != nil {
if vip := strings.TrimSpace(svc.Annotations[kloudlb.AnnotationVIP]); vip != "" { if vip := strings.TrimSpace(svc.Annotations[kloudlb.AnnotationVIP]); vip != "" {
+2
View File
@@ -5,12 +5,14 @@ type LoadBalancer struct {
IP string `json:"ip"` IP string `json:"ip"`
Namespace string `json:"namespace"` Namespace string `json:"namespace"`
Name string `json:"name"` Name string `json:"name"`
Node string `json:"node,omitempty"`
} }
type AllocateRequest struct { type AllocateRequest struct {
Namespace string `json:"namespace"` Namespace string `json:"namespace"`
Name string `json:"name"` Name string `json:"name"`
Ports []AllocatePortRule `json:"ports,omitempty"` Ports []AllocatePortRule `json:"ports,omitempty"`
LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`
} }
type AllocatePortRule struct { type AllocatePortRule struct {