mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 18:02:01 +00:00
Merge pull request #77630 from feiskyer/cluster-name-tag
Fix public IPs issues when multiple clusters are sharing the same resource group
This commit is contained in:
commit
e9af72c6e9
@ -83,6 +83,11 @@ const (
|
||||
// ServiceAnnotationLoadBalancerMixedProtocols is the annotation used on the service
|
||||
// to create both TCP and UDP protocols when creating load balancer rules.
|
||||
ServiceAnnotationLoadBalancerMixedProtocols = "service.beta.kubernetes.io/azure-load-balancer-mixed-protocols"
|
||||
|
||||
// serviceTagKey is the service key applied for public IP tags.
|
||||
serviceTagKey = "service"
|
||||
// clusterNameKey is the cluster name key applied for public IP tags.
|
||||
clusterNameKey = "kubernetes-cluster-name"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -465,7 +470,7 @@ func (az *Cloud) findServiceIPAddress(ctx context.Context, clusterName string, s
|
||||
return lbStatus.Ingress[0].IP, nil
|
||||
}
|
||||
|
||||
func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domainNameLabel string) (*network.PublicIPAddress, error) {
|
||||
func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domainNameLabel, clusterName string) (*network.PublicIPAddress, error) {
|
||||
pipResourceGroup := az.getPublicIPAddressResourceGroup(service)
|
||||
pip, existsPip, err := az.getPublicIPAddress(pipResourceGroup, pipName)
|
||||
if err != nil {
|
||||
@ -486,7 +491,10 @@ func (az *Cloud) ensurePublicIPExists(service *v1.Service, pipName string, domai
|
||||
DomainNameLabel: &domainNameLabel,
|
||||
}
|
||||
}
|
||||
pip.Tags = map[string]*string{"service": &serviceName}
|
||||
pip.Tags = map[string]*string{
|
||||
serviceTagKey: &serviceName,
|
||||
clusterNameKey: &clusterName,
|
||||
}
|
||||
if az.useStandardLoadBalancer() {
|
||||
pip.Sku = &network.PublicIPAddressSku{
|
||||
Name: network.PublicIPAddressSkuNameStandard,
|
||||
@ -711,7 +719,7 @@ func (az *Cloud) reconcileLoadBalancer(clusterName string, service *v1.Service,
|
||||
return nil, err
|
||||
}
|
||||
domainNameLabel := getPublicIPDomainNameLabel(service)
|
||||
pip, err := az.ensurePublicIPExists(service, pipName, domainNameLabel)
|
||||
pip, err := az.ensurePublicIPExists(service, pipName, domainNameLabel, clusterName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1344,9 +1352,7 @@ func (az *Cloud) reconcilePublicIP(clusterName string, service *v1.Service, lb *
|
||||
|
||||
for i := range pips {
|
||||
pip := pips[i]
|
||||
if pip.Tags != nil &&
|
||||
(pip.Tags)["service"] != nil &&
|
||||
*(pip.Tags)["service"] == serviceName {
|
||||
if serviceOwnsPublicIP(&pip, clusterName, serviceName) {
|
||||
// We need to process for pips belong to this service
|
||||
pipName := *pip.Name
|
||||
if wantLb && !isInternal && pipName == desiredPipName {
|
||||
@ -1369,7 +1375,7 @@ func (az *Cloud) reconcilePublicIP(clusterName string, service *v1.Service, lb *
|
||||
// Confirm desired public ip resource exists
|
||||
var pip *network.PublicIPAddress
|
||||
domainNameLabel := getPublicIPDomainNameLabel(service)
|
||||
if pip, err = az.ensurePublicIPExists(service, desiredPipName, domainNameLabel); err != nil {
|
||||
if pip, err = az.ensurePublicIPExists(service, desiredPipName, domainNameLabel, clusterName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pip, nil
|
||||
@ -1612,3 +1618,24 @@ func getServiceTags(service *v1.Service) ([]string, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func serviceOwnsPublicIP(pip *network.PublicIPAddress, clusterName, serviceName string) bool {
|
||||
if pip != nil && pip.Tags != nil {
|
||||
serviceTag := pip.Tags[serviceTagKey]
|
||||
clusterTag := pip.Tags[clusterNameKey]
|
||||
|
||||
if serviceTag != nil && *serviceTag == serviceName {
|
||||
// Backward compatible for clusters upgraded from old releases.
|
||||
// In such case, only "service" tag is set.
|
||||
if clusterTag == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// If cluster name tag is set, then return true if it matches.
|
||||
if *clusterTag == clusterName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -368,3 +368,82 @@ func TestEnsureLoadBalancerDeleted(t *testing.T) {
|
||||
assert.Equal(t, len(result), 0, "TestCase[%d]: %s", i, c.desc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceOwnsPublicIP(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
pip *network.PublicIPAddress
|
||||
clusterName string
|
||||
serviceName string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
desc: "false should be returned when pip is nil",
|
||||
clusterName: "kubernetes",
|
||||
serviceName: "nginx",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "false should be returned when service name tag doesn't match",
|
||||
pip: &network.PublicIPAddress{
|
||||
Tags: map[string]*string{
|
||||
serviceTagKey: to.StringPtr("nginx"),
|
||||
},
|
||||
},
|
||||
serviceName: "web",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "true should be returned when service name tag matches and cluster name tag is not set",
|
||||
pip: &network.PublicIPAddress{
|
||||
Tags: map[string]*string{
|
||||
serviceTagKey: to.StringPtr("nginx"),
|
||||
},
|
||||
},
|
||||
clusterName: "kubernetes",
|
||||
serviceName: "nginx",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "false should be returned when cluster name doesn't match",
|
||||
pip: &network.PublicIPAddress{
|
||||
Tags: map[string]*string{
|
||||
serviceTagKey: to.StringPtr("nginx"),
|
||||
clusterNameKey: to.StringPtr("kubernetes"),
|
||||
},
|
||||
},
|
||||
clusterName: "k8s",
|
||||
serviceName: "nginx",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "false should be returned when cluster name matches while service name doesn't match",
|
||||
pip: &network.PublicIPAddress{
|
||||
Tags: map[string]*string{
|
||||
serviceTagKey: to.StringPtr("web"),
|
||||
clusterNameKey: to.StringPtr("kubernetes"),
|
||||
},
|
||||
},
|
||||
clusterName: "kubernetes",
|
||||
serviceName: "nginx",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "true should be returned when both service name tag and cluster name match",
|
||||
pip: &network.PublicIPAddress{
|
||||
Tags: map[string]*string{
|
||||
serviceTagKey: to.StringPtr("nginx"),
|
||||
clusterNameKey: to.StringPtr("kubernetes"),
|
||||
},
|
||||
},
|
||||
clusterName: "kubernetes",
|
||||
serviceName: "nginx",
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for i, c := range tests {
|
||||
owns := serviceOwnsPublicIP(c.pip, c.clusterName, c.serviceName)
|
||||
assert.Equal(t, owns, c.expected, "TestCase[%d]: %s", i, c.desc)
|
||||
}
|
||||
}
|
||||
|
@ -1367,14 +1367,23 @@ func validatePublicIP(t *testing.T, publicIP *network.PublicIPAddress, service *
|
||||
t.Errorf("Expected publicIP resource exists, when it is not an internal service")
|
||||
}
|
||||
|
||||
if publicIP.Tags == nil || publicIP.Tags["service"] == nil {
|
||||
t.Errorf("Expected publicIP resource has tags[service]")
|
||||
if publicIP.Tags == nil || publicIP.Tags[serviceTagKey] == nil {
|
||||
t.Errorf("Expected publicIP resource has tags[%s]", serviceTagKey)
|
||||
}
|
||||
|
||||
serviceName := getServiceName(service)
|
||||
if serviceName != *(publicIP.Tags["service"]) {
|
||||
t.Errorf("Expected publicIP resource has matching tags[service]")
|
||||
if serviceName != *(publicIP.Tags[serviceTagKey]) {
|
||||
t.Errorf("Expected publicIP resource has matching tags[%s]", serviceTagKey)
|
||||
}
|
||||
|
||||
if publicIP.Tags[clusterNameKey] == nil {
|
||||
t.Errorf("Expected publicIP resource has tags[%s]", clusterNameKey)
|
||||
}
|
||||
|
||||
if *(publicIP.Tags[clusterNameKey]) != testClusterName {
|
||||
t.Errorf("Expected publicIP resource has matching tags[%s]", clusterNameKey)
|
||||
}
|
||||
|
||||
// We cannot use service.Spec.LoadBalancerIP to compare with
|
||||
// Public IP's IPAddress
|
||||
// Because service properties are updated outside of cloudprovider code
|
||||
|
Loading…
Reference in New Issue
Block a user