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
4 changes: 4 additions & 0 deletions src/aks-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ To release a new version, please select a new version number (usually plus 1 to
Pending
+++++++

22.0.0b4
+++++++++
* `az aks nodepool update`: Add preview `--zones`/`-z` support for migrating a regional node pool to automatic zone placement with `--zones auto`. Other availability zone changes are subject to service restrictions. Omitted zones remain unchanged, and the option can be combined with `--node-vm-size`.

22.0.0b3
+++++++++
* `az aks update`: Relax the bring-your-own VNet subnet validation for converting non-HOBO to HOBO Automatic cluster. `--apiserver-subnet-id` is no longer required, and `--system-node-subnet-id` can be supplied on its own; omitted subnets keep their current networking. `--enable-hosted-system` is still required to request the conversion, and `--node-subnet-id` still requires `--system-node-subnet-id`.
Expand Down
5 changes: 5 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2853,6 +2853,9 @@
- name: --node-vm-size -s
type: string
short-summary: VM size for Kubernetes nodes. For VMSS pools, changing this triggers a rolling upgrade to replace nodes with the new size (preview). For VirtualMachines pools, only configurable when updating autoscale settings.
- name: --zones -z
type: string array
short-summary: Use `auto` to migrate a regional node pool to automatic zone placement. Other availability zone changes are subject to service restrictions.
- name: --upgrade-strategy
type: string
short-summary: Upgrade strategy for the node pool. Allowed values are "Rolling" or "BlueGreen". Default is "Rolling".
Expand Down Expand Up @@ -2892,6 +2895,8 @@
text: az aks nodepool update -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --update-cluster-autoscaler --node-vm-size "Standard_D2s_v3" --min-count 2 --max-count 4
- name: Resize VM size for a VMSS node pool (preview, requires AFEC registration)
text: az aks nodepool update -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --node-vm-size Standard_D4s_v3
- name: Migrate a regional node pool to automatic zone placement.
text: az aks nodepool update -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --zones auto
- name: Update a node pool with blue-green upgrade settings
text: az aks nodepool update -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --drain-batch-size 50% --drain-timeout-bg 5 --batch-soak-duration 10 --final-soak-duration 10
- name: Update a nodepool with a Capacity Reservation Group(CRG) ID.
Expand Down
8 changes: 8 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -2628,6 +2628,14 @@ def load_arguments(self, _):
completer=get_vm_size_completion_list,
is_preview=True,
)
c.argument(
"zones",
zones_type,
options_list=["--zones", "-z"],
is_preview=True,
help='Use "auto" to migrate a regional node pool to automatic zone placement. '
'Other availability zone changes are subject to service restrictions.',
)
c.argument(
"gpu_driver",
arg_type=get_enum_type(gpu_driver_install_modes)
Expand Down
21 changes: 21 additions & 0 deletions src/aks-preview/azext_aks_preview/agentpool_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2119,6 +2119,23 @@ def update_vm_size(self, agentpool: AgentPool) -> AgentPool:

return agentpool

def update_zones(self, agentpool: AgentPool) -> AgentPool:
"""Update availability zones for the AgentPool object when explicitly requested.

The inherited context getter prefers the value from the fetched AgentPool over
the command-line value. Read the raw parameter here so an update can replace an
existing value while an omitted ``--zones`` leaves it untouched.

:return: the AgentPool object
"""
self._ensure_agentpool(agentpool)

zones = self.context.raw_param.get("zones")
if zones is not None:
agentpool.availability_zones = zones

return agentpool

def update_localdns_profile(self, agentpool: AgentPool) -> AgentPool:
"""Update local DNS profile for the AgentPool object if provided via --localdns-config."""
self._ensure_agentpool(agentpool)
Expand Down Expand Up @@ -2198,6 +2215,10 @@ def update_agentpool_profile_preview(self, agentpools: List[AgentPool] = None) -
# update vm size for VMSS pools
agentpool = self.update_vm_size(agentpool)

# Older CLI versions do not handle availability zones in the default update flow.
if not hasattr(AKSAgentPoolUpdateDecorator, "update_zones"):
agentpool = self.update_zones(agentpool)

# update local DNS profile
agentpool = self.update_localdns_profile(agentpool)

Expand Down
1 change: 1 addition & 0 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2388,6 +2388,7 @@ def aks_agentpool_update(
# local DNS
localdns_config=None,
node_vm_size=None,
zones=None,
gpu_driver=None,
gpu_mig_strategy=None,
# crg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interactions:
User-Agent:
- AZURECLI/2.58.0 azsdk-python-core/1.28.0 Python/3.8.10 (Linux-6.2.0-1019-azure-x86_64-with-glibc2.29)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2025-05-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2026-02-01
response:
body:
string: '{"error":{"code":"ResourceNotFound","message":"The Resource ''Microsoft.KeyVault/vaults/cliakstestkv000002''
Expand Down Expand Up @@ -70,7 +70,7 @@ interactions:
User-Agent:
- AZURECLI/2.58.0 azsdk-python-core/1.28.0 Python/3.8.10 (Linux-6.2.0-1019-azure-x86_64-with-glibc2.29)
method: PUT
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2025-05-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2026-02-01
response:
body:
string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002","name":"cliakstestkv000002","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"systemData":{"createdBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","createdByType":"Application","createdAt":"2024-03-11T07:38:10.965Z","lastModifiedBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","lastModifiedByType":"Application","lastModifiedAt":"2024-03-11T07:38:10.965Z"},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[],"enabledForDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":true,"vaultUri":"https://cliakstestkv000002.vault.azure.net","provisioningState":"RegisteringDns","publicNetworkAccess":"Enabled"}}'
Expand Down Expand Up @@ -120,7 +120,7 @@ interactions:
User-Agent:
- AZURECLI/2.58.0 azsdk-python-core/1.28.0 Python/3.8.10 (Linux-6.2.0-1019-azure-x86_64-with-glibc2.29)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2025-05-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2026-02-01
response:
body:
string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002","name":"cliakstestkv000002","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"systemData":{"createdBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","createdByType":"Application","createdAt":"2024-03-11T07:38:10.965Z","lastModifiedBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","lastModifiedByType":"Application","lastModifiedAt":"2024-03-11T07:38:10.965Z"},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[],"enabledForDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":true,"vaultUri":"https://cliakstestkv000002.vault.azure.net/","provisioningState":"RegisteringDns","publicNetworkAccess":"Enabled"}}'
Expand Down Expand Up @@ -168,7 +168,7 @@ interactions:
User-Agent:
- AZURECLI/2.58.0 azsdk-python-core/1.28.0 Python/3.8.10 (Linux-6.2.0-1019-azure-x86_64-with-glibc2.29)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2025-05-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2026-02-01
response:
body:
string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002","name":"cliakstestkv000002","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"systemData":{"createdBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","createdByType":"Application","createdAt":"2024-03-11T07:38:10.965Z","lastModifiedBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","lastModifiedByType":"Application","lastModifiedAt":"2024-03-11T07:38:10.965Z"},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[],"enabledForDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":true,"vaultUri":"https://cliakstestkv000002.vault.azure.net/","provisioningState":"Succeeded","publicNetworkAccess":"Enabled"}}'
Expand Down Expand Up @@ -1551,7 +1551,7 @@ interactions:
User-Agent:
- AZURECLI/2.58.0 azsdk-python-core/1.28.0 Python/3.8.10 (Linux-6.2.0-1019-azure-x86_64-with-glibc2.29)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2025-05-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2026-02-01
response:
body:
string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002","name":"cliakstestkv000002","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"systemData":{"createdBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","createdByType":"Application","createdAt":"2024-03-11T07:38:10.965Z","lastModifiedBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","lastModifiedByType":"Application","lastModifiedAt":"2024-03-11T07:38:10.965Z"},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[],"enabledForDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":true,"vaultUri":"https://cliakstestkv000002.vault.azure.net/","provisioningState":"Succeeded","publicNetworkAccess":"Enabled"}}'
Expand Down Expand Up @@ -1700,7 +1700,7 @@ interactions:
User-Agent:
- AZURECLI/2.58.0 azsdk-python-core/1.28.0 Python/3.8.10 (Linux-6.2.0-1019-azure-x86_64-with-glibc2.29)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2025-05-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002?api-version=2026-02-01
response:
body:
string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.KeyVault/vaults/cliakstestkv000002","name":"cliakstestkv000002","type":"Microsoft.KeyVault/vaults","location":"eastus","tags":{},"systemData":{"createdBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","createdByType":"Application","createdAt":"2024-03-11T07:38:10.965Z","lastModifiedBy":"3fac8b4e-cd90-4baa-a5d2-66d52bc8349d","lastModifiedByType":"Application","lastModifiedAt":"2024-03-11T07:38:10.965Z"},"properties":{"sku":{"family":"A","name":"standard"},"tenantId":"72f988bf-86f1-41af-91ab-2d7cd011db47","accessPolicies":[],"enabledForDeployment":false,"enableSoftDelete":true,"softDeleteRetentionInDays":90,"enableRbacAuthorization":true,"vaultUri":"https://cliakstestkv000002.vault.azure.net/","provisioningState":"Succeeded","publicNetworkAccess":"Enabled"}}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@ interactions:
User-Agent:
- AZURECLI/2.87.0 azsdk-python-core/1.39.0 Python/3.12.3 (Linux-6.17.0-1018-azure-x86_64-with-glibc2.39)
method: GET
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_clitest000001_cliakstest000001_eastus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-14233614-vmss/virtualMachines/1?api-version=2025-04-01
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_clitest000001_cliakstest000001_eastus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-14233614-vmss/virtualMachines/1?api-version=2026-04-01
response:
body:
string: "{\r\n \"name\": \"aks-nodepool1-14233614-vmss_1\",\r\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_clitest000001_cliakstest000001_eastus2/providers/Microsoft.Compute/virtualMachineScaleSets/aks-nodepool1-14233614-vmss/virtualMachines/1\",\r\n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3181,6 +3181,74 @@ def common_update_vm_size(self):
# vm_size should remain unchanged for VMs pools
self.assertEqual(dec_agentpool_3.vm_size, "Standard_D2s_v3")

