Skip to content
This repository was archived by the owner on Jan 11, 2023. It is now read-only.

Commit

Permalink
Scaling Windows agent pools for Availability Sets and VMSS (#2859)
Browse files Browse the repository at this point in the history
* acs-engine deploy: model validation and required fields in --help

* Forced apimodel validation to avoid incongruences (fixes #2025)

* Added more details about required fields while deploying (fixes #2491)

* WIP - Adding windows agent pool scaling

* Revert "WIP - Adding windows agent pool scaling" - wrong branch

This reverts commit 0eb7ece.

* WIP - Windows Scaling on Availability Sets and VMSS

* WIP - Naming format modified for vmss windows scaling

* Merge remote-tracking branch 'Azure/patch-release-v0.16.2' into windowsscale

* Fixing tests

* feat(*): Bumps client-go to v7.0.0

This updates client-go to v7.0.0 and adds the needed dependencies on
`k8s.io/api`. Also fixes a small issue with conflicting `uuid` library
versions

* testing re-vendor health

make build-vendor passed!

* removing the vnet from scale templates (#2994)

This allows a cluster to scale even if the user has added a subnet to the vnet

* Fix missing DefaultKubernetesClusterSubnet

* dos2unix

* Clean and go fmt

* Clean and go fmt

* Clean and go fmt

* Fix util_test.go

* Using StorageProfile.ImageReference.Publisher to understand if Windows Agent Pool in Scaling scenario

* lint
  • Loading branch information
danigian authored and Cecile Robert-Michon committed Jun 1, 2018
1 parent 962dcc1 commit c02ec75
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 10 deletions.
34 changes: 29 additions & 5 deletions cmd/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error {
}

orchestratorInfo := sc.containerService.Properties.OrchestratorProfile
var currentNodeCount, highestUsedIndex int
var currentNodeCount, highestUsedIndex, index, winPoolIndex int
winPoolIndex = -1
indexes := make([]int, 0)
indexToVM := make(map[int]string)
if sc.agentPool.IsAvailabilitySets() {
Expand All @@ -219,12 +220,22 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error {
return fmt.Errorf("The provided resource group does not contain any vms")
}
for _, vm := range *vms.Value {
vmTags := *vm.Tags
poolName := *vmTags["poolName"]
nameSuffix := *vmTags["resourceNameSuffix"]

poolName, nameSuffix, index, err := utils.K8sLinuxVMNameParts(*vm.Name)
if err != nil || !strings.EqualFold(poolName, sc.agentPoolToScale) || !strings.EqualFold(nameSuffix, sc.nameSuffix) {
//Changed to string contains for the nameSuffix as the Windows Agent Pools use only a substring of the first 5 characters of the entire nameSuffix
if err != nil || !strings.EqualFold(poolName, sc.agentPoolToScale) || !strings.Contains(sc.nameSuffix, nameSuffix) {
continue
}

osPublisher := *vm.StorageProfile.ImageReference.Publisher
if strings.EqualFold(osPublisher, "MicrosoftWindowsServer") {
_, _, winPoolIndex, index, err = utils.WindowsVMNameParts(*vm.Name)
} else {
_, _, index, err = utils.K8sLinuxVMNameParts(*vm.Name)
}

indexToVM[index] = *vm.Name
indexes = append(indexes, index)
}
Expand Down Expand Up @@ -298,10 +309,20 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error {
return fmt.Errorf("failed to get vmss list in the resource group. Error: %s", err.Error())
}
for _, vmss := range *vmssList.Value {
poolName, nameSuffix, err := utils.VmssNameParts(*vmss.Name)
if err != nil || !strings.EqualFold(poolName, sc.agentPoolToScale) || !strings.EqualFold(nameSuffix, sc.nameSuffix) {
vmTags := *vmss.Tags
poolName := *vmTags["poolName"]
nameSuffix := *vmTags["resourceNameSuffix"]

//Changed to string contains for the nameSuffix as the Windows Agent Pools use only a substring of the first 5 characters of the entire nameSuffix
if err != nil || !strings.EqualFold(poolName, sc.agentPoolToScale) || !strings.Contains(sc.nameSuffix, nameSuffix) {
continue
}

osPublisher := *vmss.VirtualMachineProfile.StorageProfile.ImageReference.Publisher
if strings.EqualFold(osPublisher, "MicrosoftWindowsServer") {
_, _, winPoolIndex, err = utils.WindowsVMSSNameParts(*vmss.Name)
}

currentNodeCount = int(*vmss.Sku.Capacity)
highestUsedIndex = 0
}
Expand Down Expand Up @@ -350,6 +371,9 @@ func (sc *scaleCmd) run(cmd *cobra.Command, args []string) error {
}
addValue(parametersJSON, sc.agentPool.Name+"Count", countForTemplate)

if winPoolIndex != -1 {
templateJSON["variables"].(map[string]interface{})[sc.agentPool.Name+"Index"] = winPoolIndex
}
switch orchestratorInfo.OrchestratorType {
case api.OpenShift:
err = transformer.NormalizeForOpenShiftVMASScalingUp(sc.logger, sc.agentPool.Name, templateJSON)
Expand Down
29 changes: 28 additions & 1 deletion pkg/armhelpers/utils/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,23 @@ const (
vmssNamingFormat = "^[0-9a-zA-Z]+-(.+)-([0-9a-fA-F]{8})-vmss$"
vmssAgentPoolNameIndex = 1
vmssClusterIDIndex = 2

windowsVmssNamingFormat = "^([a-fA-F0-9]{5})([0-9a-zA-Z]{3})([a-zA-Z0-9]{3})$"
windowsVmssAgentPoolNameIndex = 1
windowsVmssAgentPoolOrchestratorNameIndex = 2
windowsVmssAgentPoolIndex = 3
)

var vmnameLinuxRegexp *regexp.Regexp
var vmssnameRegexp *regexp.Regexp
var vmnameWindowsRegexp *regexp.Regexp
var vmssnameWindowsRegexp *regexp.Regexp

func init() {
vmnameLinuxRegexp = regexp.MustCompile(k8sLinuxVMNamingFormat)
vmnameWindowsRegexp = regexp.MustCompile(k8sWindowsVMNamingFormat)
vmssnameRegexp = regexp.MustCompile(vmssNamingFormat)
vmssnameWindowsRegexp = regexp.MustCompile(windowsVmssNamingFormat)
}

// ResourceName returns the last segment (the resource name) for the specified resource identifier.
Expand Down Expand Up @@ -109,7 +116,7 @@ func WindowsVMNameParts(vmName string) (poolPrefix string, acsStr string, poolIn
if err != nil {
return "", "", -1, -1, fmt.Errorf("Error parsing VM Name: %v", err)
}

poolIndex -= 900
agentIndex, _ = strconv.Atoi(poolInfo[3:])
fmt.Printf("%d\n", agentIndex)

Expand All @@ -120,6 +127,26 @@ func WindowsVMNameParts(vmName string) (poolPrefix string, acsStr string, poolIn
return poolPrefix, acsStr, poolIndex, agentIndex, nil
}

// WindowsVMSSNameParts returns parts of Windows VM name e.g: 50621k8s900
func WindowsVMSSNameParts(vmssName string) (poolPrefix string, acsStr string, poolIndex int, err error) {
vmssNameParts := vmssnameWindowsRegexp.FindStringSubmatch(vmssName)
if len(vmssNameParts) != 4 {
return "", "", -1, fmt.Errorf("resource name was missing from identifier")
}

poolPrefix = vmssNameParts[windowsVmssAgentPoolNameIndex]
acsStr = vmssNameParts[windowsVmssAgentPoolOrchestratorNameIndex]
poolInfo := vmssNameParts[windowsVmssAgentPoolIndex]

poolIndex, err = strconv.Atoi(poolInfo)
if err != nil {
return "", "", -1, fmt.Errorf("Error parsing VM Name: %v", err)
}
poolIndex -= 900

return poolPrefix, acsStr, poolIndex, nil
}

// GetVMNameIndex return VM index of a node in the Kubernetes cluster
func GetVMNameIndex(osType compute.OperatingSystemTypes, vmName string) (int, error) {
var agentIndex int
Expand Down
22 changes: 21 additions & 1 deletion pkg/armhelpers/utils/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func Test_VmssNameParts(t *testing.T) {
func Test_WindowsVMNameParts(t *testing.T) {
expectedPoolPrefix := "38988"
expectedAcs := "k8s"
expectedPoolIndex := 903
expectedPoolIndex := 3
expectedAgentIndex := 12

poolPrefix, acs, poolIndex, agentIndex, err := WindowsVMNameParts("38988k8s90312")
Expand All @@ -103,6 +103,26 @@ func Test_WindowsVMNameParts(t *testing.T) {
}
}

func Test_WindowsVMSSNameParts(t *testing.T) {
expectedPoolPrefix := "38988"
expectedAcs := "k8s"
expectedPoolIndex := 3

poolPrefix, acs, poolIndex, err := WindowsVMSSNameParts("38988k8s903")
if poolPrefix != expectedPoolPrefix {
t.Fatalf("incorrect poolPrefix. expected=%s actual=%s", expectedPoolPrefix, poolPrefix)
}
if acs != expectedAcs {
t.Fatalf("incorrect acs string. expected=%s actual=%s", expectedAcs, acs)
}
if poolIndex != expectedPoolIndex {
t.Fatalf("incorrect poolIndex. expected=%d actual=%d", expectedPoolIndex, poolIndex)
}
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
}

func Test_GetVMNameIndexLinux(t *testing.T) {
expectedAgentIndex := 65

Expand Down
7 changes: 4 additions & 3 deletions pkg/operations/kubernetesupgrade/upgradecluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package kubernetesupgrade

import (
"fmt"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -230,13 +229,15 @@ func (uc *UpgradeCluster) addVMToAgentPool(vm compute.VirtualMachine, isUpgradab
return nil
}
} else if vm.StorageProfile.OsDisk.OsType == compute.Windows {
poolPrefix, acsStr, poolIndex, _, err := utils.WindowsVMNameParts(*vm.Name)
poolPrefix, _, _, _, err := utils.WindowsVMNameParts(*vm.Name)
if err != nil {
uc.Logger.Errorf(err.Error())
return err
}

poolIdentifier = poolPrefix + acsStr + strconv.Itoa(poolIndex)
//The k8s Windows VM Naming Format is "^([a-fA-F0-9]{5})([0-9a-zA-Z]{3})([a-zA-Z0-9]{4,6})$" (i.e.: 50621k8s9000)
//The pool identifier is made of the first 11 characters
poolIdentifier = (*vm.Name)[:11]

if !strings.Contains(uc.NameSuffix, poolPrefix) {
uc.Logger.Infof("Skipping VM: %s for upgrade as it does not belong to cluster with expected name suffix: %s\n",
Expand Down

0 comments on commit c02ec75

Please sign in to comment.