Skip to content

Commit 86b262d

Browse files
[AKS] az aks nodepool add/update/upgrade: Add --max-blocked-nodes to specify maximum number or percentage of extra nodes that are allowed to be blocked in the agent pool during an upgrade (Azure#8787)
1 parent 8e9a356 commit 86b262d

File tree

10 files changed

+1702
-6
lines changed

10 files changed

+1702
-6
lines changed

src/aks-preview/HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ To release a new version, please select a new version number (usually plus 1 to
1212
Pending
1313
+++++++
1414

15+
18.0.0b9
16+
+++++++
17+
* Add `--max-blocked-nodes` to the `az aks nodepool add/update/upgrade` commands.
18+
1519
18.0.0b8
1620
+++++++
1721
* Populate location of managed namespaces using managed cluster's location

src/aks-preview/azext_aks_preview/_help.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,6 +1934,9 @@
19341934
- name: --max-unavailable
19351935
type: string
19361936
short-summary: The maximum number or percentage of nodes that can be simultaneously unavailable during upgrade. When specified, it represents the number or percent used, eg. 1 or 5%
1937+
- name: --max-blocked-nodes
1938+
type: string
1939+
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%.
19371940
- name: --kubelet-config
19381941
type: string
19391942
short-summary: Kubelet configurations for agent nodes.
@@ -2076,6 +2079,9 @@
20762079
- name: --max-unavailable
20772080
type: string
20782081
short-summary: The maximum number or percentage of nodes that can be simultaneously unavailable during upgrade. When specified, it represents the number or percent used, eg. 1 or 5%
2082+
- name: --max-blocked-nodes
2083+
type: string
2084+
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%.
20792085
- name: --aks-custom-headers
20802086
type: string
20812087
short-summary: Send custom headers. When specified, format should be Key1=Value1,Key2=Value2
@@ -2128,6 +2134,9 @@
21282134
- name: --max-unavailable
21292135
type: string
21302136
short-summary: The maximum number or percentage of nodes that can be simultaneously unavailable during upgrade. When specified, it represents the number or percent used, eg. 1 or 5%
2137+
- name: --max-blocked-nodes
2138+
type: string
2139+
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%.
21312140
- name: --mode
21322141
type: string
21332142
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.

src/aks-preview/azext_aks_preview/_params.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@
215215
validate_bootstrap_container_registry_resource_id,
216216
validate_gateway_prefix_size,
217217
validate_max_unavailable,
218+
validate_max_blocked_nodes,
218219
validate_resource_group_parameter,
219220
validate_location_resource_group_cluster_parameters,
220221
)
@@ -1594,6 +1595,7 @@ def load_arguments(self, _):
15941595
c.argument("node_soak_duration", type=int)
15951596
c.argument("undrainable_node_behavior")
15961597
c.argument("max_unavailable", validator=validate_max_unavailable)
1598+
c.argument("max_blocked_nodes", validator=validate_max_blocked_nodes)
15971599
c.argument("mode", arg_type=get_enum_type(node_mode_types))
15981600
c.argument("scale_down_mode", arg_type=get_enum_type(scale_down_modes))
15991601
c.argument("max_pods", type=int, options_list=["--max-pods", "-m"])
@@ -1726,6 +1728,7 @@ def load_arguments(self, _):
17261728
c.argument("node_soak_duration", type=int)
17271729
c.argument("undrainable_node_behavior")
17281730
c.argument("max_unavailable", validator=validate_max_unavailable)
1731+
c.argument("max_blocked_nodes", validator=validate_max_blocked_nodes)
17291732
c.argument("mode", arg_type=get_enum_type(node_mode_types))
17301733
c.argument("scale_down_mode", arg_type=get_enum_type(scale_down_modes))
17311734
# extensions
@@ -1797,6 +1800,7 @@ def load_arguments(self, _):
17971800
c.argument("node_soak_duration", type=int)
17981801
c.argument("undrainable_node_behavior")
17991802
c.argument("max_unavailable", validator=validate_max_unavailable)
1803+
c.argument("max_blocked_nodes", validator=validate_max_blocked_nodes)
18001804
c.argument("snapshot_id", validator=validate_snapshot_id)
18011805
c.argument(
18021806
"yes",

src/aks-preview/azext_aks_preview/_validators.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,22 @@ def validate_max_unavailable(namespace):
519519
raise CLIError("--max-unavailable should be an int or percentage")
520520

521521

522+
def validate_max_blocked_nodes(namespace):
523+
"""validates parameters max blocked nodes is positive integers or percents."""
524+
if namespace.max_blocked_nodes is None:
525+
return
526+
int_or_percent = namespace.max_blocked_nodes
527+
if int_or_percent.endswith('%'):
528+
int_or_percent = int_or_percent.rstrip('%s')
529+
530+
try:
531+
if int(int_or_percent) < 0:
532+
raise InvalidArgumentValueError('--max-blocked-nodes must be be positive')
533+
except ValueError:
534+
# pylint: disable=raise-missing-from
535+
raise InvalidArgumentValueError('--max-blocked-nodes should be an int or percentage')
536+
537+
522538
def validate_assign_identity(namespace):
523539
if namespace.assign_identity is not None:
524540
if namespace.assign_identity == '':

src/aks-preview/azext_aks_preview/agentpool_decorator.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,26 @@ def get_max_unavailable(self) -> str:
503503
# this parameter does not need validation
504504
return max_unavailable
505505

506+
def get_max_blocked_nodes(self) -> str:
507+
"""Obtain the value of max_blocked_nodes.
508+
509+
:return: string
510+
"""
511+
# read the original value passed by the command
512+
max_blocked_nodes = self.raw_param.get("max_blocked_nodes")
513+
# In create mode, try to read the property value corresponding to the parameter from the `agentpool` object
514+
if self.decorator_mode == DecoratorMode.CREATE:
515+
if (
516+
self.agentpool and
517+
self.agentpool.upgrade_settings and
518+
self.agentpool.upgrade_settings.max_blocked_nodes is not None
519+
):
520+
max_blocked_nodes = self.agentpool.upgrade_settings.max_blocked_nodes
521+
522+
# this parameter does not need dynamic completion
523+
# this parameter does not need validation
524+
return max_blocked_nodes
525+
506526
def get_enable_artifact_streaming(self) -> bool:
507527
"""Obtain the value of enable_artifact_streaming.
508528
:return: bool
@@ -1127,6 +1147,10 @@ def set_up_upgrade_settings(self, agentpool: AgentPool) -> AgentPool:
11271147
if max_unavailable:
11281148
upgrade_settings.max_unavailable = max_unavailable
11291149

1150+
max_blocked_nodes = self.context.get_max_blocked_nodes()
1151+
if max_blocked_nodes:
1152+
upgrade_settings.max_blocked_nodes = max_blocked_nodes
1153+
11301154
agentpool.upgrade_settings = upgrade_settings
11311155
return agentpool
11321156

@@ -1352,6 +1376,11 @@ def update_upgrade_settings(self, agentpool: AgentPool) -> AgentPool:
13521376
upgrade_settings.undrainable_node_behavior = undrainable_node_behavior
13531377
agentpool.upgrade_settings = upgrade_settings
13541378

1379+
max_blocked_nodes = self.context.get_max_blocked_nodes()
1380+
if max_blocked_nodes:
1381+
upgrade_settings.max_blocked_nodes = max_blocked_nodes
1382+
agentpool.upgrade_settings = upgrade_settings
1383+
13551384
max_unavailable = self.context.get_max_unavailable()
13561385
if max_unavailable:
13571386
upgrade_settings.max_unavailable = max_unavailable

src/aks-preview/azext_aks_preview/custom.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,7 @@ def aks_agentpool_add(
13591359
node_soak_duration=None,
13601360
undrainable_node_behavior=None,
13611361
max_unavailable=None,
1362+
max_blocked_nodes=None,
13621363
mode=CONST_NODEPOOL_MODE_USER,
13631364
scale_down_mode=CONST_SCALE_DOWN_MODE_DELETE,
13641365
max_pods=0,
@@ -1442,6 +1443,7 @@ def aks_agentpool_update(
14421443
node_soak_duration=None,
14431444
undrainable_node_behavior=None,
14441445
max_unavailable=None,
1446+
max_blocked_nodes=None,
14451447
mode=None,
14461448
scale_down_mode=None,
14471449
no_wait=False,
@@ -1534,6 +1536,7 @@ def aks_agentpool_upgrade(cmd,
15341536
node_soak_duration=None,
15351537
undrainable_node_behavior=None,
15361538
max_unavailable=None,
1539+
max_blocked_nodes=None,
15371540
snapshot_id=None,
15381541
no_wait=False,
15391542
aks_custom_headers=None,
@@ -1553,13 +1556,24 @@ def aks_agentpool_upgrade(cmd,
15531556
)
15541557

15551558
# Note: we exclude this option because node image upgrade can't accept nodepool put fields like max surge
1556-
hasUpgradeSetting = max_surge or drain_timeout or node_soak_duration or undrainable_node_behavior or max_unavailable
1559+
hasUpgradeSetting = (
1560+
max_surge or
1561+
drain_timeout or
1562+
node_soak_duration or
1563+
undrainable_node_behavior or
1564+
max_unavailable or
1565+
max_blocked_nodes)
15571566
if hasUpgradeSetting and node_image_only:
15581567
raise MutuallyExclusiveArgumentError(
1559-
"Conflicting flags. Unable to specify max-surge/drain-timeout/node-soak-duration with node-image-only."
1560-
"If you want to use max-surge/drain-timeout/node-soak-duration with a node image upgrade, please first "
1561-
"update max-surge/drain-timeout/node-soak-duration using "
1562-
'"az aks nodepool update --max-surge/--drain-timeout/--node-soak-duration".'
1568+
"Conflicting flags. Unable to specify "
1569+
"max-surge/drain-timeout/node-soak-duration/undrainable-node-behavior/max-unavailable/max-blocked-nodes"
1570+
" with node-image-only.If you want to use "
1571+
"max-surge/drain-timeout/node-soak-duration/undrainable-node-behavior/max-unavailable/max-blocked-nodes"
1572+
" with a node image upgrade, please first update "
1573+
"max-surge/drain-timeout/node-soak-duration/undrainable-node-behavior/max-unavailable/max-blocked-nodes"
1574+
" using 'az aks nodepool update "
1575+
"--max-surge/--drain-timeout/--node-soak-duration/"
1576+
"--undrainable-node-behavior/--max-unavailable/--max-blocked-nodes'."
15631577
)
15641578

15651579
if node_image_only:
@@ -1621,6 +1635,8 @@ def aks_agentpool_upgrade(cmd,
16211635
instance.upgrade_settings.undrainable_node_behavior = undrainable_node_behavior
16221636
if max_unavailable:
16231637
instance.upgrade_settings.max_unavailable = max_unavailable
1638+
if max_blocked_nodes:
1639+
instance.upgrade_settings.max_blocked_nodes = max_blocked_nodes
16241640

16251641
# custom headers
16261642
aks_custom_headers = extract_comma_separated_string(

0 commit comments

Comments
 (0)