Skip to content

Commit

Permalink
Azure: support allocatable resources overrides via VMSS tags
Browse files Browse the repository at this point in the history
  • Loading branch information
nilo19 committed Oct 19, 2020
1 parent 814935b commit 816a742
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 2 deletions.
9 changes: 9 additions & 0 deletions cluster-autoscaler/cloudprovider/azure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ To add the taint of `foo=bar:NoSchedule` to a node from a VMSS pool, you would a

You can also use forward slashes in taints by setting them as an underscore in the tag name. For example to add the taint of `k8s.io/foo=bar:NoSchedule` to a node from a VMSS pool, you would add the following tag to the VMSS `k8s.io_cluster-autoscaler_node-template_taint_k8s.io_foo: bar:NoSchedule`

#### Resources

When scaling from an empty VM Scale Set (0 instances), Cluster Autoscaler will evaluate the provided presources (cpu, memory, ephemeral-storage) based on that VM Scale Set's backing instance type.
This can be overridden (for instance, to account for system reserved resources) by specifying capacities with VMSS tags, formated as: `k8s.io_cluster-autoscaler_node-template_resources_<resource name>: <resource value>`. For instance:
```
k8s.io_cluster-autoscaler_node-template_resources_cpu: 3800m
k8s.io_cluster-autoscaler_node-template_resources_memory: 11Gi
```

## Deployment manifests

Cluster autoscaler supports four Kubernetes cluster options on Azure:
Expand Down
17 changes: 17 additions & 0 deletions cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"time"

apiv1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
"k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient"
"k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient"
Expand Down Expand Up @@ -470,3 +471,19 @@ func TestTemplateNodeInfo(t *testing.T) {
assert.NotNil(t, nodeInfo)
assert.NotEmpty(t, nodeInfo.Pods)
}

func TestExtractAllocatableResourcesFromScaleSet(t *testing.T) {
tags := map[string]*string{
fmt.Sprintf("%s%s", nodeResourcesTagName, "cpu"): to.StringPtr("100m"),
fmt.Sprintf("%s%s", nodeResourcesTagName, "memory"): to.StringPtr("100M"),
fmt.Sprintf("%s%s", nodeResourcesTagName, "ephemeral-storage"): to.StringPtr("20G"),
}

labels := extractAllocatableResourcesFromScaleSet(tags)

assert.Equal(t, resource.NewMilliQuantity(100, resource.DecimalSI).String(), labels["cpu"].String())
expectedMemory := resource.MustParse("100M")
assert.Equal(t, (&expectedMemory).String(), labels["memory"].String())
expectedEphemeralStorage := resource.MustParse("20G")
assert.Equal(t, (&expectedEphemeralStorage).String(), labels["ephemeral-storage"].String())
}
24 changes: 24 additions & 0 deletions cluster-autoscaler/cloudprovider/azure/azure_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ func buildNodeFromTemplate(scaleSetName string, template compute.VirtualMachineS
node.Status.Capacity[gpu.ResourceNvidiaGPU] = *resource.NewQuantity(vmssType.GPU, resource.DecimalSI)
node.Status.Capacity[apiv1.ResourceMemory] = *resource.NewQuantity(vmssType.MemoryMb*1024*1024, resource.DecimalSI)

resourcesFromTags := extractAllocatableResourcesFromScaleSet(template.Tags)
for resourceName, val := range resourcesFromTags {
node.Status.Capacity[apiv1.ResourceName(resourceName)] = *val
}

// TODO: set real allocatable.
node.Status.Allocatable = node.Status.Capacity

Expand Down Expand Up @@ -140,6 +145,25 @@ func buildNodeFromTemplate(scaleSetName string, template compute.VirtualMachineS
return &node, nil
}

func extractAllocatableResourcesFromScaleSet(tags map[string]*string) map[string]*resource.Quantity {
resources := make(map[string]*resource.Quantity)

for tagName, tagValue := range tags {
resourceName := strings.Split(tagName, nodeResourcesTagName)
if len(resourceName) < 2 || resourceName[1] == "" {
continue
}

quantity, err := resource.ParseQuantity(*tagValue)
if err != nil {
continue
}
resources[resourceName[1]] = &quantity
}

return resources
}

func extractLabelsFromScaleSet(tags map[string]*string) map[string]string {
result := make(map[string]string)

Expand Down
5 changes: 3 additions & 2 deletions cluster-autoscaler/cloudprovider/azure/azure_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@ const (
k8sWindowsVMAgentOrchestratorNameIndex = 2
k8sWindowsVMAgentPoolInfoIndex = 3

nodeLabelTagName = "k8s.io_cluster-autoscaler_node-template_label_"
nodeTaintTagName = "k8s.io_cluster-autoscaler_node-template_taint_"
nodeLabelTagName = "k8s.io_cluster-autoscaler_node-template_label_"
nodeTaintTagName = "k8s.io_cluster-autoscaler_node-template_taint_"
nodeResourcesTagName = "k8s.io_cluster-autoscaler_node-template_resources_"
)

var (
Expand Down

0 comments on commit 816a742

Please sign in to comment.