Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/aks-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ To release a new version, please select a new version number (usually plus 1 to

Pending
+++++++
* Add support for `ManagedSystem` Agent Pool Mode.

18.0.0b18
+++++++
* Add validation error when neither --location or --cluster and --resource-group-name are specified for az extension type list or az extension type version list



18.0.0b17
+++++++
* Remove `__import__('pkg_resources').declare_namespace(__name__)` from `vendored_sdks/__init__.py`` to fix the namespace package issue.
Expand Down
1 change: 1 addition & 0 deletions src/aks-preview/azext_aks_preview/_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
CONST_NODEPOOL_MODE_SYSTEM = "System"
CONST_NODEPOOL_MODE_USER = "User"
CONST_NODEPOOL_MODE_GATEWAY = "Gateway"
CONST_NODEPOOL_MODE_MANAGEDSYSTEM = "ManagedSystem"

# os type
CONST_DEFAULT_NODE_OS_TYPE = "Linux"
Expand Down
12 changes: 10 additions & 2 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,10 @@
- name: --vm-sizes
type: string
short-summary: Comma-separated list of sizes. Must use VirtualMachines agent pool type.
- name: --enable-managed-system-pool
type: bool
short-summary: Create a default ManagedSystem mode that is fully managed by AKS.
long-summary: When set, the default system node pool is created with ManagedSystem mode, where all properties except name and mode are managed by AKS. Learn more at https://aka.ms/aks/nodepool/mode.
examples:
- name: Create a Kubernetes cluster with an existing SSH public key.
text: az aks create -g MyResourceGroup -n MyManagedCluster --ssh-key-value /path/to/publickey
Expand Down Expand Up @@ -729,6 +733,8 @@
text: az aks create -g MyResourceGroup -n MyManagedCluster --os-sku Ubuntu --max-pods MaxPodsPerNode --network-plugin azure --vnet-subnet-id /subscriptions/00000/resourceGroups/AnotherResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVnet/subnets/NodeSubnet --pod-subnet-id /subscriptions/00000/resourceGroups/AnotherResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVnet/subnets/PodSubnet --pod-ip-allocation-mode StaticBlock
- name: Create a kubernetes cluster with a VirtualMachines nodepool
text: az aks create -g MyResourceGroup -n MyManagedCluster --vm-set-type VirtualMachines --vm-sizes "VMSize1,VMSize2" --node-count 3
- name: Create a kubernetes cluster with a fully managed system node pool
text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-managed-system-pool

"""

Expand Down Expand Up @@ -1933,7 +1939,7 @@
short-summary: The node labels for the node pool. See https://aka.ms/node-labels for syntax of labels.
- name: --mode
type: string
short-summary: The mode for a node pool which defines a node pool's primary function. If set as "System", AKS prefers system pods scheduling to node pools with mode `System`. Learn more at https://aka.ms/aks/nodepool/mode.
short-summary: The mode for a node pool which defines a node pool's primary function. If set as "System", AKS prefers system pods scheduling to node pools with mode `System`. If set as "ManagedSystem", all other properties except name and mode will be reset and managed by AKS. Learn more at https://aka.ms/aks/nodepool/mode.
- name: --vm-set-type
type: string
short-summary: Agent pool vm set type. VirtualMachineScaleSets, AvailabilitySet or VirtualMachines(Preview).
Expand Down Expand Up @@ -2061,6 +2067,8 @@
text: az aks nodepool add -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --os-sku Ubuntu --pod-subnet-id /subscriptions/00000/resourceGroups/AnotherResourceGroup/providers/Microsoft.Network/virtualNetworks/MyVnet/subnets/MySubnet --pod-ip-allocation-mode StaticBlock
- name: Create a nodepool of type VirtualMachines
text: az aks nodepool add -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --vm-set-type VirtualMachines --vm-sizes "Standard_D4s_v3,Standard_D8s_v3" --node-count 3
- name: Create a nodepool with ManagedSystem mode
text: az aks nodepool add -g MyResourceGroup -n managedsystem1 --cluster-name MyManagedCluster --mode ManagedSystem
"""

helps['aks nodepool scale'] = """
Expand Down Expand Up @@ -2157,7 +2165,7 @@
short-summary: The maximum number or percentage of extra nodes that are allowed to be blocked in the agent pool during an upgrade when undrainable node behavior is Cordon. When specified, it represents the number or percent used, eg. 1 or 5%.
- name: --mode
type: string
short-summary: The mode for a node pool which defines a node pool's primary function. If set as "System", AKS prefers system pods scheduling to node pools with mode `System`. Learn more at https://aka.ms/aks/nodepool/mode.
short-summary: The mode for a node pool which defines a node pool's primary function. If set as "System", AKS prefers system pods scheduling to node pools with mode `System`. If set as "ManagedSystem", all other properties except name and mode will be rejected and managed by AKS. Learn more at https://aka.ms/aks/nodepool/mode.
- name: --labels
type: string
short-summary: The node labels for the node pool. See https://aka.ms/node-labels for syntax of labels.
Expand Down
9 changes: 8 additions & 1 deletion src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
CONST_NODEPOOL_MODE_SYSTEM,
CONST_NODEPOOL_MODE_USER,
CONST_NODEPOOL_MODE_GATEWAY,
CONST_NODEPOOL_MODE_MANAGEDSYSTEM,
CONST_NONE_UPGRADE_CHANNEL,
CONST_NRG_LOCKDOWN_RESTRICTION_LEVEL_READONLY,
CONST_NRG_LOCKDOWN_RESTRICTION_LEVEL_UNRESTRICTED,
Expand Down Expand Up @@ -259,7 +260,12 @@
CONST_SPOT_EVICTION_POLICY_DEALLOCATE,
]
node_os_disk_types = [CONST_OS_DISK_TYPE_MANAGED, CONST_OS_DISK_TYPE_EPHEMERAL]
node_mode_types = [CONST_NODEPOOL_MODE_SYSTEM, CONST_NODEPOOL_MODE_USER, CONST_NODEPOOL_MODE_GATEWAY]
node_mode_types = [
CONST_NODEPOOL_MODE_SYSTEM,
CONST_NODEPOOL_MODE_USER,
CONST_NODEPOOL_MODE_GATEWAY,
CONST_NODEPOOL_MODE_MANAGEDSYSTEM,
]
node_os_skus_create = [
CONST_OS_SKU_AZURELINUX,
CONST_OS_SKU_UBUNTU,
Expand Down Expand Up @@ -1066,6 +1072,7 @@ def load_arguments(self, _):
# virtual machines
c.argument("vm_sizes", is_preview=True)
c.argument("enable_imds_restriction", action="store_true", is_preview=True)
c.argument("enable_managed_system_pool", action="store_true", is_preview=True)

with self.argument_context("aks update") as c:
# managed cluster paramerters
Expand Down
45 changes: 45 additions & 0 deletions src/aks-preview/azext_aks_preview/agentpool_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
AKSAgentPoolUpdateDecorator,
)
from azure.cli.core.azclierror import (
CLIInternalError,
InvalidArgumentValueError,
MutuallyExclusiveArgumentError,
)
Expand All @@ -41,6 +42,7 @@
CONST_DEFAULT_WINDOWS_VMS_VM_SIZE,
CONST_SSH_ACCESS_LOCALUSER,
CONST_GPU_DRIVER_NONE,
CONST_NODEPOOL_MODE_MANAGEDSYSTEM,
)
from azext_aks_preview._helpers import (
get_nodepool_snapshot_by_snapshot_id,
Expand Down Expand Up @@ -1070,6 +1072,33 @@ def set_up_virtual_machines_profile(self, agentpool: AgentPool) -> AgentPool:

return agentpool

def set_up_managed_system_mode(self, agentpool: AgentPool) -> AgentPool:
"""Handle the special ManagedSystem mode by resetting all properties except name and mode.

:param agentpool: the AgentPool object
:return: the AgentPool object
"""
if self.context.raw_param.get("enable_managed_system_pool") is True:
mode = CONST_NODEPOOL_MODE_MANAGEDSYSTEM
else:
mode = self.context.raw_param.get("mode")

if mode == CONST_NODEPOOL_MODE_MANAGEDSYSTEM:
# Raise error if agentpool is None
if agentpool is None:
raise CLIInternalError("agentpool cannot be None for ManagedSystem mode")

# Instead of creating a new instance, modify the existing one
# Keep name and set mode to ManagedSystem
agentpool.mode = CONST_NODEPOOL_MODE_MANAGEDSYSTEM
# Make sure all other attributes are None
for attr in vars(agentpool):
if attr != 'name' and attr != 'mode' and not attr.startswith('_'):
if hasattr(agentpool, attr):
setattr(agentpool, attr, None)

return agentpool

def construct_agentpool_profile_preview(self) -> AgentPool:
"""The overall controller used to construct the preview AgentPool profile.

Expand All @@ -1081,6 +1110,13 @@ def construct_agentpool_profile_preview(self) -> AgentPool:
# DO NOT MOVE: keep this on top, construct the default AgentPool profile
agentpool = self.construct_agentpool_profile_default(bypass_restore_defaults=True)

# Check if mode is ManagedSystem, if yes, reset all properties
agentpool = self.set_up_managed_system_mode(agentpool)

# If mode is ManagedSystem, skip all other property setups
if agentpool.mode == CONST_NODEPOOL_MODE_MANAGEDSYSTEM:
return agentpool

Comment on lines +1113 to +1119
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about putting it to the end of this constructor, then you don't need the check and return early.

Copy link
Contributor Author

@hao1939 hao1939 Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quit early could skip unnecessary code branch

# set up preview vm properties
agentpool = self.set_up_preview_vm_properties(agentpool)
# set up message of the day
Expand Down Expand Up @@ -1318,6 +1354,15 @@ def update_agentpool_profile_preview(self, agentpools: List[AgentPool] = None) -
# DO NOT MOVE: keep this on top, fetch and update the default AgentPool profile
agentpool = self.update_agentpool_profile_default(agentpools)

# Check if agentpool is in ManagedSystem mode and handle special case
if agentpool.mode == CONST_NODEPOOL_MODE_MANAGEDSYSTEM:
# Make sure all other attributes are None
for attr in vars(agentpool):
if attr != 'name' and attr != 'mode' and not attr.startswith('_'):
if hasattr(agentpool, attr):
setattr(agentpool, attr, None)
return agentpool
Comment on lines +1357 to +1364
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about wrapping this as a function (maybe add a helper function to do the clean up), and put it to the end of this update function?


# update custom ca trust
agentpool = self.update_custom_ca_trust(agentpool)

Expand Down
2 changes: 2 additions & 0 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,8 @@ def aks_create(
vm_sizes=None,
# IMDS restriction
enable_imds_restriction=False,
# managed system pool
enable_managed_system_pool=False,
):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down
22 changes: 22 additions & 0 deletions src/aks-preview/azext_aks_preview/managed_cluster_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
CONST_NETWORK_PLUGIN_AZURE,
CONST_NETWORK_PLUGIN_MODE_OVERLAY,
CONST_NETWORK_POLICY_CILIUM,
CONST_NODEPOOL_MODE_MANAGEDSYSTEM,
CONST_PRIVATE_DNS_ZONE_NONE,
CONST_PRIVATE_DNS_ZONE_SYSTEM,
CONST_ROTATION_POLL_INTERVAL,
Expand Down Expand Up @@ -3972,6 +3973,25 @@ def __init__(
self.__raw_parameters = raw_parameters
super().__init__(cmd, client, raw_parameters, resource_type)

def update_managed_system_pools(self, mc: ManagedCluster) -> ManagedCluster:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no corresponding option for command aks update, so this just acts as a guard?

BTW, this made me realize that other client tools probably don’t know that they need to clear other properties when switching nodepool mode to managed system. If the rp validation is strict, this will result in a bad request, resulting in a bad user experience.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mode is not allowed for updating, so we are not worried CX would change the mode.
For ManagedSystem Pool, because we restrict the api to reject any extra field but not ignore, so we need to clear those properties while reconciling.

"""Update ManagedSystem agent pools to only include name, mode, and type fields.

:return: the ManagedCluster object
"""
self._ensure_mc(mc)

if mc.agent_pool_profiles is None:
return mc
for agentpool in mc.agent_pool_profiles:
# Check if agentpool is in ManagedSystem mode and handle special case
if agentpool.mode == CONST_NODEPOOL_MODE_MANAGEDSYSTEM:
# Make sure all other attributes are None
for attr in vars(agentpool):
if attr != 'name' and attr != 'mode' and not attr.startswith('_'):
if hasattr(agentpool, attr):
setattr(agentpool, attr, None)
return mc

def init_models(self) -> None:
"""Initialize an AKSManagedClusterModels object to store the models.

Expand Down Expand Up @@ -5475,6 +5495,8 @@ def update_mc_profile_preview(self) -> ManagedCluster:
mc = self.update_vmas_to_vms(mc)
# update http proxy config
mc = self.update_http_proxy_enabled(mc)
# update ManagedSystem pools, must at end
mc = self.update_managed_system_pools(mc)

return mc

Expand Down
Loading
Loading