@@ -101,6 +101,12 @@ const (
101
101
// See https://nip.io
102
102
defaultProxyHostnameSuffix = "nip.io"
103
103
ServiceAnnotationLoadBalancerID = "loadbalancer.openstack.org/load-balancer-id"
104
+
105
+ // Octavia resources name formats
106
+ lbFormat = "%s%s_%s_%s"
107
+ listenerFormat = "listener_%d_%s"
108
+ poolFormat = "pool_%d_%s"
109
+ monitorFormat = "monitor_%d_%s"
104
110
)
105
111
106
112
// LbaasV2 is a LoadBalancer implementation based on Octavia
@@ -514,20 +520,17 @@ func (lbaas *LbaasV2) createFullyPopulatedOctaviaLoadBalancer(name, clusterName
514
520
}
515
521
516
522
for portIndex , port := range service .Spec .Ports {
517
- listenerCreateOpt := lbaas .buildListenerCreateOpt (port , svcConf )
518
- listenerCreateOpt .Name = cutString (fmt .Sprintf ("listener_%d_%s" , portIndex , name ))
523
+ listenerCreateOpt := lbaas .buildListenerCreateOpt (port , svcConf , cpoutil .Sprintf255 (listenerFormat , portIndex , name ))
519
524
members , newMembers , err := lbaas .buildBatchUpdateMemberOpts (port , nodes , svcConf )
520
525
if err != nil {
521
526
return nil , err
522
527
}
523
- poolCreateOpt := lbaas .buildPoolCreateOpt (string (listenerCreateOpt .Protocol ), service , svcConf )
528
+ poolCreateOpt := lbaas .buildPoolCreateOpt (string (listenerCreateOpt .Protocol ), service , svcConf , cpoutil . Sprintf255 ( poolFormat , portIndex , name ) )
524
529
poolCreateOpt .Members = members
525
530
// Pool name must be provided to create fully populated loadbalancer
526
- poolCreateOpt .Name = cutString (fmt .Sprintf ("pool_%d_%s" , portIndex , name ))
527
531
var withHealthMonitor string
528
532
if svcConf .enableMonitor {
529
- opts := lbaas .buildMonitorCreateOpts (svcConf , port )
530
- opts .Name = cutString (fmt .Sprintf ("monitor_%d_%s" , port .Port , name ))
533
+ opts := lbaas .buildMonitorCreateOpts (svcConf , port , cpoutil .Sprintf255 (monitorFormat , portIndex , name ))
531
534
poolCreateOpt .Monitor = & opts
532
535
withHealthMonitor = " with healthmonitor"
533
536
}
@@ -598,24 +601,14 @@ func (lbaas *LbaasV2) GetLoadBalancer(ctx context.Context, clusterName string, s
598
601
599
602
// GetLoadBalancerName returns the constructed load balancer name.
600
603
func (lbaas * LbaasV2 ) GetLoadBalancerName (_ context.Context , clusterName string , service * corev1.Service ) string {
601
- name := fmt .Sprintf ("%s%s_%s_%s" , servicePrefix , clusterName , service .Namespace , service .Name )
602
- return cutString (name )
604
+ return cpoutil .Sprintf255 (lbFormat , servicePrefix , clusterName , service .Namespace , service .Name )
603
605
}
604
606
605
607
// getLoadBalancerLegacyName returns the legacy load balancer name for backward compatibility.
606
608
func (lbaas * LbaasV2 ) getLoadBalancerLegacyName (_ context.Context , _ string , service * corev1.Service ) string {
607
609
return cloudprovider .DefaultLoadBalancerName (service )
608
610
}
609
611
610
- // cutString makes sure the string length doesn't exceed 255, which is usually the maximum string length in OpenStack.
611
- func cutString (original string ) string {
612
- ret := original
613
- if len (original ) > 255 {
614
- ret = original [:255 ]
615
- }
616
- return ret
617
- }
618
-
619
612
// The LB needs to be configured with instance addresses on the same
620
613
// subnet as the LB (aka opts.SubnetID). Currently, we're just
621
614
// guessing that the node's InternalIP is the right address.
@@ -1079,55 +1072,56 @@ func (lbaas *LbaasV2) ensureFloatingIP(clusterName string, service *corev1.Servi
1079
1072
func (lbaas * LbaasV2 ) ensureOctaviaHealthMonitor (lbID string , name string , pool * v2pools.Pool , port corev1.ServicePort , svcConf * serviceConfig ) error {
1080
1073
monitorID := pool .MonitorID
1081
1074
1082
- if monitorID != "" {
1083
- monitor , err := openstackutil .GetHealthMonitor (lbaas .lb , monitorID )
1084
- if err != nil {
1085
- return err
1086
- }
1087
- //Recreate health monitor with correct protocol if externalTrafficPolicy was changed
1088
- createOpts := lbaas .buildMonitorCreateOpts (svcConf , port )
1089
- if createOpts .Type != monitor .Type {
1090
- klog .InfoS ("Recreating health monitor for the pool" , "pool" , pool .ID , "oldMonitor" , monitorID )
1091
- if err := openstackutil .DeleteHealthMonitor (lbaas .lb , monitorID , lbID ); err != nil {
1092
- return err
1093
- }
1094
- monitorID = ""
1095
- }
1096
- if svcConf .healthMonitorDelay != monitor .Delay ||
1097
- svcConf .healthMonitorTimeout != monitor .Timeout ||
1098
- svcConf .healthMonitorMaxRetries != monitor .MaxRetries ||
1099
- svcConf .healthMonitorMaxRetriesDown != monitor .MaxRetriesDown {
1100
- updateOpts := v2monitors.UpdateOpts {
1101
- Delay : svcConf .healthMonitorDelay ,
1102
- Timeout : svcConf .healthMonitorTimeout ,
1103
- MaxRetries : svcConf .healthMonitorMaxRetries ,
1104
- MaxRetriesDown : svcConf .healthMonitorMaxRetriesDown ,
1105
- }
1106
- klog .Infof ("Updating health monitor %s updateOpts %+v" , monitorID , updateOpts )
1107
- if err := openstackutil .UpdateHealthMonitor (lbaas .lb , monitorID , updateOpts ); err != nil {
1108
- return err
1109
- }
1075
+ if monitorID == "" {
1076
+ // do nothing
1077
+ if ! svcConf .enableMonitor {
1078
+ return nil
1110
1079
}
1111
- }
1112
- if monitorID == "" && svcConf . enableMonitor {
1080
+
1081
+ // a new monitor must be created
1113
1082
klog .V (2 ).Infof ("Creating monitor for pool %s" , pool .ID )
1083
+ createOpts := lbaas .buildMonitorCreateOpts (svcConf , port , name )
1084
+ return lbaas .createOctaviaHealthMonitor (createOpts , pool .ID , lbID )
1085
+ }
1114
1086
1115
- createOpts := lbaas .buildMonitorCreateOpts (svcConf , port )
1116
- // Populate PoolID, attribute is omitted for consumption of the createOpts for fully populated Loadbalancer
1117
- createOpts .PoolID = pool .ID
1118
- createOpts .Name = name
1119
- monitor , err := openstackutil .CreateHealthMonitor (lbaas .lb , createOpts , lbID )
1120
- if err != nil {
1121
- return err
1122
- }
1123
- monitorID = monitor .ID
1124
- klog .Infof ("Health monitor %s for pool %s created." , monitorID , pool .ID )
1125
- } else if monitorID != "" && ! svcConf .enableMonitor {
1087
+ // an existing monitor must be deleted
1088
+ if ! svcConf .enableMonitor {
1126
1089
klog .Infof ("Deleting health monitor %s for pool %s" , monitorID , pool .ID )
1090
+ return openstackutil .DeleteHealthMonitor (lbaas .lb , monitorID , lbID )
1091
+ }
1092
+
1093
+ // get an existing monitor status
1094
+ monitor , err := openstackutil .GetHealthMonitor (lbaas .lb , monitorID )
1095
+ if err != nil {
1096
+ // return err on 404 is ok, since we get monitorID dynamically from the pool
1097
+ return err
1098
+ }
1127
1099
1100
+ // recreate health monitor with a new type
1101
+ createOpts := lbaas .buildMonitorCreateOpts (svcConf , port , name )
1102
+ if createOpts .Type != monitor .Type {
1103
+ klog .InfoS ("Recreating health monitor for the pool" , "pool" , pool .ID , "oldMonitor" , monitorID )
1128
1104
if err := openstackutil .DeleteHealthMonitor (lbaas .lb , monitorID , lbID ); err != nil {
1129
1105
return err
1130
1106
}
1107
+ return lbaas .createOctaviaHealthMonitor (createOpts , pool .ID , lbID )
1108
+ }
1109
+
1110
+ // update new monitor parameters
1111
+ if name != monitor .Name ||
1112
+ svcConf .healthMonitorDelay != monitor .Delay ||
1113
+ svcConf .healthMonitorTimeout != monitor .Timeout ||
1114
+ svcConf .healthMonitorMaxRetries != monitor .MaxRetries ||
1115
+ svcConf .healthMonitorMaxRetriesDown != monitor .MaxRetriesDown {
1116
+ updateOpts := v2monitors.UpdateOpts {
1117
+ Name : & name ,
1118
+ Delay : svcConf .healthMonitorDelay ,
1119
+ Timeout : svcConf .healthMonitorTimeout ,
1120
+ MaxRetries : svcConf .healthMonitorMaxRetries ,
1121
+ MaxRetriesDown : svcConf .healthMonitorMaxRetriesDown ,
1122
+ }
1123
+ klog .Infof ("Updating health monitor %s updateOpts %+v" , monitorID , updateOpts )
1124
+ return openstackutil .UpdateHealthMonitor (lbaas .lb , monitorID , updateOpts )
1131
1125
}
1132
1126
1133
1127
return nil
@@ -1137,7 +1131,9 @@ func (lbaas *LbaasV2) canUseHTTPMonitor(port corev1.ServicePort) bool {
1137
1131
if lbaas .opts .LBProvider == "ovn" {
1138
1132
// ovn-octavia-provider doesn't support HTTP monitors at all. We got to avoid creating it with ovn.
1139
1133
return false
1140
- } else if port .Protocol == corev1 .ProtocolUDP {
1134
+ }
1135
+
1136
+ if port .Protocol == corev1 .ProtocolUDP {
1141
1137
// Older Octavia versions or OVN provider doesn't support HTTP monitors on UDP pools. We got to check if that's the case.
1142
1138
return openstackutil .IsOctaviaFeatureSupported (lbaas .lb , openstackutil .OctaviaFeatureHTTPMonitorsOnUDP , lbaas .opts .LBProvider )
1143
1139
}
@@ -1146,8 +1142,9 @@ func (lbaas *LbaasV2) canUseHTTPMonitor(port corev1.ServicePort) bool {
1146
1142
}
1147
1143
1148
1144
// buildMonitorCreateOpts returns a v2monitors.CreateOpts without PoolID for consumption of both, fully popuplated Loadbalancers and Monitors.
1149
- func (lbaas * LbaasV2 ) buildMonitorCreateOpts (svcConf * serviceConfig , port corev1.ServicePort ) v2monitors.CreateOpts {
1145
+ func (lbaas * LbaasV2 ) buildMonitorCreateOpts (svcConf * serviceConfig , port corev1.ServicePort , name string ) v2monitors.CreateOpts {
1150
1146
opts := v2monitors.CreateOpts {
1147
+ Name : name ,
1151
1148
Type : string (port .Protocol ),
1152
1149
Delay : svcConf .healthMonitorDelay ,
1153
1150
Timeout : svcConf .healthMonitorTimeout ,
@@ -1166,6 +1163,18 @@ func (lbaas *LbaasV2) buildMonitorCreateOpts(svcConf *serviceConfig, port corev1
1166
1163
return opts
1167
1164
}
1168
1165
1166
+ func (lbaas * LbaasV2 ) createOctaviaHealthMonitor (createOpts v2monitors.CreateOpts , poolID , lbID string ) error {
1167
+ // populate PoolID, attribute is omitted for consumption of the createOpts for fully populated Loadbalancer
1168
+ createOpts .PoolID = poolID
1169
+ monitor , err := openstackutil .CreateHealthMonitor (lbaas .lb , createOpts , lbID )
1170
+ if err != nil {
1171
+ return err
1172
+ }
1173
+ klog .Infof ("Health monitor %s for pool %s created." , monitor .ID , poolID )
1174
+
1175
+ return nil
1176
+ }
1177
+
1169
1178
// Make sure the pool is created for the Service, nodes are added as pool members.
1170
1179
func (lbaas * LbaasV2 ) ensureOctaviaPool (lbID string , name string , listener * listeners.Listener , service * corev1.Service , port corev1.ServicePort , nodes []* corev1.Node , svcConf * serviceConfig ) (* v2pools.Pool , error ) {
1171
1180
pool , err := openstackutil .GetPoolByListener (lbaas .lb , lbID , listener .ID )
@@ -1193,9 +1202,8 @@ func (lbaas *LbaasV2) ensureOctaviaPool(lbID string, name string, listener *list
1193
1202
}
1194
1203
1195
1204
if pool == nil {
1196
- createOpt := lbaas .buildPoolCreateOpt (listener .Protocol , service , svcConf )
1205
+ createOpt := lbaas .buildPoolCreateOpt (listener .Protocol , service , svcConf , name )
1197
1206
createOpt .ListenerID = listener .ID
1198
- createOpt .Name = name
1199
1207
1200
1208
klog .InfoS ("Creating pool" , "listenerID" , listener .ID , "protocol" , createOpt .Protocol )
1201
1209
pool , err = openstackutil .CreatePool (lbaas .lb , createOpt , lbID )
@@ -1230,7 +1238,7 @@ func (lbaas *LbaasV2) ensureOctaviaPool(lbID string, name string, listener *list
1230
1238
return pool , nil
1231
1239
}
1232
1240
1233
- func (lbaas * LbaasV2 ) buildPoolCreateOpt (listenerProtocol string , service * corev1.Service , svcConf * serviceConfig ) v2pools.CreateOpts {
1241
+ func (lbaas * LbaasV2 ) buildPoolCreateOpt (listenerProtocol string , service * corev1.Service , svcConf * serviceConfig , name string ) v2pools.CreateOpts {
1234
1242
// By default, use the protocol of the listener
1235
1243
poolProto := v2pools .Protocol (listenerProtocol )
1236
1244
if svcConf .enableProxyProtocol {
@@ -1257,6 +1265,7 @@ func (lbaas *LbaasV2) buildPoolCreateOpt(listenerProtocol string, service *corev
1257
1265
1258
1266
lbmethod := v2pools .LBMethod (lbaas .opts .LBMethod )
1259
1267
return v2pools.CreateOpts {
1268
+ Name : name ,
1260
1269
Protocol : poolProto ,
1261
1270
LBMethod : lbmethod ,
1262
1271
Persistence : persistence ,
@@ -1309,9 +1318,8 @@ func (lbaas *LbaasV2) ensureOctaviaListener(lbID string, name string, curListene
1309
1318
Port : int (port .Port ),
1310
1319
}]
1311
1320
if ! isPresent {
1312
- listenerCreateOpt := lbaas .buildListenerCreateOpt (port , svcConf )
1321
+ listenerCreateOpt := lbaas .buildListenerCreateOpt (port , svcConf , name )
1313
1322
listenerCreateOpt .LoadbalancerID = lbID
1314
- listenerCreateOpt .Name = name
1315
1323
1316
1324
klog .V (2 ).Infof ("Creating listener for port %d using protocol %s" , int (port .Port ), listenerCreateOpt .Protocol )
1317
1325
@@ -1396,11 +1404,10 @@ func (lbaas *LbaasV2) ensureOctaviaListener(lbID string, name string, curListene
1396
1404
}
1397
1405
1398
1406
// buildListenerCreateOpt returns listeners.CreateOpts for a specific Service port and configuration
1399
- func (lbaas * LbaasV2 ) buildListenerCreateOpt (port corev1.ServicePort , svcConf * serviceConfig ) listeners.CreateOpts {
1400
- listenerProtocol := listeners .Protocol (port .Protocol )
1401
-
1407
+ func (lbaas * LbaasV2 ) buildListenerCreateOpt (port corev1.ServicePort , svcConf * serviceConfig , name string ) listeners.CreateOpts {
1402
1408
listenerCreateOpt := listeners.CreateOpts {
1403
- Protocol : listenerProtocol ,
1409
+ Name : name ,
1410
+ Protocol : listeners .Protocol (port .Protocol ),
1404
1411
ProtocolPort : int (port .Port ),
1405
1412
ConnLimit : & svcConf .connLimit ,
1406
1413
}
@@ -1999,17 +2006,17 @@ func (lbaas *LbaasV2) ensureOctaviaLoadBalancer(ctx context.Context, clusterName
1999
2006
}
2000
2007
2001
2008
for portIndex , port := range service .Spec .Ports {
2002
- listener , err := lbaas .ensureOctaviaListener (loadbalancer .ID , cutString ( fmt . Sprintf ( "listener_%d_%s" , portIndex , lbName ) ), curListenerMapping , port , svcConf , service )
2009
+ listener , err := lbaas .ensureOctaviaListener (loadbalancer .ID , cpoutil . Sprintf255 ( listenerFormat , portIndex , lbName ), curListenerMapping , port , svcConf , service )
2003
2010
if err != nil {
2004
2011
return nil , err
2005
2012
}
2006
2013
2007
- pool , err := lbaas .ensureOctaviaPool (loadbalancer .ID , cutString ( fmt . Sprintf ( "pool_%d_%s" , portIndex , lbName ) ), listener , service , port , nodes , svcConf )
2014
+ pool , err := lbaas .ensureOctaviaPool (loadbalancer .ID , cpoutil . Sprintf255 ( poolFormat , portIndex , lbName ), listener , service , port , nodes , svcConf )
2008
2015
if err != nil {
2009
2016
return nil , err
2010
2017
}
2011
2018
2012
- if err := lbaas .ensureOctaviaHealthMonitor (loadbalancer .ID , cutString ( fmt . Sprintf ( "monitor_%d_%s" , portIndex , lbName ) ), pool , port , svcConf ); err != nil {
2019
+ if err := lbaas .ensureOctaviaHealthMonitor (loadbalancer .ID , cpoutil . Sprintf255 ( monitorFormat , portIndex , lbName ), pool , port , svcConf ); err != nil {
2013
2020
return nil , err
2014
2021
}
2015
2022
@@ -2199,7 +2206,12 @@ func (lbaas *LbaasV2) updateOctaviaLoadBalancer(ctx context.Context, clusterName
2199
2206
return fmt .Errorf ("loadbalancer %s does not contain required listener for port %d and protocol %s" , loadbalancer .ID , port .Port , port .Protocol )
2200
2207
}
2201
2208
2202
- _ , err := lbaas .ensureOctaviaPool (loadbalancer .ID , cutString (fmt .Sprintf ("pool_%d_%s" , portIndex , loadbalancer .Name )), & listener , service , port , nodes , svcConf )
2209
+ pool , err := lbaas .ensureOctaviaPool (loadbalancer .ID , cpoutil .Sprintf255 (poolFormat , portIndex , loadbalancer .Name ), & listener , service , port , nodes , svcConf )
2210
+ if err != nil {
2211
+ return err
2212
+ }
2213
+
2214
+ err = lbaas .ensureOctaviaHealthMonitor (loadbalancer .ID , cpoutil .Sprintf255 (monitorFormat , portIndex , loadbalancer .Name ), pool , port , svcConf )
2203
2215
if err != nil {
2204
2216
return err
2205
2217
}
0 commit comments