@@ -148,14 +148,18 @@ const (
148148 // (for instance "80,443")
149149 serviceAnnotationLoadBalancerProtocolHTTP = "service.beta.kubernetes.io/scw-loadbalancer-protocol-http"
150150
151- // serviceAnnotationLoadBalancerCertificateIDs is the annotation to choose the the certificate IDS to associate
151+ // serviceAnnotationLoadBalancerCertificateIDs is the annotation to choose the certificate IDS to associate
152152 // with this LoadBalancer.
153153 // The possible format are:
154154 // "<certificate-id>": will use this certificate for all frontends
155155 // "<certificate-id>,<certificate-id>" will use these certificates for all frontends
156156 // "<port1>:<certificate1-id>,<certificate2-id>;<port2>,<port3>:<certificate3-id>" will use certificate 1 and 2 for frontend with port port1
157157 // and certificate3 for frotend with port port2 and port3
158158 serviceAnnotationLoadBalancerCertificateIDs = "service.beta.kubernetes.io/scw-loadbalancer-certificate-ids"
159+
160+ // serviceAnnotationLoadBalancerTargetNodeLabels is the annotation to target nodes with specific label(s)
161+ // Expected format: "Key1=Val1,Key2=Val2"
162+ serviceAnnotationLoadBalancerTargetNodeLabels = "service.beta.kubernetes.io/scw-loadbalancer-target-node-labels"
159163)
160164
161165const MaxEntriesPerACL = 60
@@ -276,6 +280,8 @@ func (l *loadbalancers) EnsureLoadBalancer(ctx context.Context, clusterName stri
276280 return nil , LoadBalancerNotReady
277281 }
278282
283+ nodes = filterNodes (service , nodes )
284+
279285 err = l .updateLoadBalancer (ctx , lb , service , nodes )
280286 if err != nil {
281287 klog .Errorf ("error updating loadbalancer for service %s: %v" , service .Name , err )
@@ -342,7 +348,6 @@ func (l *loadbalancers) EnsureLoadBalancerDeleted(ctx context.Context, clusterNa
342348 return l .deleteLoadBalancer (ctx , lb , service )
343349}
344350
345- //
346351func (l * loadbalancers ) deleteLoadBalancer (ctx context.Context , lb * scwlb.LB , service * v1.Service ) error {
347352 // remove loadbalancer annotation
348353 if err := l .unannotateAndPatch (service ); err != nil {
@@ -1737,3 +1742,63 @@ func getHTTPSHealthCheck(service *v1.Service, nodePort int32) (*scwlb.HealthChec
17371742 URI : uri ,
17381743 }, nil
17391744}
1745+
1746+ // Original version: https://github.com/kubernetes/legacy-cloud-providers/blob/1aa918bf227e52af6f8feb3fa065dabff251a0a3/aws/aws_loadbalancer.go#L117
1747+ func getKeyValueFromAnnotation (annotation string ) map [string ]string {
1748+ additionalTags := make (map [string ]string )
1749+ additionalTagsList := strings .TrimSpace (annotation )
1750+
1751+ // Break up list of "Key1=Val,Key2=Val2"
1752+ tagList := strings .Split (additionalTagsList , "," )
1753+
1754+ // Break up "Key=Val"
1755+ for _ , tagSet := range tagList {
1756+ tag := strings .Split (strings .TrimSpace (tagSet ), "=" )
1757+
1758+ // Accept "Key=val" or "Key=" or just "Key"
1759+ if len (tag ) >= 2 && len (tag [0 ]) != 0 {
1760+ // There is a key and a value, so save it
1761+ additionalTags [tag [0 ]] = tag [1 ]
1762+ } else if len (tag ) == 1 && len (tag [0 ]) != 0 {
1763+ // Just "Key"
1764+ additionalTags [tag [0 ]] = ""
1765+ }
1766+ }
1767+
1768+ return additionalTags
1769+ }
1770+
1771+ // Original version: https://github.com/kubernetes/legacy-cloud-providers/blob/1aa918bf227e52af6f8feb3fa065dabff251a0a3/aws/aws_loadbalancer.go#L1631
1772+ func filterNodes (service * v1.Service , nodes []* v1.Node ) []* v1.Node {
1773+ nodeLabels , ok := service .Annotations [serviceAnnotationLoadBalancerTargetNodeLabels ]
1774+ if ! ok {
1775+ return nodes
1776+ }
1777+
1778+ targetNodeLabels := getKeyValueFromAnnotation (nodeLabels )
1779+
1780+ if len (targetNodeLabels ) == 0 {
1781+ return nodes
1782+ }
1783+
1784+ targetNodes := make ([]* v1.Node , 0 , len (nodes ))
1785+
1786+ for _ , node := range nodes {
1787+ if node .Labels != nil && len (node .Labels ) > 0 {
1788+ allFiltersMatch := true
1789+
1790+ for targetLabelKey , targetLabelValue := range targetNodeLabels {
1791+ if nodeLabelValue , ok := node .Labels [targetLabelKey ]; ! ok || (nodeLabelValue != targetLabelValue && targetLabelValue != "" ) {
1792+ allFiltersMatch = false
1793+ break
1794+ }
1795+ }
1796+
1797+ if allFiltersMatch {
1798+ targetNodes = append (targetNodes , node )
1799+ }
1800+ }
1801+ }
1802+
1803+ return targetNodes
1804+ }
0 commit comments