def common_update_zones(self):
# No zones provided: preserve both the value and list instance from the fetched pool.
dec_1 = AKSPreviewAgentPoolUpdateDecorator(
self.cmd,
self.client,
{"zones": None},
self.resource_type,
self.agentpool_decorator_mode,
)
with self.assertRaises(CLIInternalError):
dec_1.update_zones(None)

existing_zones = ["1", "2"]
agentpool_1 = self.create_initialized_agentpool_instance(
availability_zones=existing_zones
)
stored_zones = agentpool_1.availability_zones
dec_1.context.attach_agentpool(agentpool_1)
dec_agentpool_1 = dec_1.update_zones(agentpool_1)
self.assertIs(dec_agentpool_1.availability_zones, stored_zones)

# The automatic-zone token is passed through as a one-element list.
dec_2 = AKSPreviewAgentPoolUpdateDecorator(
self.cmd,
self.client,
{"zones": ["auto"]},
self.resource_type,
self.agentpool_decorator_mode,
)
agentpool_2 = self.create_initialized_agentpool_instance(
availability_zones=None
)
dec_2.context.attach_agentpool(agentpool_2)
dec_agentpool_2 = dec_2.update_zones(agentpool_2)
self.assertEqual(dec_agentpool_2.availability_zones, ["auto"])

