Skip to content

Commit 99936f3

Browse files
authored
Merge pull request kubernetes#3558 from marwanad/add-non-beta-labels-azure-template
Add missing stable labels in the azure template
2 parents 24b4df0 + 875f355 commit 99936f3

File tree

4 files changed

+321
-264
lines changed

4 files changed

+321
-264
lines changed

cluster-autoscaler/cloudprovider/azure/azure_scale_set.go

Lines changed: 1 addition & 177 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,14 @@ import (
2020
"fmt"
2121
"math/rand"
2222
"net/http"
23-
"regexp"
2423
"strings"
2524
"sync"
2625
"time"
2726

2827
apiv1 "k8s.io/api/core/v1"
29-
"k8s.io/apimachinery/pkg/api/resource"
30-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3128
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
3229
"k8s.io/autoscaler/cluster-autoscaler/config/dynamic"
33-
"k8s.io/autoscaler/cluster-autoscaler/utils/gpu"
34-
cloudvolume "k8s.io/cloud-provider/volume"
3530
klog "k8s.io/klog/v2"
36-
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
3731
schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
3832
"k8s.io/legacy-cloud-providers/azure/retry"
3933

@@ -524,184 +518,14 @@ func (scaleSet *ScaleSet) Debug() string {
524518
return fmt.Sprintf("%s (%d:%d)", scaleSet.Id(), scaleSet.MinSize(), scaleSet.MaxSize())
525519
}
526520

527-
func buildInstanceOS(template compute.VirtualMachineScaleSet) string {
528-
instanceOS := cloudprovider.DefaultOS
529-
if template.VirtualMachineProfile != nil && template.VirtualMachineProfile.OsProfile != nil && template.VirtualMachineProfile.OsProfile.WindowsConfiguration != nil {
530-
instanceOS = "windows"
531-
}
532-
533-
return instanceOS
534-
}
535-
536-
func buildGenericLabels(template compute.VirtualMachineScaleSet, nodeName string) map[string]string {
537-
result := make(map[string]string)
538-
539-
result[kubeletapis.LabelArch] = cloudprovider.DefaultArch
540-
result[kubeletapis.LabelOS] = buildInstanceOS(template)
541-
result[apiv1.LabelInstanceType] = *template.Sku.Name
542-
result[apiv1.LabelZoneRegion] = strings.ToLower(*template.Location)
543-
544-
if template.Zones != nil && len(*template.Zones) > 0 {
545-
failureDomains := make([]string, len(*template.Zones))
546-
for k, v := range *template.Zones {
547-
failureDomains[k] = strings.ToLower(*template.Location) + "-" + v
548-
}
549-
550-
result[apiv1.LabelZoneFailureDomain] = strings.Join(failureDomains[:], cloudvolume.LabelMultiZoneDelimiter)
551-
} else {
552-
result[apiv1.LabelZoneFailureDomain] = "0"
553-
}
554-
555-
result[apiv1.LabelHostname] = nodeName
556-
return result
557-
}
558-
559-
func (scaleSet *ScaleSet) buildNodeFromTemplate(template compute.VirtualMachineScaleSet) (*apiv1.Node, error) {
560-
node := apiv1.Node{}
561-
nodeName := fmt.Sprintf("%s-asg-%d", scaleSet.Name, rand.Int63())
562-
563-
node.ObjectMeta = metav1.ObjectMeta{
564-
Name: nodeName,
565-
SelfLink: fmt.Sprintf("/api/v1/nodes/%s", nodeName),
566-
Labels: map[string]string{},
567-
}
568-
569-
node.Status = apiv1.NodeStatus{
570-
Capacity: apiv1.ResourceList{},
571-
}
572-
573-
var vmssType *InstanceType
574-
for k := range InstanceTypes {
575-
if strings.EqualFold(k, *template.Sku.Name) {
576-
vmssType = InstanceTypes[k]
577-
break
578-
}
579-
}
580-
581-
promoRe := regexp.MustCompile(`(?i)_promo`)
582-
if promoRe.MatchString(*template.Sku.Name) {
583-
if vmssType == nil {
584-
// We didn't find an exact match but this is a promo type, check for matching standard
585-
klog.V(1).Infof("No exact match found for %s, checking standard types", *template.Sku.Name)
586-
skuName := promoRe.ReplaceAllString(*template.Sku.Name, "")
587-
for k := range InstanceTypes {
588-
if strings.EqualFold(k, skuName) {
589-
vmssType = InstanceTypes[k]
590-
break
591-
}
592-
}
593-
}
594-
}
595-
596-
if vmssType == nil {
597-
return nil, fmt.Errorf("instance type %q not supported", *template.Sku.Name)
598-
}
599-
node.Status.Capacity[apiv1.ResourcePods] = *resource.NewQuantity(110, resource.DecimalSI)
600-
node.Status.Capacity[apiv1.ResourceCPU] = *resource.NewQuantity(vmssType.VCPU, resource.DecimalSI)
601-
node.Status.Capacity[gpu.ResourceNvidiaGPU] = *resource.NewQuantity(vmssType.GPU, resource.DecimalSI)
602-
node.Status.Capacity[apiv1.ResourceMemory] = *resource.NewQuantity(vmssType.MemoryMb*1024*1024, resource.DecimalSI)
603-
604-
resourcesFromTags := extractAllocatableResourcesFromScaleSet(template.Tags)
605-
for resourceName, val := range resourcesFromTags {
606-
node.Status.Capacity[apiv1.ResourceName(resourceName)] = *val
607-
}
608-
609-
// TODO: set real allocatable.
610-
node.Status.Allocatable = node.Status.Capacity
611-
612-
// NodeLabels
613-
if template.Tags != nil {
614-
for k, v := range template.Tags {
615-
if v != nil {
616-
node.Labels[k] = *v
617-
} else {
618-
node.Labels[k] = ""
619-
}
620-
621-
}
622-
}
623-
624-
// GenericLabels
625-
node.Labels = cloudprovider.JoinStringMaps(node.Labels, buildGenericLabels(template, nodeName))
626-
// Labels from the Scale Set's Tags
627-
node.Labels = cloudprovider.JoinStringMaps(node.Labels, extractLabelsFromScaleSet(template.Tags))
628-
629-
// Taints from the Scale Set's Tags
630-
node.Spec.Taints = extractTaintsFromScaleSet(template.Tags)
631-
632-
node.Status.Conditions = cloudprovider.BuildReadyConditions()
633-
return &node, nil
634-
}
635-
636-
func extractLabelsFromScaleSet(tags map[string]*string) map[string]string {
637-
result := make(map[string]string)
638-
639-
for tagName, tagValue := range tags {
640-
splits := strings.Split(tagName, nodeLabelTagName)
641-
if len(splits) > 1 {
642-
label := strings.Replace(splits[1], "_", "/", -1)
643-
if label != "" {
644-
result[label] = *tagValue
645-
}
646-
}
647-
}
648-
649-
return result
650-
}
651-
652-
func extractTaintsFromScaleSet(tags map[string]*string) []apiv1.Taint {
653-
taints := make([]apiv1.Taint, 0)
654-
655-
for tagName, tagValue := range tags {
656-
// The tag value must be in the format <tag>:NoSchedule
657-
r, _ := regexp.Compile("(.*):(?:NoSchedule|NoExecute|PreferNoSchedule)")
658-
659-
if r.MatchString(*tagValue) {
660-
splits := strings.Split(tagName, nodeTaintTagName)
661-
if len(splits) > 1 {
662-
values := strings.SplitN(*tagValue, ":", 2)
663-
if len(values) > 1 {
664-
taintKey := strings.Replace(splits[1], "_", "/", -1)
665-
taints = append(taints, apiv1.Taint{
666-
Key: taintKey,
667-
Value: values[0],
668-
Effect: apiv1.TaintEffect(values[1]),
669-
})
670-
}
671-
}
672-
}
673-
}
674-
675-
return taints
676-
}
677-
678-
func extractAllocatableResourcesFromScaleSet(tags map[string]*string) map[string]*resource.Quantity {
679-
resources := make(map[string]*resource.Quantity)
680-
681-
for tagName, tagValue := range tags {
682-
resourceName := strings.Split(tagName, nodeResourcesTagName)
683-
if len(resourceName) < 2 || resourceName[1] == "" {
684-
continue
685-
}
686-
687-
quantity, err := resource.ParseQuantity(*tagValue)
688-
if err != nil {
689-
continue
690-
}
691-
resources[resourceName[1]] = &quantity
692-
}
693-
694-
return resources
695-
}
696-
697521
// TemplateNodeInfo returns a node template for this scale set.
698522
func (scaleSet *ScaleSet) TemplateNodeInfo() (*schedulerframework.NodeInfo, error) {
699523
template, rerr := scaleSet.getVMSSInfo()
700524
if rerr != nil {
701525
return nil, rerr.Error()
702526
}
703527

704-
node, err := scaleSet.buildNodeFromTemplate(template)
528+
node, err := buildNodeFromTemplate(scaleSet.Name, template)
705529
if err != nil {
706530
return nil, err
707531
}

cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"time"
2424

2525
apiv1 "k8s.io/api/core/v1"
26-
"k8s.io/apimachinery/pkg/api/resource"
2726
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
2827
"k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient"
2928
"k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient"
@@ -471,89 +470,3 @@ func TestTemplateNodeInfo(t *testing.T) {
471470
assert.NotNil(t, nodeInfo)
472471
assert.NotEmpty(t, nodeInfo.Pods)
473472
}
474-
func TestExtractLabelsFromScaleSet(t *testing.T) {
475-
expectedNodeLabelKey := "zip"
476-
expectedNodeLabelValue := "zap"
477-
extraNodeLabelValue := "buzz"
478-
blankString := ""
479-
480-
tags := map[string]*string{
481-
fmt.Sprintf("%s%s", nodeLabelTagName, expectedNodeLabelKey): &expectedNodeLabelValue,
482-
"fizz": &extraNodeLabelValue,
483-
"bip": &blankString,
484-
}
485-
486-
labels := extractLabelsFromScaleSet(tags)
487-
assert.Len(t, labels, 1)
488-
assert.Equal(t, expectedNodeLabelValue, labels[expectedNodeLabelKey])
489-
}
490-
491-
func TestExtractTaintsFromScaleSet(t *testing.T) {
492-
noScheduleTaintValue := "foo:NoSchedule"
493-
noExecuteTaintValue := "bar:NoExecute"
494-
preferNoScheduleTaintValue := "fizz:PreferNoSchedule"
495-
noSplitTaintValue := "some_value"
496-
blankTaintValue := ""
497-
regularTagValue := "baz"
498-
499-
tags := map[string]*string{
500-
fmt.Sprintf("%s%s", nodeTaintTagName, "dedicated"): &noScheduleTaintValue,
501-
fmt.Sprintf("%s%s", nodeTaintTagName, "group"): &noExecuteTaintValue,
502-
fmt.Sprintf("%s%s", nodeTaintTagName, "app"): &preferNoScheduleTaintValue,
503-
fmt.Sprintf("%s%s", nodeTaintTagName, "k8s.io_testing_underscore_to_slash"): &preferNoScheduleTaintValue,
504-
"bar": &regularTagValue,
505-
fmt.Sprintf("%s%s", nodeTaintTagName, "blank"): &blankTaintValue,
506-
fmt.Sprintf("%s%s", nodeTaintTagName, "nosplit"): &noSplitTaintValue,
507-
}
508-
509-
expectedTaints := []apiv1.Taint{
510-
{
511-
Key: "dedicated",
512-
Value: "foo",
513-
Effect: apiv1.TaintEffectNoSchedule,
514-
},
515-
{
516-
Key: "group",
517-
Value: "bar",
518-
Effect: apiv1.TaintEffectNoExecute,
519-
},
520-
{
521-
Key: "app",
522-
Value: "fizz",
523-
Effect: apiv1.TaintEffectPreferNoSchedule,
524-
},
525-
{
526-
Key: "k8s.io/testing/underscore/to/slash",
527-
Value: "fizz",
528-
Effect: apiv1.TaintEffectPreferNoSchedule,
529-
},
530-
}
531-
532-
taints := extractTaintsFromScaleSet(tags)
533-
assert.Len(t, taints, 4)
534-
assert.Equal(t, makeTaintSet(expectedTaints), makeTaintSet(taints))
535-
}
536-
537-
func TestExtractAllocatableResourcesFromScaleSet(t *testing.T) {
538-
tags := map[string]*string{
539-
fmt.Sprintf("%s%s", nodeResourcesTagName, "cpu"): to.StringPtr("100m"),
540-
fmt.Sprintf("%s%s", nodeResourcesTagName, "memory"): to.StringPtr("100M"),
541-
fmt.Sprintf("%s%s", nodeResourcesTagName, "ephemeral-storage"): to.StringPtr("20G"),
542-
}
543-
544-
labels := extractAllocatableResourcesFromScaleSet(tags)
545-
546-
assert.Equal(t, resource.NewMilliQuantity(100, resource.DecimalSI).String(), labels["cpu"].String())
547-
expectedMemory := resource.MustParse("100M")
548-
assert.Equal(t, (&expectedMemory).String(), labels["memory"].String())
549-
expectedEphemeralStorage := resource.MustParse("20G")
550-
assert.Equal(t, (&expectedEphemeralStorage).String(), labels["ephemeral-storage"].String())
551-
}
552-
553-
func makeTaintSet(taints []apiv1.Taint) map[apiv1.Taint]bool {
554-
set := make(map[apiv1.Taint]bool)
555-
for _, taint := range taints {
556-
set[taint] = true
557-
}
558-
return set
559-
}

0 commit comments

Comments
 (0)