Skip to content

Commit bbefc97

Browse files
authored
[AKS] az aks create/update az aks nodepool add: Add static egress gateway feature support (#31285)
1 parent e9f92bc commit bbefc97

13 files changed

+3893
-8
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
# mode
2626
CONST_NODEPOOL_MODE_SYSTEM = "System"
2727
CONST_NODEPOOL_MODE_USER = "User"
28+
CONST_NODEPOOL_MODE_GATEWAY = "Gateway"
2829

2930
# os type
3031
CONST_DEFAULT_NODE_OS_TYPE = "Linux"

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,9 @@
584584
- name: --bootstrap-container-registry-resource-id
585585
type: string
586586
short-summary: Configure container registry resource ID. Must use "Cache" as bootstrap artifact source.
587-
587+
- name: --enable-static-egress-gateway
588+
type: bool
589+
short-summary: Enable Static Egress Gateway addon to the cluster.
588590
examples:
589591
- name: Create a Kubernetes cluster with an existing SSH public key.
590592
text: az aks create -g MyResourceGroup -n MyManagedCluster --ssh-key-value /path/to/publickey
@@ -1036,6 +1038,12 @@
10361038
- name: --bootstrap-container-registry-resource-id
10371039
type: string
10381040
short-summary: Configure container registry resource ID. Must use "Cache" as bootstrap artifact source.
1041+
- name: --enable-static-egress-gateway
1042+
type: bool
1043+
short-summary: Enable Static Egress Gateway addon to the cluster.
1044+
- name: --disable-static-egress-gateway
1045+
type: bool
1046+
short-summary: Disable Static Egress Gateway addon to the cluster.
10391047
examples:
10401048
- name: Reconcile the cluster back to its current state.
10411049
text: az aks update -g MyResourceGroup -n MyManagedCluster
@@ -1701,7 +1709,9 @@
17011709
- name: --gpu-driver
17021710
type: string
17031711
short-summary: Whether to install driver for GPU node pool. Possible values are "Install" or "None". Default is "Install".
1704-
1712+
- name: --gateway-prefix-size
1713+
type: int
1714+
short-summary: The size of Public IPPrefix attached to the Gateway-mode node pool. The node pool must be in Gateway mode.
17051715
examples:
17061716
- name: Create a nodepool in an existing AKS cluster with ephemeral os enabled.
17071717
text: az aks nodepool add -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --node-osdisk-type Ephemeral --node-osdisk-size 48

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
CONST_NODE_OS_CHANNEL_NONE,
2929
CONST_NODE_OS_CHANNEL_UNMANAGED,
3030
CONST_NODE_OS_CHANNEL_SECURITY_PATCH,
31-
CONST_NODEPOOL_MODE_SYSTEM, CONST_NODEPOOL_MODE_USER,
31+
CONST_NODEPOOL_MODE_SYSTEM, CONST_NODEPOOL_MODE_USER, CONST_NODEPOOL_MODE_GATEWAY,
3232
CONST_OS_DISK_TYPE_EPHEMERAL, CONST_OS_DISK_TYPE_MANAGED,
3333
CONST_OS_SKU_AZURELINUX, CONST_OS_SKU_CBLMARINER, CONST_OS_SKU_MARINER,
3434
CONST_OS_SKU_UBUNTU, CONST_OS_SKU_UBUNTU2204,
@@ -110,7 +110,9 @@
110110
validate_azure_service_mesh_revision,
111111
validate_message_of_the_day,
112112
validate_custom_ca_trust_certificates,
113-
validate_bootstrap_container_registry_resource_id)
113+
validate_bootstrap_container_registry_resource_id,
114+
validate_gateway_prefix_size,
115+
)
114116
from azure.cli.core.commands.parameters import (
115117
edge_zone_type, file_type, get_enum_type,
116118
get_resource_name_completion_list, get_three_state_flag, name_type,
@@ -158,7 +160,7 @@
158160
node_priorities = [CONST_SCALE_SET_PRIORITY_REGULAR, CONST_SCALE_SET_PRIORITY_SPOT]
159161
node_eviction_policies = [CONST_SPOT_EVICTION_POLICY_DELETE, CONST_SPOT_EVICTION_POLICY_DEALLOCATE]
160162
node_os_disk_types = [CONST_OS_DISK_TYPE_MANAGED, CONST_OS_DISK_TYPE_EPHEMERAL]
161-
node_mode_types = [CONST_NODEPOOL_MODE_SYSTEM, CONST_NODEPOOL_MODE_USER]
163+
node_mode_types = [CONST_NODEPOOL_MODE_SYSTEM, CONST_NODEPOOL_MODE_USER, CONST_NODEPOOL_MODE_GATEWAY]
162164
node_os_skus_create = [CONST_OS_SKU_AZURELINUX, CONST_OS_SKU_UBUNTU, CONST_OS_SKU_CBLMARINER, CONST_OS_SKU_MARINER, CONST_OS_SKU_UBUNTU2204]
163165
node_os_skus = node_os_skus_create + [CONST_OS_SKU_WINDOWS2019, CONST_OS_SKU_WINDOWS2022]
164166
node_os_skus_update = [CONST_OS_SKU_AZURELINUX, CONST_OS_SKU_UBUNTU, CONST_OS_SKU_UBUNTU2204]
@@ -434,6 +436,7 @@ def load_arguments(self, _):
434436
arg_type=get_enum_type(app_routing_nginx_configs),
435437
options_list=["--app-routing-default-nginx-controller", "--ardnc"]
436438
)
439+
c.argument("enable_static_egress_gateway", action="store_true")
437440

