Skip to content

Commit e9af72c

Browse files
authored
Merge pull request kubernetes#77630 from feiskyer/cluster-name-tag
Fix public IPs issues when multiple clusters are sharing the same resource group
2 parents ed239ce + 1ea5a69 commit e9af72c

File tree

3 files changed

+126
-11
lines changed

3 files changed

+126
-11
lines changed

staging/src/k8s.io/legacy-cloud-providers/azure/azure_loadbalancer.go

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ const (
8383
// ServiceAnnotationLoadBalancerMixedProtocols is the annotation used on the service
8484
// to create both TCP and UDP protocols when creating load balancer rules.
8585
ServiceAnnotationLoadBalancerMixedProtocols = "service.beta.kubernetes.io/azure-load-balancer-mixed-protocols"
86+
87+
// serviceTagKey is the service key applied for public IP tags.
88+
serviceTagKey = "service"
89+
// clusterNameKey is the cluster name key applied for public IP tags.
90+
clusterNameKey = "kubernetes-cluster-name"
8691
)
8792

8893
var (
@@ -465,7 +470,7 @@ func (az *Cloud) findServiceIPAddress(ctx context.Context, clusterName string, s
465470
return lbStatus.Ingress[0].IP, nil
466471
}
467472

468-
func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domainNameLabel string) (*network.PublicIPAddress, error) {
473+
func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domainNameLabel, clusterName string) (*network.PublicIPAddress, error) {
469474
pipResourceGroup := az.getPublicIPAddressResourceGroup(service)
470475
pip, existsPip, err := az.getPublicIPAddress(pipResourceGroup, pipName)
471476
if err != nil {
@@ -486,7 +491,10 @@ func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domai
486491
DomainNameLabel: &domainNameLabel,
487492
}
488493
}
489-
pip.Tags = map[string]*string{"service": &serviceName}
494+
pip.Tags = map[string]*string{
495+
serviceTagKey: &serviceName,
496+
clusterNameKey: &clusterName,
497+
}
490498
if az.useStandardLoadBalancer() {
491499
pip.Sku = &network.PublicIPAddressSku{
492500
Name: network.PublicIPAddressSkuNameStandard,
@@ -711,7 +719,7 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
711719
return nil, err
712720
}
713721
domainNameLabel := getPublicIPDomainNameLabel(service)
714-
pip, err := az.ensurePublicIPExists(service, pipName, domainNameLabel)
722+
pip, err := az.ensurePublicIPExists(service, pipName, domainNameLabel, clusterName)
715723
if err != nil {
716724
return nil, err
717725
}
@@ -1344,9 +1352,7 @@ func (az *Cloud) reconcilePublicIP(clusterName string, service *v1.Service, lb *
13441352

13451353
for i := range pips {
13461354
pip := pips[i]
1347-
if pip.Tags != nil &&
1348-
(pip.Tags)["service"] != nil &&
1349-
*(pip.Tags)["service"] == serviceName {
1355+
if serviceOwnsPublicIP(&pip, clusterName, serviceName) {
13501356
// We need to process for pips belong to this service
13511357
pipName := *pip.Name
13521358
if wantLb && !isInternal && pipName == desiredPipName {
@@ -1369,7 +1375,7 @@ func (az *Cloud) reconcilePublicIP(clusterName string, service *v1.Service, lb *
13691375
// Confirm desired public ip resource exists
13701376
var pip *network.PublicIPAddress
13711377
domainNameLabel := getPublicIPDomainNameLabel(service)
1372-
if pip, err = az.ensurePublicIPExists(service, desiredPipName, domainNameLabel); err != nil {
1378+
if pip, err = az.ensurePublicIPExists(service, desiredPipName, domainNameLabel, clusterName); err != nil {
13731379
return nil, err
13741380
}
13751381
return pip, nil
@@ -1612,3 +1618,24 @@ func getServiceTags(service *v1.Service) ([]string, error) {
16121618

16131619
return nil, nil
16141620
}
1621+
1622+
func serviceOwnsPublicIP(pip *network.PublicIPAddress, clusterName, serviceName string) bool {
1623+
if pip != nil && pip.Tags != nil {
1624+
serviceTag := pip.Tags[serviceTagKey]
1625+
clusterTag := pip.Tags[clusterNameKey]
1626+
1627+
if serviceTag != nil && *serviceTag == serviceName {
1628+
// Backward compatible for clusters upgraded from old releases.
1629+
// In such case, only "service" tag is set.
1630+
if clusterTag == nil {
1631+
return true
1632+
}
1633+
1634+
// If cluster name tag is set, then return true if it matches.
1635+
if *clusterTag == clusterName {
1636+
return true
1637+
}
1638+
}
1639+
}
1640+
return false
1641+
}

staging/src/k8s.io/legacy-cloud-providers/azure/azure_loadbalancer_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,3 +368,82 @@ func TestEnsureLoadBalancerDeleted(t *testing.T) {
368368
assert.Equal(t, len(result), 0, "TestCase[%d]: %s", i, c.desc)
369369
}
370370
}
371+
372+
func TestServiceOwnsPublicIP(t *testing.T) {
373+
tests := []struct {
374+
desc string
375+
pip *network.PublicIPAddress
376+
clusterName string
377+
serviceName string
378+
expected bool
379+
}{
380+
{
381+
desc: "false should be returned when pip is nil",
382+
clusterName: "kubernetes",
383+
serviceName: "nginx",
384+
expected: false,
385+
},
386+
{
387+
desc: "false should be returned when service name tag doesn't match",
388+
pip: &network.PublicIPAddress{
389+
Tags: map[string]*string{
390+
serviceTagKey: to.StringPtr("nginx"),
391+
},
392+
},
393+
serviceName: "web",
394+
expected: false,
395+
},
396+
{
397+
desc: "true should be returned when service name tag matches and cluster name tag is not set",
398+
pip: &network.PublicIPAddress{
399+
Tags: map[string]*string{
400+
serviceTagKey: to.StringPtr("nginx"),
401+
},
402+
},
403+
clusterName: "kubernetes",
404+
serviceName: "nginx",
405+
expected: true,
406+
},
407+
{
408+
desc: "false should be returned when cluster name doesn't match",
409+
pip: &network.PublicIPAddress{
410+
Tags: map[string]*string{
411+
serviceTagKey: to.StringPtr("nginx"),
412+
clusterNameKey: to.StringPtr("kubernetes"),
413+
},
414+
},
415+
clusterName: "k8s",
416+
serviceName: "nginx",
417+
expected: false,
418+
},
419+
{
420+
desc: "false should be returned when cluster name matches while service name doesn't match",
421+
pip: &network.PublicIPAddress{
422+
Tags: map[string]*string{
423+
serviceTagKey: to.StringPtr("web"),
424+
clusterNameKey: to.StringPtr("kubernetes"),
425+
},
426+
},
427+
clusterName: "kubernetes",
428+
serviceName: "nginx",
429+
expected: false,
430+
},
431+
{
432+
desc: "true should be returned when both service name tag and cluster name match",
433+
pip: &network.PublicIPAddress{
434+
Tags: map[string]*string{
435+
serviceTagKey: to.StringPtr("nginx"),
436+
clusterNameKey: to.StringPtr("kubernetes"),
437+
},
438+
},
439+
clusterName: "kubernetes",
440+
serviceName: "nginx",
441+
expected: true,
442+
},
443+
}
444+
445+
for i, c := range tests {
446+
owns := serviceOwnsPublicIP(c.pip, c.clusterName, c.serviceName)
447+
assert.Equal(t, owns, c.expected, "TestCase[%d]: %s", i, c.desc)
448+
}
449+
}

staging/src/k8s.io/legacy-cloud-providers/azure/azure_test.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,14 +1367,23 @@ func validatePublicIP(t *testing.T, publicIP *network.PublicIPAddress, service *
13671367
t.Errorf("Expected publicIP resource exists, when it is not an internal service")
13681368
}
13691369

1370-
if publicIP.Tags == nil || publicIP.Tags["service"] == nil {
1371-
t.Errorf("Expected publicIP resource has tags[service]")
1370+
if publicIP.Tags == nil || publicIP.Tags[serviceTagKey] == nil {
1371+
t.Errorf("Expected publicIP resource has tags[%s]", serviceTagKey)
13721372
}
13731373

13741374
serviceName := getServiceName(service)
1375-
if serviceName != *(publicIP.Tags["service"]) {
1376-
t.Errorf("Expected publicIP resource has matching tags[service]")
1375+
if serviceName != *(publicIP.Tags[serviceTagKey]) {
1376+
t.Errorf("Expected publicIP resource has matching tags[%s]", serviceTagKey)
13771377
}
1378+
1379+
if publicIP.Tags[clusterNameKey] == nil {
1380+
t.Errorf("Expected publicIP resource has tags[%s]", clusterNameKey)
1381+
}
1382+
1383+
if *(publicIP.Tags[clusterNameKey]) != testClusterName {
1384+
t.Errorf("Expected publicIP resource has matching tags[%s]", clusterNameKey)
1385+
}
1386+
13781387
// We cannot use service.Spec.LoadBalancerIP to compare with
13791388
// Public IP's IPAddress
13801389
// Because service properties are updated outside of cloudprovider code

0 commit comments

Comments
 (0)