Skip to content

Commit 5982062

Browse files
committed
Azure: support allocatable resources overrides via VMSS tags
This allows to specify effective nodes resources capacity using Scale Sets tags, preventing wrong CA decisions and infinite upscale when pods requests are within instance type capacity but over k8s nodes allocatable (which might comprise system and kubelet's reservations), and when using node-infos from instances templates (ie. scaling from 0). This is similar to what AWS (with launch configuration tags) and GCP (with instances templates metadata) cloud providers offers, ensuring the tags format is similar to AWS' for consistency. See also: https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/proposals/min_at_zero_gcp.md
1 parent 1e0b433 commit 5982062

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

cluster-autoscaler/cloudprovider/azure/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ To add the taint of `foo=bar:NoSchedule` to a node from a VMSS pool, you would a
4545

4646
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`
4747

48+
#### Resources
49+
50+
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.
51+
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:
52+
```
53+
k8s.io_cluster-autoscaler_node-template_resources_cpu: 3800m
54+
k8s.io_cluster-autoscaler_node-template_resources_memory: 11Gi
55+
```
56+
4857
## Deployment manifests
4958

5059
Cluster autoscaler supports four Kubernetes cluster options on Azure:

cluster-autoscaler/cloudprovider/azure/azure_scale_set.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,11 @@ func (scaleSet *ScaleSet) buildNodeFromTemplate(template compute.VirtualMachineS
601601
node.Status.Capacity[gpu.ResourceNvidiaGPU] = *resource.NewQuantity(vmssType.GPU, resource.DecimalSI)
602602
node.Status.Capacity[apiv1.ResourceMemory] = *resource.NewQuantity(vmssType.MemoryMb*1024*1024, resource.DecimalSI)
603603

604+
resourcesFromTags := extractAllocatableResourcesFromScaleSet(template.Tags)
605+
for resourceName, val := range resourcesFromTags {
606+
node.Status.Capacity[apiv1.ResourceName(resourceName)] = *val
607+
}
608+
604609
// TODO: set real allocatable.
605610
node.Status.Allocatable = node.Status.Capacity
606611

@@ -670,6 +675,25 @@ func extractTaintsFromScaleSet(tags map[string]*string) []apiv1.Taint {
670675
return taints
671676
}
672677

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+
673697
// TemplateNodeInfo returns a node template for this scale set.
674698
func (scaleSet *ScaleSet) TemplateNodeInfo() (*schedulerframework.NodeInfo, error) {
675699
template, rerr := scaleSet.getVMSSInfo()

cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go

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

2525
apiv1 "k8s.io/api/core/v1"
26+
"k8s.io/apimachinery/pkg/api/resource"
2627
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
2728
"k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient"
2829
"k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient"
@@ -533,6 +534,22 @@ func TestExtractTaintsFromScaleSet(t *testing.T) {
533534
assert.Equal(t, makeTaintSet(expectedTaints), makeTaintSet(taints))
534535
}
535536

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+
536553
func makeTaintSet(taints []apiv1.Taint) map[apiv1.Taint]bool {
537554
set := make(map[apiv1.Taint]bool)
538555
for _, taint := range taints {

cluster-autoscaler/cloudprovider/azure/azure_util.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ const (
7878
k8sWindowsVMAgentOrchestratorNameIndex = 2
7979
k8sWindowsVMAgentPoolInfoIndex = 3
8080

81-
nodeLabelTagName = "k8s.io_cluster-autoscaler_node-template_label_"
82-
nodeTaintTagName = "k8s.io_cluster-autoscaler_node-template_taint_"
81+
nodeLabelTagName = "k8s.io_cluster-autoscaler_node-template_label_"
82+
nodeTaintTagName = "k8s.io_cluster-autoscaler_node-template_taint_"
83+
nodeResourcesTagName = "k8s.io_cluster-autoscaler_node-template_resources_"
8384
)
8485

8586
var (

0 commit comments

Comments
 (0)