Merge pull request #123223 from mmerkes/labels

Add AdditionalLabels to cloudprovider.InstanceMetadata
This commit is contained in:
Kubernetes Prow Robot 2024-02-21 14:41:50 -08:00 committed by GitHub
commit 3ae6c051a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 281 additions and 6 deletions

View File

@ -327,4 +327,9 @@ type InstanceMetadata struct {
// * topology.kubernetes.io/region=<region> // * topology.kubernetes.io/region=<region>
// * failure-domain.beta.kubernetes.io/region=<region> (DEPRECATED) // * failure-domain.beta.kubernetes.io/region=<region> (DEPRECATED)
Region string Region string
// AdditionalLabels is a map of additional labels provided by the cloud provider.
// When provided, they will be applied to the node and enable cloud providers
// to labels nodes with information that may be valuable to that provider.
AdditionalLabels map[string]string
} }

View File

@ -20,6 +20,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"regexp"
"time" "time"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
@ -572,6 +573,30 @@ func (cnc *CloudNodeController) getNodeModifiersFromCloudProvider(
}) })
} }
if len(instanceMeta.AdditionalLabels) > 0 {
klog.V(2).Infof("Adding additional node label(s) from cloud provider: %v", instanceMeta.AdditionalLabels)
nodeModifiers = append(nodeModifiers, func(n *v1.Node) {
if n.Labels == nil {
n.Labels = map[string]string{}
}
k8sNamespaceRegex := regexp.MustCompile("(kubernetes|k8s).io/")
for k, v := range instanceMeta.AdditionalLabels {
// Cloud provider should not be using kubernetes namespaces in labels
if isK8sNamespace := k8sNamespaceRegex.MatchString(k); isK8sNamespace {
klog.Warningf("Discarding node label %s with kubernetes namespace", k)
continue
} else if originalVal, ok := n.Labels[k]; ok {
if originalVal != v {
klog.Warningf("Discarding node label %s that is already present", k)
}
continue
}
n.Labels[k] = v
}
})
}
return nodeModifiers, nil return nodeModifiers, nil
} }

View File

