fix load balancer IP change when updating service

This commit is contained in:
Xinhe Li 2018-07-24 18:49:35 +08:00
parent 59fdc02b13
commit 006310b78e

View File

@ -117,14 +117,6 @@ func (az *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, ser
// Here we'll firstly ensure service do not lie in the opposite LB.
serviceName := getServiceName(service)
glog.V(5).Infof("ensureloadbalancer(%s): START clusterName=%q", serviceName, clusterName)
flippedService := flipServiceInternalAnnotation(service)
if _, err := az.reconcileLoadBalancer(clusterName, flippedService, nil, false /* wantLb */); err != nil {
return nil, err
}
if _, err := az.reconcilePublicIP(clusterName, service, true /* wantLb */); err != nil {
return nil, err
}
lb, err := az.reconcileLoadBalancer(clusterName, service, nodes, true /* wantLb */)
if err != nil {
@ -145,6 +137,16 @@ func (az *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, ser
return nil, err
}
updateService := updateServiceLoadBalancerIP(service, to.String(serviceIP))
flippedService := flipServiceInternalAnnotation(updateService)
if _, err := az.reconcileLoadBalancer(clusterName, flippedService, nil, false /* wantLb */); err != nil {
return nil, err
}
if _, err := az.reconcilePublicIP(clusterName, updateService, true /* wantLb */); err != nil {
return nil, err
}
return lbStatus, nil
}
@ -223,7 +225,7 @@ func (az *Cloud) getServiceLoadBalancer(service *v1.Service, clusterName string,
return nil, nil, false, err
}
if status == nil {
// service is not om this load balancer
// service is not on this load balancer
continue
}
@ -409,6 +411,14 @@ func flipServiceInternalAnnotation(service *v1.Service) *v1.Service {
return copyService
}
func updateServiceLoadBalancerIP(service *v1.Service, serviceIP string) *v1.Service {
copyService := service.DeepCopy()
if len(serviceIP) > 0 && copyService != nil {
copyService.Spec.LoadBalancerIP = serviceIP
}
return copyService
}
func (az *Cloud) findServiceIPAddress(ctx context.Context, clusterName string, service *v1.Service, isInternalLb bool) (string, error) {
if len(service.Spec.LoadBalancerIP) > 0 {
return service.Spec.LoadBalancerIP, nil
@ -502,6 +512,53 @@ func getIdleTimeout(s *v1.Service) (*int32, error) {
return &to32, nil
}
func (az *Cloud) isFrontendIPChanged(clusterName string, config network.FrontendIPConfiguration, service *v1.Service, lbFrontendIPConfigName string) (bool, error) {
if az.serviceOwnsFrontendIP(config, service) && !strings.EqualFold(to.String(config.Name), lbFrontendIPConfigName) {
return true, nil
}
if !strings.EqualFold(to.String(config.Name), lbFrontendIPConfigName) {
return false, nil
}
loadBalancerIP := service.Spec.LoadBalancerIP
isInternal := requiresInternalLoadBalancer(service)
if isInternal {
// Judge subnet
subnetName := subnet(service)
if subnetName != nil {
subnet, existsSubnet, err := az.getSubnet(az.VnetName, *subnetName)
if err != nil {
return false, err
}
if !existsSubnet {
return false, fmt.Errorf("failed to get subnet")
}
if config.Subnet != nil && !strings.EqualFold(to.String(config.Subnet.Name), to.String(subnet.Name)) {
return true, nil
}
}
if loadBalancerIP == "" {
return config.PrivateIPAllocationMethod == network.Static, nil
}
return config.PrivateIPAllocationMethod != network.Static || !strings.EqualFold(loadBalancerIP, to.String(config.PrivateIPAddress)), nil
}
if loadBalancerIP == "" {
return false, nil
}
pipName, err := az.determinePublicIPName(clusterName, service)
if err != nil {
return false, err
}
pipResourceGroup := az.getPublicIPAddressResourceGroup(service)
pip, existsPip, err := az.getPublicIPAddress(pipResourceGroup, pipName)
if err != nil {
return false, err
}
if !existsPip {
return true, nil
}
return config.PublicIPAddress != nil && !strings.EqualFold(to.String(pip.ID), to.String(config.PublicIPAddress.ID)), nil
}
// This ensures load balancer exists and the frontend ip config is setup.
// This also reconciles the Service's Ports with the LoadBalancer config.
// This entails adding rules/probes for expected Ports and removing stale rules/ports.
@ -574,14 +631,16 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
}
}
} else {
if isInternal {
for i := len(newConfigs) - 1; i >= 0; i-- {
config := newConfigs[i]
if az.serviceOwnsFrontendIP(config, service) && !strings.EqualFold(*config.Name, lbFrontendIPConfigName) {
glog.V(2).Infof("reconcileLoadBalancer for service (%s)(%t): lb frontendconfig(%s) - dropping", serviceName, wantLb, *config.Name)
newConfigs = append(newConfigs[:i], newConfigs[i+1:]...)
dirtyConfigs = true
}
for i := len(newConfigs) - 1; i >= 0; i-- {
config := newConfigs[i]
isFipChanged, err := az.isFrontendIPChanged(clusterName, config, service, lbFrontendIPConfigName)
if err != nil {
return nil, err
}
if isFipChanged {
glog.V(2).Infof("reconcileLoadBalancer for service (%s)(%t): lb frontendconfig(%s) - dropping", serviceName, wantLb, *config.Name)
newConfigs = append(newConfigs[:i], newConfigs[i+1:]...)
dirtyConfigs = true
}
}
foundConfig := false