Skip to content

Commit

Permalink
Merge pull request #1095 from nilo19/fix/cherry-pick-1070-1.0
Browse files Browse the repository at this point in the history
[release-1.0] fix: use zones in the pre-existing frontend IP configurations for int…
  • Loading branch information
k8s-ci-robot committed Jan 30, 2022
2 parents dcb3d72 + a520dda commit a88def3
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 11 deletions.
47 changes: 38 additions & 9 deletions pkg/provider/azure_loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -1718,16 +1718,21 @@ func (az *Cloud) reconcileFrontendIPConfigs(clusterName string, service *v1.Serv
}
}
} else {
var (
previousZone *[]string
isFipChanged bool
)
for i := len(newConfigs) - 1; i >= 0; i-- {
config := newConfigs[i]
isFipChanged, err := az.isFrontendIPChanged(clusterName, config, service, defaultLBFrontendIPConfigName)
isFipChanged, err = az.isFrontendIPChanged(clusterName, config, service, defaultLBFrontendIPConfigName)
if err != nil {
return nil, false, err
}
if isFipChanged {
klog.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
previousZone = config.Zones
}
}

Expand Down Expand Up @@ -1794,14 +1799,11 @@ func (az *Cloud) reconcileFrontendIPConfigs(clusterName string, service *v1.Serv
FrontendIPConfigurationPropertiesFormat: fipConfigurationProperties,
}

// only add zone information for new internal frontend IP configurations for standard load balancer not deployed to an edge zone.
location := az.Location
zones, err := az.getRegionZonesBackoff(location)
if err != nil {
return nil, false, err
}
if isInternal && az.useStandardLoadBalancer() && len(zones) > 0 && !az.HasExtendedLocation() {
newConfig.Zones = &zones
if isInternal {
if err := az.getFrontendZones(&newConfig, previousZone, isFipChanged, serviceName, defaultLBFrontendIPConfigName); err != nil {
klog.Errorf("reconcileLoadBalancer for service (%s)(%t): failed to getFrontendZones: %s", serviceName, wantLb, err.Error())
return nil, false, err
}
}
newConfigs = append(newConfigs, newConfig)
klog.V(2).Infof("reconcileLoadBalancer for service (%s)(%t): lb frontendconfig(%s) - adding", serviceName, wantLb, defaultLBFrontendIPConfigName)
Expand All @@ -1816,6 +1818,33 @@ func (az *Cloud) reconcileFrontendIPConfigs(clusterName string, service *v1.Serv
return ownedFIPConfig, dirtyConfigs, err
}

func (az *Cloud) getFrontendZones(
fipConfig *network.FrontendIPConfiguration,
previousZone *[]string,
isFipChanged bool,
serviceName, defaultLBFrontendIPConfigName string) error {
if !isFipChanged { // fetch zone information from API for new frontends
// only add zone information for new internal frontend IP configurations for standard load balancer not deployed to an edge zone.
location := az.Location
zones, err := az.getRegionZonesBackoff(location)
if err != nil {
return err
}
if az.useStandardLoadBalancer() && len(zones) > 0 && !az.HasExtendedLocation() {
fipConfig.Zones = &zones
}
} else {
if previousZone == nil { // keep the existing zone information for existing frontends
klog.V(2).Infof("getFrontendZones for service (%s): lb frontendconfig(%s): setting zone to nil", serviceName, defaultLBFrontendIPConfigName)
} else {
zoneStr := strings.Join(*previousZone, ",")
klog.V(2).Infof("getFrontendZones for service (%s): lb frontendconfig(%s): setting zone to %s", serviceName, defaultLBFrontendIPConfigName, zoneStr)
}
fipConfig.Zones = previousZone
}
return nil
}

func (az *Cloud) reconcileBackendPools(clusterName string, service *v1.Service, nodes []*v1.Node, lb *network.LoadBalancer, isBackendPoolPreConfigured bool) (bool, bool, error) {
var newBackendPools []network.BackendAddressPool
var err error
Expand Down
55 changes: 54 additions & 1 deletion pkg/provider/azure_loadbalancer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/subnetclient/mocksubnetclient"
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmclient/mockvmclient"
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmssclient/mockvmssclient"
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/zoneclient/mockzoneclient"
"sigs.k8s.io/cloud-provider-azure/pkg/consts"
"sigs.k8s.io/cloud-provider-azure/pkg/retry"
)
Expand Down Expand Up @@ -4347,9 +4348,11 @@ func TestReconcileZonesForFrontendIPConfigs(t *testing.T) {
existingFrontendIPConfigs []network.FrontendIPConfiguration
existingPIP network.PublicIPAddress
getPIPError *retry.Error
getZoneError *retry.Error
regionZonesMap map[string][]string
expectedZones *[]string
expectedDirty bool
expectedErr error
}{
{
description: "reconcileFrontendIPConfigs should reconcile the zones for the new fip config",
Expand All @@ -4370,6 +4373,48 @@ func TestReconcileZonesForFrontendIPConfigs(t *testing.T) {
expectedZones: &[]string{"1", "2", "3"},
expectedDirty: true,
},
{
description: "reconcileFrontendIPConfigs should report an error if failed to get zones",
service: getInternalTestService("test", 80),
getZoneError: retry.NewError(false, errors.New("get zone failed")),
expectedErr: errors.New("get zone failed"),
},
{
description: "reconcileFrontendIPConfigs should use the nil zones of the existing frontend",
service: getTestServiceWithAnnotation("test", map[string]string{
consts.ServiceAnnotationLoadBalancerInternalSubnet: "subnet",
consts.ServiceAnnotationLoadBalancerInternal: consts.TrueAnnotationValue}, 80),
existingFrontendIPConfigs: []network.FrontendIPConfiguration{
{
Name: to.StringPtr("atest1"),
FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{
Subnet: &network.Subnet{
Name: to.StringPtr("subnet-1"),
},
},
},
},
expectedDirty: true,
},
{
description: "reconcileFrontendIPConfigs should use the non-nil zones of the existing frontend",
service: getTestServiceWithAnnotation("test", map[string]string{
consts.ServiceAnnotationLoadBalancerInternalSubnet: "subnet",
consts.ServiceAnnotationLoadBalancerInternal: consts.TrueAnnotationValue}, 80),
existingFrontendIPConfigs: []network.FrontendIPConfiguration{
{
Name: to.StringPtr("atest1"),
FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{
Subnet: &network.Subnet{
Name: to.StringPtr("subnet-1"),
},
},
Zones: &[]string{"1"},
},
},
expectedZones: &[]string{"1"},
expectedDirty: true,
},
} {
t.Run(tc.description, func(t *testing.T) {
cloud := GetTestCloud(ctrl)
Expand All @@ -4387,9 +4432,17 @@ func TestReconcileZonesForFrontendIPConfigs(t *testing.T) {
subnetClient := cloud.SubnetsClient.(*mocksubnetclient.MockInterface)
subnetClient.EXPECT().Get(gomock.Any(), "rg", "vnet", "subnet", gomock.Any()).Return(network.Subnet{}, nil).MaxTimes(1)

zoneClient := mockzoneclient.NewMockInterface(ctrl)
zoneClient.EXPECT().GetZones(gomock.Any(), gomock.Any()).Return(map[string][]string{}, tc.getZoneError).MaxTimes(1)
cloud.ZoneClient = zoneClient

defaultLBFrontendIPConfigName := cloud.getDefaultFrontendIPConfigName(&tc.service)
_, dirty, err := cloud.reconcileFrontendIPConfigs("testCluster", &tc.service, &lb, true, defaultLBFrontendIPConfigName)
assert.NoError(t, err)
if tc.expectedErr == nil {
assert.NoError(t, err)
} else {
assert.Contains(t, err.Error(), tc.expectedErr.Error())
}
assert.Equal(t, tc.expectedDirty, dirty)

for _, fip := range *lb.FrontendIPConfigurations {
Expand Down
7 changes: 6 additions & 1 deletion pkg/provider/azure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1530,8 +1530,13 @@ func getTestService(identifier string, proto v1.Protocol, annotations map[string
}

func getInternalTestService(identifier string, requestedPorts ...int32) v1.Service {
return getTestServiceWithAnnotation(identifier, map[string]string{consts.ServiceAnnotationLoadBalancerInternal: consts.TrueAnnotationValue}, requestedPorts...)
}
func getTestServiceWithAnnotation(identifier string, annotations map[string]string, requestedPorts ...int32) v1.Service {
svc := getTestService(identifier, v1.ProtocolTCP, nil, false, requestedPorts...)
svc.Annotations[consts.ServiceAnnotationLoadBalancerInternal] = consts.TrueAnnotationValue
for k, v := range annotations {
svc.Annotations[k] = v
}
return svc
}

Expand Down

0 comments on commit a88def3

Please sign in to comment.