Skip to content

Commit a531595

Browse files
authored
[AKS] support Virtual Machines node pools in AKS (#31780)
1 parent 3f91119 commit a531595

File tree

10 files changed

+5551
-19
lines changed

10 files changed

+5551
-19
lines changed

src/azure-cli/azure/cli/command_modules/acs/_consts.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,15 @@
4242
# vm set type
4343
CONST_VIRTUAL_MACHINE_SCALE_SETS = "VirtualMachineScaleSets"
4444
CONST_AVAILABILITY_SET = "AvailabilitySet"
45+
CONST_VIRTUAL_MACHINES = "VirtualMachines"
4546

4647
# vm size
4748
CONST_DEFAULT_NODE_VM_SIZE = ""
4849
CONST_DEFAULT_WINDOWS_NODE_VM_SIZE = ""
4950

51+
CONST_DEFAULT_VMS_VM_SIZE = "Standard_DS2_v2"
52+
CONST_DEFAULT_WINDOWS_VMS_VM_SIZE = "Standard_D2s_v3"
53+
5054
# gpu instance
5155
CONST_GPU_INSTANCE_PROFILE_MIG1_G = "MIG1g"
5256
CONST_GPU_INSTANCE_PROFILE_MIG2_G = "MIG2g"

src/azure-cli/azure/cli/command_modules/acs/_help.py

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666
- name: --node-vm-size -s
6767
type: string
6868
short-summary: Size of Virtual Machines to create as Kubernetes nodes. If the user does not specify one, server will select a default VM size for her/him.
69+
- name: --vm-sizes
70+
type: string
71+
short-summary: Comma-separated list of VM sizes. Valid for VirtualMachines node pool only. If `--vm-sizes` not specified but `--node-vm-size` specified, value of `--node-vm-size` will be used. If neither of them specified, defaults to Standard_DS2_v2 for Linux or Standard_D2s_v3 for Windows.
6972
- name: --dns-name-prefix -p
7073
type: string
7174
short-summary: Prefix for hostnames that are created. If not specified, generate a hostname using the managed cluster and resource group names.
@@ -201,7 +204,7 @@
201204
short-summary: Maximum nodes count used for autoscaler, when "--enable-cluster-autoscaler" specified. Please specify the value in the range of [1, 1000].
202205
- name: --vm-set-type
203206
type: string
204-
short-summary: Agent pool vm set type. VirtualMachineScaleSets or AvailabilitySet. Defaults to 'VirtualMachineScaleSets'
207+
short-summary: Agent pool vm set type. VirtualMachineScaleSets or AvailabilitySet or VirtualMachines. Defaults to 'VirtualMachineScaleSets'
205208
- name: --enable-addons -a
206209
type: string
207210
short-summary: Enable the Kubernetes addons in a comma-separated list.
@@ -301,10 +304,10 @@
301304
short-summary: The ID of a PPG.
302305
- name: --enable-node-public-ip
303306
type: bool
304-
short-summary: Enable VMSS node public IP.
307+
short-summary: Enable VMSS or VMs node public IP.
305308
- name: --node-public-ip-prefix-id
306309
type: string
307-
short-summary: Public IP prefix ID used to assign public IPs to VMSS nodes.
310+
short-summary: Public IP prefix ID used to assign public IPs to VMSS or VMs nodes.
308311
- name: --workspace-resource-id
309312
type: string
310313
short-summary: The resource ID of an existing Log Analytics Workspace to use for storing monitoring data. If not specified, uses the default Log Analytics Workspace if it exists, otherwise creates one.
@@ -559,10 +562,10 @@
559562
short-summary: Enable exporting Kubernetes Namespace and Deployment details to the Cost Analysis views in the Azure portal. For more information see aka.ms/aks/docs/cost-analysis.
560563
- name: --enable-secure-boot
561564
type: bool
562-
short-summary: Enable Secure Boot on all node pools in the cluster. Must use VMSS agent pool type.
565+
short-summary: Enable Secure Boot on all node pools in the cluster. Must use VMSS or VMs agent pool type.
563566
- name: --enable-vtpm
564567
type: bool
565-
short-summary: Enable vTPM on all node pools in the cluster. Must use VMSS agent pool type.
568+
short-summary: Enable vTPM on all node pools in the cluster. Must use VMSS or VMs agent pool type.
566569
- name: --enable-acns
567570
type: bool
568571
short-summary: Enable advanced network functionalities on a cluster. Enabling this will incur additional costs. For non-cilium clusters, acns security will be disabled by default until further notice.
@@ -670,6 +673,8 @@
670673
text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-azure-service-mesh
671674
- name: Create a kubernetes cluster with a nodepool having ip allocation mode set to "StaticBlock"
672675
text: az aks create -g MyResourceGroup -n MyManagedCluster --os-sku Ubuntu --max-pods MaxPodsPerNode --network-plugin azure --vnet-subnet-id /subscriptions/SubID/resourceGroups/AnotherResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVnet/subnets/NodeSubnet --pod-subnet-id /subscriptions/SubID/resourceGroups/AnotherResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVnet/subnets/PodSubnet --pod-ip-allocation-mode StaticBlock
676+
- name: Create a kubernetes cluster with VirtualMachines vm set type.
677+
text: az aks create -g MyResourceGroup -n MyManagedCluster --vm-set-type VirtualMachines --vm-sizes "VMSize1,VMSize2" --node-count 3
673678
"""
674679

675680
helps['aks update'] = """
@@ -1570,6 +1575,12 @@
15701575
- name: --node-vm-size -s
15711576
type: string
15721577
short-summary: Size of Virtual Machines to create as Kubernetes nodes. If the user does not specify one, server will select a default VM size for her/him.
1578+
- name: --vm-sizes
1579+
type: string
1580+
short-summary: Comma-separated list of VM sizes. Valid for VirtualMachines node pool only. If `--vm-sizes` not specified but `--node-vm-size` specified, value of `--node-vm-size` will be used. If neither of them specified, defaults to Standard_DS2_v2 for Linux or Standard_D2s_v3 for Windows.
1581+
- name: --vm-set-type
1582+
type: string
1583+
short-summary: Agent pool vm set type. VirtualMachineScaleSets or AvailabilitySet or VirtualMachines. Defaults to 'VirtualMachineScaleSets'
15731584
- name: --node-count -c
15741585
type: int
15751586
short-summary: Number of nodes in the Kubernetes agent pool. After creating a cluster, you can change the size of its node pool with `az aks scale`.
@@ -1593,10 +1604,10 @@
15931604
short-summary: Availability zones where agent nodes will be placed. Also, to install agent nodes to more than one zone you need to pass zone numbers separated by blanks. For example - To have all 3 zones, you are expected to enter `--zones 1 2 3`
15941605
- name: --enable-node-public-ip
15951606
type: bool
1596-
short-summary: Enable VMSS node public IP.
1607+
short-summary: Enable VMSS or VMs node public IP.
15971608
- name: --node-public-ip-prefix-id
15981609
type: string
1599-
short-summary: Public IP prefix ID used to assign public IPs to VMSS nodes.
1610+
short-summary: Public IP prefix ID used to assign public IPs to VMSS or VMs nodes.
16001611
- name: --vnet-subnet-id
16011612
type: string
16021613
short-summary: The Resource Id of a subnet in an existing VNet into which to deploy the cluster.
@@ -1710,10 +1721,10 @@
17101721
short-summary: Disable Windows OutboundNAT on Windows agent node pool.
17111722
- name: --enable-secure-boot
17121723
type: bool
1713-
short-summary: Enable Secure Boot on agent node pool. Must use VMSS agent pool type.
1724+
short-summary: Enable Secure Boot on agent node pool. Must use VMSS or VMs agent pool type.
17141725
- name: --enable-vtpm
17151726
type: bool
1716-
short-summary: Enable vTPM on agent node pool. Must use VMSS agent pool type.
1727+
short-summary: Enable vTPM on agent node pool. Must use VMSS or VMs agent pool type.
17171728
- name: --if-match
17181729
type: string
17191730
short-summary: The value provided will be compared to the ETag of the agentpool, if it matches the operation will proceed. If it does not match, the request will be rejected to prevent accidental overwrites. This must not be specified when creating a new agentpool.
@@ -1745,6 +1756,8 @@
17451756
text: az aks nodepool add -g MyResourceGroup -n MyNodePool --cluster-name MyMC --node-vm-size VMSize --crg-id "/subscriptions/SubID/resourceGroups/ResourceGroupName/providers/Microsoft.ContainerService/CapacityReservationGroups/MyCRGID"
17461757
- name: Create a nodepool with ip allocation mode set to "StaticBlock" and using a pod subnet ID
17471758
text: az aks nodepool add -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --os-sku Ubuntu --pod-subnet-id /subscriptions/SubID/resourceGroups/AnotherResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVnet/subnets/MySubnet --pod-ip-allocation-mode StaticBlock
1759+
- name: create a nodepool of type VirtualMachines
1760+
text: az aks nodepool add -g MyResourceGroup -n MyNodePool --cluster-name MyMC --vm-set-type VirtualMachines --vm-sizes "VMSize1,VMSize2" --node-count 3
17481761
"""
17491762

17501763
helps['aks nodepool delete'] = """
@@ -1857,13 +1870,13 @@
18571870
short-summary: Switch to use non-FIPS-enabled OS on agent nodes.
18581871
- name: --enable-secure-boot
18591872
type: bool
1860-
short-summary: Enable Secure Boot on an existing Trusted Launch enabled agent node pool. Must use VMSS agent pool type.
1873+
short-summary: Enable Secure Boot on an existing Trusted Launch enabled agent node pool. Must use VMSS or VMs agent pool type.
18611874
- name: --disable-secure-boot
18621875
type: bool
18631876
short-summary: Disable Secure Boot on on an existing Trusted Launch enabled agent node pool.
18641877
- name: --enable-vtpm
18651878
type: bool
1866-
short-summary: Enable vTPM on an existing Trusted Launch enabled agent node pool. Must use VMSS agent pool type.
1879+
short-summary: Enable vTPM on an existing Trusted Launch enabled agent node pool. Must use VMSS or VMs agent pool type.
18671880
- name: --disable-vtpm
18681881
type: bool
18691882
short-summary: Disable vTPM on an existing Trusted Launch enabled agent node pool.
@@ -2000,6 +2013,47 @@
20002013
crafted: true
20012014
"""
20022015

2016+
helps['aks nodepool manual-scale'] = """
2017+
type: group
2018+
short-summary: Commands to manage nodepool virtualMachineProfile.scale.manual.
2019+
"""
2020+
2021+
helps['aks nodepool manual-scale add'] = """
2022+
type: command
2023+
short-summary: Add a new manual to a VirtualMachines agentpool in the managed Kubernetes cluster.
2024+
parameters:
2025+
- name: --vm-sizes
2026+
type: string
2027+
short-summary: Comma-separated list of sizes in the manual.
2028+
- name: --node-count -c
2029+
type: int
2030+
short-summary: Number of nodes in the manual.
2031+
"""
2032+
2033+
helps['aks nodepool manual-scale update'] = """
2034+
type: command
2035+
short-summary: Update an existing manual of a VirtualMachines agentpool in the managed Kubernetes cluster.
2036+
parameters:
2037+
- name: --current-vm-sizes
2038+
type: string
2039+
short-summary: Comma-separated list of sizes in the manual to be updated.
2040+
- name: --vm-sizes
2041+
type: string
2042+
short-summary: Comma-separated list of new sizes.
2043+
- name: --node-count -c
2044+
type: int
2045+
short-summary: Number of nodes in the manual.
2046+
"""
2047+
2048+
helps['aks nodepool manual-scale delete'] = """
2049+
type: command
2050+
short-summary: Delete an existing manual to a VirtualMachines agentpool in the managed Kubernetes cluster.
2051+
parameters:
2052+
- name: --current-vm-sizes
2053+
type: string
2054+
short-summary: Comma-separated list of sizes in the manual to be deleted.
2055+
"""
2056+
20032057
helps['aks show'] = """
20042058
type: command
20052059
short-summary: Show the details for a managed Kubernetes cluster.

src/azure-cli/azure/cli/command_modules/acs/_params.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ def load_arguments(self, _):
445445
c.argument('nodepool_name', default='nodepool1',
446446
help='Node pool name, up to 12 alphanumeric characters', validator=validate_nodepool_name)
447447
c.argument('node_vm_size', options_list=['--node-vm-size', '-s'], completer=get_vm_size_completion_list)
448+
c.argument('vm_sizes')
448449
c.argument('os_sku', arg_type=get_enum_type(node_os_skus_create), validator=validate_os_sku)
449450
c.argument('snapshot_id', validator=validate_snapshot_id)
450451
c.argument('vnet_subnet_id', validator=validate_vnet_subnet_id)
@@ -823,6 +824,8 @@ def load_arguments(self, _):
823824

824825
with self.argument_context('aks nodepool add') as c:
825826
c.argument('node_vm_size', options_list=['--node-vm-size', '-s'], completer=get_vm_size_completion_list)
827+
c.argument('vm_sizes')
828+
c.argument('vm_set_type', validator=validate_vm_set_type)
826829
c.argument('os_type')
827830
c.argument('os_sku', arg_type=get_enum_type(node_os_skus), validator=validate_os_sku)
828831
c.argument('snapshot_id', validator=validate_snapshot_id)
@@ -913,6 +916,16 @@ def load_arguments(self, _):
913916
c.argument('snapshot_id', validator=validate_snapshot_id)
914917
c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true')
915918

919+
with self.argument_context("aks nodepool manual-scale add") as c:
920+
c.argument("vm_sizes")
921+
922+
with self.argument_context("aks nodepool manual-scale update") as c:
923+
c.argument("current_vm_sizes")
924+
c.argument("vm_sizes")
925+
926+
with self.argument_context("aks nodepool manual-scale delete") as c:
927+
c.argument("current_vm_sizes")
928+
916929
with self.argument_context('aks command invoke') as c:
917930
c.argument('command_string', options_list=[
918931
"--command", "-c"], help='the command to run')

src/azure-cli/azure/cli/command_modules/acs/_validators.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
CONST_NETWORK_POD_IP_ALLOCATION_MODE_DYNAMIC_INDIVIDUAL,
2020
CONST_NETWORK_POD_IP_ALLOCATION_MODE_STATIC_BLOCK,
2121
CONST_NODEPOOL_MODE_GATEWAY,
22+
CONST_VIRTUAL_MACHINE_SCALE_SETS,
23+
CONST_AVAILABILITY_SET,
24+
CONST_VIRTUAL_MACHINES,
2225
)
2326
from azure.cli.core import keys
2427
from azure.cli.core.azclierror import (
@@ -185,9 +188,12 @@ def validate_vm_set_type(namespace):
185188
if namespace.vm_set_type is not None:
186189
if namespace.vm_set_type == '':
187190
return
188-
if namespace.vm_set_type.lower() != "availabilityset" and \
189-
namespace.vm_set_type.lower() != "virtualmachinescalesets":
190-
raise CLIError("--vm-set-type can only be VirtualMachineScaleSets or AvailabilitySet")
191+
if (
192+
namespace.vm_set_type.lower() != CONST_VIRTUAL_MACHINE_SCALE_SETS.lower() and
193+
namespace.vm_set_type.lower() != CONST_AVAILABILITY_SET.lower() and
194+
namespace.vm_set_type.lower() != CONST_VIRTUAL_MACHINES.lower()
195+
):
196+
raise CLIError("--vm-set-type can only be VirtualMachineScaleSets or AvailabilitySet or VirtualMachines")
191197

192198

193199
def validate_load_balancer_sku(namespace):

src/azure-cli/azure/cli/command_modules/acs/agentpool_decorator.py

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
CONST_DEFAULT_NODE_OS_TYPE,
1616
CONST_DEFAULT_NODE_VM_SIZE,
1717
CONST_DEFAULT_WINDOWS_NODE_VM_SIZE,
18+
CONST_DEFAULT_VMS_VM_SIZE,
19+
CONST_DEFAULT_WINDOWS_VMS_VM_SIZE,
1820
CONST_NODEPOOL_MODE_SYSTEM,
1921
CONST_NODEPOOL_MODE_USER,
2022
CONST_SCALE_DOWN_MODE_DELETE,
2123
CONST_SCALE_SET_PRIORITY_REGULAR,
2224
CONST_SCALE_SET_PRIORITY_SPOT,
2325
CONST_SPOT_EVICTION_POLICY_DELETE,
2426
CONST_VIRTUAL_MACHINE_SCALE_SETS,
27+
CONST_VIRTUAL_MACHINES,
2528
CONST_OS_SKU_WINDOWS2019,
2629
CONST_OS_SKU_WINDOWS2022,
2730
AgentPoolDecoratorMode,
@@ -629,6 +632,33 @@ def get_node_vm_size(self) -> str:
629632
"""
630633
return self._get_node_vm_size(read_only=False)
631634

635+
def get_vm_sizes(self) -> List[str]:
636+
"""Obtain the value of vm_sizes.
637+
638+
:return: list of strings
639+
"""
640+
raw_value = self.raw_param.get("vm_sizes")
641+
node_vm_size = self.raw_param.get("node_vm_size")
642+
if raw_value is not None:
643+
# vm_sizes is a comma-separated string, only used when vm_set_type is VirtualMachines
644+
if self.get_vm_set_type() != CONST_VIRTUAL_MACHINES:
645+
raise InvalidArgumentValueError("--vm-sizes can only be used with --vm-set-type VirtualMachines.")
646+
if node_vm_size:
647+
raise MutuallyExclusiveArgumentError("Cannot specify -vm-sizes and --node-vm-size at the same time.")
648+
vm_sizes = [x.strip() for x in raw_value.split(",")]
649+
else:
650+
# when vm_sizes is not specified, try to use the value from node_vm_size (only 1 size)
651+
if node_vm_size:
652+
vm_sizes = [node_vm_size]
653+
else:
654+
# use default value
655+
if self.get_os_type().lower() == "windows":
656+
vm_sizes = [CONST_DEFAULT_WINDOWS_VMS_VM_SIZE]
657+
else:
658+
vm_sizes = [CONST_DEFAULT_VMS_VM_SIZE]
659+
660+
return vm_sizes
661+
632662
def _get_os_type(self, read_only: bool = False) -> Union[str, None]:
633663
"""Internal function to dynamically obtain the value of os_type according to the context.
634664
@@ -1222,8 +1252,12 @@ def get_vm_set_type(self) -> str:
12221252
vm_set_type = CONST_VIRTUAL_MACHINE_SCALE_SETS
12231253
elif vm_set_type.lower() == CONST_AVAILABILITY_SET.lower():
12241254
vm_set_type = CONST_AVAILABILITY_SET
1255+
elif vm_set_type.lower() == CONST_VIRTUAL_MACHINES.lower():
1256+
vm_set_type = CONST_VIRTUAL_MACHINES
12251257
else:
1226-
raise InvalidArgumentValueError("--vm-set-type can only be VirtualMachineScaleSets or AvailabilitySet")
1258+
raise InvalidArgumentValueError(
1259+
"--vm-set-type can only be VirtualMachineScaleSets or AvailabilitySet or VirtualMachines"
1260+
)
12271261
# this parameter does not need validation
12281262
return vm_set_type
12291263

@@ -2064,6 +2098,37 @@ def set_up_pod_ip_allocation_mode(self, agentpool: AgentPool) -> AgentPool:
20642098

20652099
return agentpool
20662100

2101+
def set_up_virtual_machines_profile(self, agentpool: AgentPool) -> AgentPool:
2102+
"""Set up virtual machines profile for the AgentPool object.
2103+
2104+
:return: the AgentPool object
2105+
"""
2106+
self._ensure_agentpool(agentpool)
2107+
2108+
# validate vm_sizes first, then skip if not Virtual Machines
2109+
sizes = self.context.get_vm_sizes()
2110+
if len(sizes) != 1:
2111+
raise InvalidArgumentValueError(f"We only accept single sku size for manual profile. {sizes} is invalid.")
2112+
2113+
if self.context.get_vm_set_type() != CONST_VIRTUAL_MACHINES:
2114+
return agentpool
2115+
2116+
count, _, _, _ = self.context.get_node_count_and_enable_cluster_autoscaler_min_max_count()
2117+
agentpool.virtual_machines_profile = self.models.VirtualMachinesProfile(
2118+
scale=self.models.ScaleProfile(
2119+
manual=[
2120+
self.models.ManualScaleProfile(
2121+
size=sizes[0],
2122+
count=count,
2123+
)
2124+
]
2125+
)
2126+
)
2127+
agentpool.vm_size = None
2128+
agentpool.count = None
2129+
2130+
return agentpool
2131+
20672132
def construct_agentpool_profile_default(self, bypass_restore_defaults: bool = False) -> AgentPool:
20682133
"""The overall controller used to construct the AgentPool profile by default.
20692134
@@ -2114,6 +2179,8 @@ def construct_agentpool_profile_default(self, bypass_restore_defaults: bool = Fa
21142179
agentpool = self.set_up_gpu_profile(agentpool)
21152180
# set up agentpool gateway profile
21162181
agentpool = self.set_up_agentpool_gateway_profile(agentpool)
2182+
# set up virtual machines profile
2183+
agentpool = self.set_up_virtual_machines_profile(agentpool)
21172184
# restore defaults
21182185
if not bypass_restore_defaults:
21192186
agentpool = self._restore_defaults_in_agentpool(agentpool)

src/azure-cli/azure/cli/command_modules/acs/commands.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ def load_command_table(self, _):
151151
g.custom_command('operation-abort', 'aks_agentpool_operation_abort', supports_no_wait=True)
152152
g.custom_command('delete-machines', 'aks_agentpool_delete_machines', supports_no_wait=True)
153153

154+
# AKS nodepool manual-scale command
155+
with self.command_group('aks nodepool manual-scale', agent_pools_sdk, client_factory=cf_agent_pools) as g:
156+
g.custom_command("add", "aks_agentpool_manual_scale_add", supports_no_wait=True)
157+
g.custom_command("update", "aks_agentpool_manual_scale_update", supports_no_wait=True)
158+
g.custom_command("delete", "aks_agentpool_manual_scale_delete", supports_no_wait=True, confirmation=True)
159+
154160
with self.command_group('aks command', managed_clusters_sdk, client_factory=cf_managed_clusters) as g:
155161
g.custom_command('invoke', 'aks_runcommand', supports_no_wait=True,
156162
table_transformer=aks_run_command_result_format)

0 commit comments

Comments
 (0)