@ -1302,6 +1302,249 @@ func Test_syncNode(t *testing.T) {
}, },
}, },
}, },
{
name: "[instanceV2] provided additional labels",
fakeCloud: &fakecloud.Cloud{
EnableInstancesV2: true,
Addresses: []v1.NodeAddress{
{
Type: v1.NodeInternalIP,
Address: "10.0.0.1",
},
{
Type: v1.NodeExternalIP,
Address: "132.143.154.163",
},
},
ExistsByProviderID: true,
Err: nil,
Zone: cloudprovider.Zone{
FailureDomain: "us-west-1a",
Region: "us-west",
},
AdditionalLabels: map[string]string{
"topology.k8s.cp/zone-id": "az1",
"my.custom.label/foo": "bar",
},
},
existingNode: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Annotations: map[string]string{
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1",
},
},
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{
Key: "ImproveCoverageTaint",
Value: "true",
Effect: v1.TaintEffectNoSchedule,
},
{
Key: cloudproviderapi.TaintExternalCloudProvider,
Value: "true",
Effect: v1.TaintEffectNoSchedule,
},
},
ProviderID: "node0.cp.12345",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionUnknown,
LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
},
},
Addresses: []v1.NodeAddress{
{
Type: v1.NodeHostName,
Address: "node0.cloud.internal",
},
},
},
},
updatedNode: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Annotations: map[string]string{
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1",
},
Labels: map[string]string{
"failure-domain.beta.kubernetes.io/region": "us-west",
"failure-domain.beta.kubernetes.io/zone": "us-west-1a",
"topology.kubernetes.io/region": "us-west",
"topology.kubernetes.io/zone": "us-west-1a",
"topology.k8s.cp/zone-id": "az1",
"my.custom.label/foo": "bar",
},
},
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{
Key: "ImproveCoverageTaint",
Value: "true",
Effect: v1.TaintEffectNoSchedule,
},
},
ProviderID: "node0.cp.12345",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionUnknown,
LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
},
},
Addresses: []v1.NodeAddress{
{
Type: v1.NodeInternalIP,
Address: "10.0.0.1",
},
{
Type: v1.NodeExternalIP,
Address: "132.143.154.163",
},
{
Type: v1.NodeHostName,
Address: "node0.cloud.internal",
},
},
},
},
},
{
name: "[instanceV2] provided additional labels with labels to discard",
fakeCloud: &fakecloud.Cloud{
EnableInstancesV2: true,
Addresses: []v1.NodeAddress{
{
Type: v1.NodeInternalIP,
Address: "10.0.0.1",
},
{
Type: v1.NodeExternalIP,
Address: "132.143.154.163",
},
},
ExistsByProviderID: true,
Err: nil,
Zone: cloudprovider.Zone{
FailureDomain: "us-west-1a",
Region: "us-west",
},
AdditionalLabels: map[string]string{
// Kubernetes reserves k8s.io and kubernetes.io namespaces
// and should be discarded
"topology.kubernetes.io/region": "us-other-west",
"topology.k8s.io/region": "us-other-west",
// Should discard labels that already exist
"my.custom.label/foo": "bar",
"my.custom.label/bar": "foo",
},
},
existingNode: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Annotations: map[string]string{
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1",
},
Labels: map[string]string{
"my.custom.label/foo": "fizz",
"my.custom.label/bar": "foo",
},
},
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{
Key: "ImproveCoverageTaint",
Value: "true",
Effect: v1.TaintEffectNoSchedule,
},
{
Key: cloudproviderapi.TaintExternalCloudProvider,
Value: "true",
Effect: v1.TaintEffectNoSchedule,
},
},
ProviderID: "node0.cp.12345",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionUnknown,
LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
},
},
Addresses: []v1.NodeAddress{
{
Type: v1.NodeHostName,
Address: "node0.cloud.internal",
},
},
},
},
updatedNode: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node0",
CreationTimestamp: metav1.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
Annotations: map[string]string{
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1",
},
Labels: map[string]string{
"failure-domain.beta.kubernetes.io/region": "us-west",
"failure-domain.beta.kubernetes.io/zone": "us-west-1a",
"topology.kubernetes.io/region": "us-west",
"topology.kubernetes.io/zone": "us-west-1a",
"my.custom.label/foo": "fizz",
"my.custom.label/bar": "foo",
},
},
Spec: v1.NodeSpec{
Taints: []v1.Taint{
{
Key: "ImproveCoverageTaint",
Value: "true",
Effect: v1.TaintEffectNoSchedule,
},
},
ProviderID: "node0.cp.12345",
},
Status: v1.NodeStatus{
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionUnknown,
LastHeartbeatTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
LastTransitionTime: metav1.Date(2015, 1, 1, 12, 0, 0, 0, time.UTC),
},
},
Addresses: []v1.NodeAddress{
{
Type: v1.NodeInternalIP,
Address: "10.0.0.1",
},
{
Type: v1.NodeExternalIP,
Address: "132.143.154.163",
},
{
Type: v1.NodeHostName,
Address: "node0.cloud.internal",
},
},
},
},
},
{ {
name: "[instanceV2] provider ID already set", name: "[instanceV2] provider ID already set",
fakeCloud: &fakecloud.Cloud{ fakeCloud: &fakecloud.Cloud{

View File

@ -97,7 +97,8 @@ type Cloud struct {
ProviderID map[types.NodeName]string ProviderID map[types.NodeName]string
addCallLock sync.Mutex addCallLock sync.Mutex
cloudprovider.Zone cloudprovider.Zone
VolumeLabelMap map[string]map[string]string VolumeLabelMap map[string]map[string]string
AdditionalLabels map[string]string
OverrideInstanceMetadata func(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error) OverrideInstanceMetadata func(ctx context.Context, node *v1.Node) (*cloudprovider.InstanceMetadata, error)
@ -373,11 +374,12 @@ func (f *Cloud) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloudprov
} }
return &cloudprovider.InstanceMetadata{ return &cloudprovider.InstanceMetadata{
ProviderID: providerID, ProviderID: providerID,
InstanceType: f.InstanceTypes[types.NodeName(node.Spec.ProviderID)], InstanceType: f.InstanceTypes[types.NodeName(node.Spec.ProviderID)],
NodeAddresses: f.Addresses, NodeAddresses: f.Addresses,
Zone: f.Zone.FailureDomain, Zone: f.Zone.FailureDomain,
Region: f.Zone.Region, Region: f.Zone.Region,
AdditionalLabels: f.AdditionalLabels,
}, f.MetadataErr }, f.MetadataErr
} }