payload = dec_agentpool_2.as_dict()
if self.agentpool_decorator_mode == AgentPoolDecoratorMode.STANDALONE:
payload = payload["properties"]
self.assertEqual(payload["availabilityZones"], ["auto"])

# Explicit zone lists compose with a VM-size update on the same payload.
dec_3 = AKSPreviewAgentPoolUpdateDecorator(
self.cmd,
self.client,
{
"zones": ["1", "2", "3"],
"node_vm_size": "Standard_D4s_v3",
},
self.resource_type,
self.agentpool_decorator_mode,
)
agentpool_3 = self.create_initialized_agentpool_instance(
availability_zones=None,
vm_size="Standard_D2s_v3",
)
dec_3.context.attach_agentpool(agentpool_3)
dec_agentpool_3 = dec_3.update_vm_size(agentpool_3)
dec_agentpool_3 = dec_3.update_zones(dec_agentpool_3)
self.assertEqual(dec_agentpool_3.availability_zones, ["1", "2", "3"])
self.assertEqual(dec_agentpool_3.vm_size, "Standard_D4s_v3")

payload = dec_agentpool_3.as_dict()
if self.agentpool_decorator_mode == AgentPoolDecoratorMode.STANDALONE:
payload = payload["properties"]
self.assertEqual(payload["availabilityZones"], ["1", "2", "3"])
self.assertEqual(payload["vmSize"], "Standard_D4s_v3")

def common_update_upgrade_strategy(self):
# Test case 1: No upgrade strategy provided (should not change agentpool)
dec_1 = AKSPreviewAgentPoolUpdateDecorator(
Expand Down Expand Up @@ -3524,6 +3592,9 @@ def test_update_fips_image(self):
def test_update_vm_size(self):
self.common_update_vm_size()

def test_update_zones(self):
self.common_update_zones()

def test_update_upgrade_strategy(self):
self.common_update_upgrade_strategy()

Expand Down Expand Up @@ -3559,6 +3630,8 @@ def test_update_agentpool_profile_preview(self):
"nodepool_name",
]
self.assertEqual(positional_params, ground_truth_positional_params)
self.assertIn("zones", optional_params)
self.assertIsNone(optional_params["zones"])

# prepare a dictionary of default parameters
raw_param_dict = {
Expand Down Expand Up @@ -3623,6 +3696,9 @@ def test_update_fips_image(self):
def test_update_vm_size(self):
self.common_update_vm_size()

def test_update_zones(self):
self.common_update_zones()

def test_update_upgrade_strategy(self):
self.common_update_upgrade_strategy()

Expand Down
Loading
Loading