438441
# nodepool paramerters
439442
c.argument('nodepool_name', default='nodepool1',
@@ -626,6 +629,9 @@ def load_arguments(self, _):
626629
c.argument('enable_secret_rotation', action='store_true')
627630
c.argument('disable_secret_rotation', action='store_true', validator=validate_keyvault_secrets_provider_disable_and_enable_parameters)
628631
c.argument('rotation_poll_interval')
632+
c.argument('enable_static_egress_gateway', action='store_true')
633+
c.argument('disable_static_egress_gateway', action='store_true')
634+
629635
# nodepool paramerters
630636
c.argument('enable_cluster_autoscaler', options_list=[
631637
"--enable-cluster-autoscaler", "-e"], action='store_true')
@@ -860,6 +866,7 @@ def load_arguments(self, _):
860866
c.argument("if_match")
861867
c.argument("if_none_match")
862868
c.argument('gpu_driver', arg_type=get_enum_type(gpu_driver_install_modes))
869+
c.argument("gateway_prefix_size", type=int, validator=validate_gateway_prefix_size)
863870

864871
with self.argument_context('aks nodepool update', resource_type=ResourceType.MGMT_CONTAINERSERVICE, operation_group='agent_pools') as c:
865872
c.argument('enable_cluster_autoscaler', options_list=[

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
CONST_OS_SKU_AZURELINUX,
1717
CONST_OS_SKU_CBLMARINER,
1818
CONST_OS_SKU_MARINER,
19+
CONST_NODEPOOL_MODE_GATEWAY,
1920
)
2021
from azure.cli.core import keys
2122
from azure.cli.core.azclierror import (
@@ -882,3 +883,12 @@ def validate_custom_ca_trust_certificates(namespace):
882883
if hasattr(namespace, 'os_type') and namespace.os_type != "Linux":
883884
raise ArgumentUsageError(
884885
'--custom-ca-trust-certificates can only be set for linux nodepools')
886+
887+
888+
def validate_gateway_prefix_size(namespace):
889+
"""Validates the gateway prefix size."""
890+
if namespace.gateway_prefix_size is not None:
891+
if not hasattr(namespace, 'mode') or namespace.mode != CONST_NODEPOOL_MODE_GATEWAY:
892+
raise ArgumentUsageError("--gateway-prefix-size can only be set for Gateway-mode nodepools")
893+
if namespace.gateway_prefix_size < 28 or namespace.gateway_prefix_size > 31:
894+
raise InvalidArgumentValueError("--gateway-prefix-size must be in the range [28, 31]")

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,6 +1619,13 @@ def get_gpu_driver(self) -> Union[str, None]:
16191619
"""
16201620
return self._get_gpu_driver()
16211621

1622+
def get_gateway_prefix_size(self) -> Union[int, None]:
1623+
"""Obtain the value of gateway_prefix_size.
1624+
1625+
:return: int or None
1626+
"""
1627+
return self.raw_param.get('gateway_prefix_size')
1628+
16221629

16231630
class AKSAgentPoolAddDecorator:
16241631
def __init__(
@@ -2007,6 +2014,22 @@ def set_up_gpu_profile(self, agentpool: AgentPool) -> AgentPool:
20072014

20082015
return agentpool
20092016

2017+
def set_up_agentpool_gateway_profile(self, agentpool: AgentPool) -> AgentPool:
2018+
"""Set up agentpool gateway profile for the AgentPool object.
2019+
2020+
:return: the AgentPool object
2021+
"""
2022+
self._ensure_agentpool(agentpool)
2023+
2024+
gateway_prefix_size = self.context.get_gateway_prefix_size()
2025+
if gateway_prefix_size is not None:
2026+
if agentpool.gateway_profile is None:
2027+
agentpool.gateway_profile = self.models.AgentPoolGatewayProfile() # pylint: disable=no-member
2028+
2029+
agentpool.gateway_profile.public_ip_prefix_size = gateway_prefix_size
2030+
2031+
return agentpool
2032+
20102033
def construct_agentpool_profile_default(self, bypass_restore_defaults: bool = False) -> AgentPool:
20112034
"""The overall controller used to construct the AgentPool profile by default.
20122035
@@ -2053,6 +2076,8 @@ def construct_agentpool_profile_default(self, bypass_restore_defaults: bool = Fa
20532076
agentpool = self.set_up_motd(agentpool)
20542077
# set up gpu profile
20552078
agentpool = self.set_up_gpu_profile(agentpool)
2079+
# set up agentpool gateway profile
2080+
agentpool = self.set_up_agentpool_gateway_profile(agentpool)
20562081
# restore defaults
20572082
if not bypass_restore_defaults:
20582083
agentpool = self._restore_defaults_in_agentpool(agentpool)

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ def aks_create(
602602
rotation_poll_interval=None,
603603
enable_app_routing=False,
604604
app_routing_default_nginx_controller=None,
605+
enable_static_egress_gateway=False,
605606
# nodepool paramerters
606607
nodepool_name="nodepool1",
607608
node_vm_size=None,
@@ -800,6 +801,8 @@ def aks_update(
800801
enable_secret_rotation=False,
801802
disable_secret_rotation=False,
802803
rotation_poll_interval=None,
804+
enable_static_egress_gateway=False,
805+
disable_static_egress_gateway=False,
803806
# nodepool paramerters
804807
enable_cluster_autoscaler=False,
805808
disable_cluster_autoscaler=False,
@@ -2440,6 +2443,8 @@ def aks_agentpool_add(
24402443
if_none_match=None,
24412444
# gpu driver
24422445
gpu_driver=None,
2446+
# static egress gateway - gateway-mode pool
2447+
gateway_prefix_size=None,
24432448
):
24442449
# DO NOT MOVE: get all the original parameters and save them as a dictionary
24452450
raw_parameters = locals()

src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ aks create:
8585
enable_apiserver_vnet_integration:
8686
rule_exclusions:
8787
- option_length_too_long
88-
88+
enable_static_egress_gateway:
89+
rule_exclusions:
90+
- option_length_too_long
8991
aks enable-addons:
9092
parameters:
9193
appgw_watch_namespace:
@@ -195,6 +197,12 @@ aks update:
195197
disable_private_cluster:
196198
rule_exclusions:
197199
- option_length_too_long
200+
enable_static_egress_gateway:
201+
rule_exclusions:
202+
- option_length_too_long
203+
disable_static_egress_gateway:
204+
rule_exclusions:
205+
- option_length_too_long
198206
aks nodepool add:
199207
parameters:
200208
disable_windows_outbound_nat:

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5469,6 +5469,37 @@ def get_bootstrap_container_registry_resource_id(self) -> Union[str, None]:
54695469
"""
54705470
return self.raw_param.get("bootstrap_container_registry_resource_id")
54715471

5472+
def _get_enable_static_egress_gateway(self, enable_validation: bool = False) -> bool:
5473+
"""Internal function to obtain the value of enable_static_egress_gateway.
5474+
When enabled, if both enable_static_egress_gateway and disable_static_egress_gateway are
5475+
specified, raise a MutuallyExclusiveArgumentError.
5476+
:return: bool
5477+
"""
5478+
enable_static_egress_gateway = self.raw_param.get("enable_static_egress_gateway")
5479+
# This parameter does not need dynamic completion.
5480+
if enable_validation:
5481+
if enable_static_egress_gateway and self.get_disable_static_egress_gateway():
5482+
raise MutuallyExclusiveArgumentError(
5483+
"Cannot specify --enable-static-egress-gateway and "
5484+
"--disable-static-egress-gateway at the same time. "
5485+
)
5486+
5487+
return enable_static_egress_gateway
5488+
5489+
def get_enable_static_egress_gateway(self) -> bool:
5490+
"""Obtain the value of enable_static_egress_gateway.
5491+
:return: bool
5492+
"""
5493+
return self._get_enable_static_egress_gateway(enable_validation=True)
5494+
5495+
def get_disable_static_egress_gateway(self) -> bool:
5496+
"""Obtain the value of disable_static_egress_gateway.
5497+
:return: bool
5498+
"""
5499+
# Note: No need to check for mutually exclusive parameter with enable-static-egress-gateway here
5500+
# because it's already checked in get_enable_static_egress_gateway
5501+
return self.raw_param.get("disable_static_egress_gateway")
5502+
54725503

54735504
class AKSManagedClusterCreateDecorator(BaseAKSManagedClusterDecorator):
54745505
def __init__(
@@ -6787,6 +6818,25 @@ def set_up_bootstrap_profile(self, mc: ManagedCluster) -> ManagedCluster:
67876818

67886819
return mc
67896820

6821+
def set_up_static_egress_gateway(self, mc: ManagedCluster) -> ManagedCluster:
6822+
self._ensure_mc(mc)
6823+
6824+
if self.context.get_enable_static_egress_gateway():
6825+
if not mc.network_profile:
6826+
raise UnknownError(
6827+
"Unexpectedly get an empty network profile in the process of "
6828+
"updating enable-static-egress-gateway config."
6829+
)
6830+
if mc.network_profile.static_egress_gateway_profile is None:
6831+
mc.network_profile.static_egress_gateway_profile = (
6832+
self.models.ManagedClusterStaticEgressGatewayProfile() # pylint: disable=no-member
6833+
)
6834+
# set enabled
6835+
mc.network_profile.static_egress_gateway_profile.enabled = True
6836+
6837+
# Default is disabled so no need to worry about that here
6838+
return mc
6839+
67906840
def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) -> ManagedCluster:
67916841
"""The overall controller used to construct the default ManagedCluster profile.
67926842
@@ -6871,6 +6921,8 @@ def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) ->
68716921
mc = self.set_up_node_resource_group_profile(mc)
68726922
# set up bootstrap profile
68736923
mc = self.set_up_bootstrap_profile(mc)
6924+
# set up static egress gateway profile
6925+
mc = self.set_up_static_egress_gateway(mc)
68746926

68756927
# DO NOT MOVE: keep this at the bottom, restore defaults
68766928
if not bypass_restore_defaults:
@@ -8700,6 +8752,35 @@ def update_bootstrap_profile(self, mc: ManagedCluster) -> ManagedCluster:
87008752

87018753
return mc
87028754

8755+
def update_static_egress_gateway(self, mc: ManagedCluster) -> ManagedCluster:
8756+
"""Update static egress gateway addon for the ManagedCluster object.
8757+
:return: the ManagedCluster object
8758+
"""
8759+
self._ensure_mc(mc)
8760+
8761+
if self.context.get_enable_static_egress_gateway():
8762+
if not mc.network_profile:
8763+
raise UnknownError(
8764+
"Unexpectedly get an empty network profile in the process of updating static-egress-gateway config."
8765+
)
8766+
if mc.network_profile.static_egress_gateway_profile is None:
8767+
mc.network_profile.static_egress_gateway_profile = (
8768+
self.models.ManagedClusterStaticEgressGatewayProfile() # pylint: disable=no-member
8769+
)
8770+
mc.network_profile.static_egress_gateway_profile.enabled = True
8771+
8772+
if self.context.get_disable_static_egress_gateway():
8773+
if not mc.network_profile:
8774+
raise UnknownError(
8775+
"Unexpectedly get an empty network profile in the process of updating static-egress-gateway config."
8776+
)
8777+
if mc.network_profile.static_egress_gateway_profile is None:
8778+
mc.network_profile.static_egress_gateway_profile = (
8779+
self.models.ManagedClusterStaticEgressGatewayProfile() # pylint: disable=no-member
8780+
)
8781+
mc.network_profile.static_egress_gateway_profile.enabled = False
8782+
return mc
8783+
87038784
def update_mc_profile_default(self) -> ManagedCluster:
87048785
"""The overall controller used to update the default ManagedCluster profile.
87058786
@@ -8783,6 +8864,8 @@ def update_mc_profile_default(self) -> ManagedCluster:
87838864
mc = self.update_node_resource_group_profile(mc)
87848865
# update bootstrap profile
87858866
mc = self.update_bootstrap_profile(mc)
8867+
# update static egress gateway
8868+
mc = self.update_static_egress_gateway(mc)
87868869
# update kubernetes version and orchestrator version
87878870
mc = self.update_kubernetes_version_and_orchestrator_version(mc)
87888871
return mc

0 commit comments

Comments
 (0)