Commit c170f5bf authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #50972 from FengyunPan/external-loadBalancerIP

Automatic merge from submit-queue (batch tested with PRs 51235, 50819, 51274, 50972, 50504) Support for specifying external LoadBalancerIP on openstack 1. Support ServiceAnnotationLoadBalancerFloatingNetworkId for LB v1 2. Support for specifying external LoadBalancerIP on openstack Add ServiceAnnotationLoadBalancerInternal annotation to distinguish between internal LoadBalancerIP and external LoadBalancerIP. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # Fix #50851 **Release note**: ```release-note NONE ```
parents 9d7bdb6a 9bdf2cc0
...@@ -68,6 +68,11 @@ const ( ...@@ -68,6 +68,11 @@ const (
errorStatus = "ERROR" errorStatus = "ERROR"
ServiceAnnotationLoadBalancerFloatingNetworkId = "loadbalancer.openstack.org/floating-network-id" ServiceAnnotationLoadBalancerFloatingNetworkId = "loadbalancer.openstack.org/floating-network-id"
// ServiceAnnotationLoadBalancerInternal is the annotation used on the service
// to indicate that we want an internal loadbalancer service.
// If the value of ServiceAnnotationLoadBalancerInternal is false, it indicates that we want an external loadbalancer service. Default to true.
ServiceAnnotationLoadBalancerInternal = "service.beta.kubernetes.io/openstack-internal-load-balancer"
) )
// LoadBalancer implementation for LBaaS v1 // LoadBalancer implementation for LBaaS v1
...@@ -501,7 +506,7 @@ func createNodeSecurityGroup(client *gophercloud.ServiceClient, nodeSecurityGrou ...@@ -501,7 +506,7 @@ func createNodeSecurityGroup(client *gophercloud.ServiceClient, nodeSecurityGrou
return nil return nil
} }
func (lbaas *LbaasV2) createLoadBalancer(service *v1.Service, name string) (*loadbalancers.LoadBalancer, error) { func (lbaas *LbaasV2) createLoadBalancer(service *v1.Service, name string, internalAnnotation bool) (*loadbalancers.LoadBalancer, error) {
createOpts := loadbalancers.CreateOpts{ createOpts := loadbalancers.CreateOpts{
Name: name, Name: name,
Description: fmt.Sprintf("Kubernetes external service %s", name), Description: fmt.Sprintf("Kubernetes external service %s", name),
...@@ -509,7 +514,7 @@ func (lbaas *LbaasV2) createLoadBalancer(service *v1.Service, name string) (*loa ...@@ -509,7 +514,7 @@ func (lbaas *LbaasV2) createLoadBalancer(service *v1.Service, name string) (*loa
} }
loadBalancerIP := service.Spec.LoadBalancerIP loadBalancerIP := service.Spec.LoadBalancerIP
if loadBalancerIP != "" { if loadBalancerIP != "" && internalAnnotation {
createOpts.VipAddress = loadBalancerIP createOpts.VipAddress = loadBalancerIP
} }
...@@ -626,6 +631,24 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv ...@@ -626,6 +631,24 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
floatingPool := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerFloatingNetworkId, lbaas.opts.FloatingNetworkId) floatingPool := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerFloatingNetworkId, lbaas.opts.FloatingNetworkId)
glog.V(4).Infof("EnsureLoadBalancer using floatingPool: %v", floatingPool) glog.V(4).Infof("EnsureLoadBalancer using floatingPool: %v", floatingPool)
var internalAnnotation bool
internal := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerInternal, "true")
switch internal {
case "true":
glog.V(4).Infof("Ensure an internal loadbalancer service.")
internalAnnotation = true
case "false":
if len(floatingPool) != 0 {
glog.V(4).Infof("Ensure an external loadbalancer service.")
internalAnnotation = false
} else {
return nil, fmt.Errorf("floating-network-id or loadbalancer.openstack.org/floating-network-id should be specified when service.beta.kubernetes.io/openstack-internal-load-balancer is false")
}
default:
return nil, fmt.Errorf("unknow service.beta.kubernetes.io/openstack-internal-load-balancer annotation: %v, specify \"true\" or \"false\".",
internal)
}
// Check for TCP protocol on each port // Check for TCP protocol on each port
// TODO: Convert all error messages to use an event recorder // TODO: Convert all error messages to use an event recorder
for _, port := range ports { for _, port := range ports {
...@@ -661,7 +684,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv ...@@ -661,7 +684,7 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
return nil, fmt.Errorf("Error getting loadbalancer %s: %v", name, err) return nil, fmt.Errorf("Error getting loadbalancer %s: %v", name, err)
} }
glog.V(2).Infof("Creating loadbalancer %s", name) glog.V(2).Infof("Creating loadbalancer %s", name)
loadbalancer, err = lbaas.createLoadBalancer(apiService, name) loadbalancer, err = lbaas.createLoadBalancer(apiService, name, internalAnnotation)
if err != nil { if err != nil {
// Unknown error, retry later // Unknown error, retry later
return nil, fmt.Errorf("Error creating loadbalancer %s: %v", name, err) return nil, fmt.Errorf("Error creating loadbalancer %s: %v", name, err)
...@@ -855,12 +878,18 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv ...@@ -855,12 +878,18 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv
if err != nil && err != ErrNotFound { if err != nil && err != ErrNotFound {
return nil, fmt.Errorf("Error getting floating ip for port %s: %v", portID, err) return nil, fmt.Errorf("Error getting floating ip for port %s: %v", portID, err)
} }
if floatIP == nil && floatingPool != "" { if floatIP == nil && floatingPool != "" && !internalAnnotation {
glog.V(4).Infof("Creating floating ip for loadbalancer %s port %s", loadbalancer.ID, portID) glog.V(4).Infof("Creating floating ip for loadbalancer %s port %s", loadbalancer.ID, portID)
floatIPOpts := floatingips.CreateOpts{ floatIPOpts := floatingips.CreateOpts{
FloatingNetworkID: floatingPool, FloatingNetworkID: floatingPool,
PortID: portID, PortID: portID,
} }
loadBalancerIP := apiService.Spec.LoadBalancerIP
if loadBalancerIP != "" {
floatIPOpts.FloatingIP = loadBalancerIP
}
floatIP, err = floatingips.Create(lbaas.network, floatIPOpts).Extract() floatIP, err = floatingips.Create(lbaas.network, floatIPOpts).Extract()
if err != nil { if err != nil {
return nil, fmt.Errorf("Error creating LB floatingip %+v: %v", floatIPOpts, err) return nil, fmt.Errorf("Error creating LB floatingip %+v: %v", floatIPOpts, err)
...@@ -1283,6 +1312,27 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service ...@@ -1283,6 +1312,27 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service
lb.opts.SubnetId = subnetID lb.opts.SubnetId = subnetID
} }
floatingPool := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerFloatingNetworkId, lb.opts.FloatingNetworkId)
glog.V(4).Infof("EnsureLoadBalancer using floatingPool: %v", floatingPool)
var internalAnnotation bool
internal := getStringFromServiceAnnotation(apiService, ServiceAnnotationLoadBalancerInternal, "true")
switch internal {
case "true":
glog.V(4).Infof("Ensure an internal loadbalancer service.")
internalAnnotation = true
case "false":
if len(floatingPool) != 0 {
glog.V(4).Infof("Ensure an external loadbalancer service.")
internalAnnotation = false
} else {
return nil, fmt.Errorf("floating-network-id or loadbalancer.openstack.org/floating-network-id should be specified when service.beta.kubernetes.io/openstack-internal-load-balancer is false")
}
default:
return nil, fmt.Errorf("unknow service.beta.kubernetes.io/openstack-internal-load-balancer annotation: %v, specify \"true\" or \"false\".",
internal)
}
ports := apiService.Spec.Ports ports := apiService.Spec.Ports
if len(ports) > 1 { if len(ports) > 1 {
return nil, fmt.Errorf("multiple ports are not supported in openstack v1 load balancers") return nil, fmt.Errorf("multiple ports are not supported in openstack v1 load balancers")
...@@ -1393,7 +1443,7 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service ...@@ -1393,7 +1443,7 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service
} }
loadBalancerIP := apiService.Spec.LoadBalancerIP loadBalancerIP := apiService.Spec.LoadBalancerIP
if loadBalancerIP != "" { if loadBalancerIP != "" && internalAnnotation {
createOpts.Address = loadBalancerIP createOpts.Address = loadBalancerIP
} }
...@@ -1406,11 +1456,17 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service ...@@ -1406,11 +1456,17 @@ func (lb *LbaasV1) EnsureLoadBalancer(clusterName string, apiService *v1.Service
status.Ingress = []v1.LoadBalancerIngress{{IP: vip.Address}} status.Ingress = []v1.LoadBalancerIngress{{IP: vip.Address}}
if lb.opts.FloatingNetworkId != "" { if floatingPool != "" && !internalAnnotation {
floatIPOpts := floatingips.CreateOpts{ floatIPOpts := floatingips.CreateOpts{
FloatingNetworkID: lb.opts.FloatingNetworkId, FloatingNetworkID: floatingPool,
PortID: vip.PortID, PortID: vip.PortID,
} }
loadBalancerIP := apiService.Spec.LoadBalancerIP
if loadBalancerIP != "" {
floatIPOpts.FloatingIP = loadBalancerIP
}
floatIP, err := floatingips.Create(lb.network, floatIPOpts).Extract() floatIP, err := floatingips.Create(lb.network, floatIPOpts).Extract()
if err != nil { if err != nil {
return nil, fmt.Errorf("Error creating floatingip for openstack load balancer %s: %v", name, err) return nil, fmt.Errorf("Error creating floatingip for openstack load balancer %s: %v", name, err)
...@@ -1494,7 +1550,7 @@ func (lb *LbaasV1) EnsureLoadBalancerDeleted(clusterName string, service *v1.Ser ...@@ -1494,7 +1550,7 @@ func (lb *LbaasV1) EnsureLoadBalancerDeleted(clusterName string, service *v1.Ser
return err return err
} }
if lb.opts.FloatingNetworkId != "" && vip != nil { if vip != nil && vip.PortID != "" {
floatingIP, err := getFloatingIPByPortID(lb.network, vip.PortID) floatingIP, err := getFloatingIPByPortID(lb.network, vip.PortID)
if err != nil && !isNotFound(err) { if err != nil && !isNotFound(err) {
return err return err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment