Skip to content

Commit d4c2523

Browse files
authored
{AKS} Add support for KEDA workload auto-scaler (#4905)
1 parent 6dbf738 commit d4c2523

File tree

10 files changed

+2742
-5
lines changed

10 files changed

+2742
-5
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+
0.5.79
16+
++++++
17+
18+
* Add support for KEDA workload auto-scaler.
1519
* Fix `az aks addon list`, `az aks addon list-available` and `az aks addon show` commands when dealing with the web application routing addon.
1620
* Update to use 2022-05-02-preview api version.
1721

src/aks-preview/azext_aks_preview/_help.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@
447447
- name: --enable-custom-ca-trust
448448
type: bool
449449
short-summary: Enable Custom CA Trust on agent node pool.
450+
- name: --enable-keda
451+
type: bool
452+
short-summary: Enable KEDA workload auto-scaler.
450453
examples:
451454
- name: Create a Kubernetes cluster with an existing SSH public key.
452455
text: az aks create -g MyResourceGroup -n MyManagedCluster --ssh-key-value /path/to/publickey
@@ -761,6 +764,12 @@
761764
- name: --apiserver-subnet-id
762765
type: string
763766
short-summary: The ID of a subnet in an existing VNet into which to assign control plane apiserver pods(requires --enable-apiserver-vnet-integration)
767+
- name: --enable-keda
768+
type: bool
769+
short-summary: Enable KEDA workload auto-scaler.
770+
- name: --disable-keda
771+
type: bool
772+
short-summary: Disable KEDA workload auto-scaler.
764773
examples:
765774
- name: Reconcile the cluster back to its current state.
766775
text: az aks update -g MyResourceGroup -n MyManagedCluster

src/aks-preview/azext_aks_preview/_params.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ def load_arguments(self, _):
306306
c.argument('dns-zone-resource-id')
307307
# no validation for aks create because it already only supports Linux.
308308
c.argument('enable_custom_ca_trust', action='store_true')
309+
c.argument('enable_keda', action='store_true', is_preview=True)
309310

310311
with self.argument_context('aks update') as c:
311312
# managed cluster paramerters
@@ -380,6 +381,8 @@ def load_arguments(self, _):
380381
c.argument('azure_keyvault_kms_key_id', validator=validate_azure_keyvault_kms_key_id, is_preview=True)
381382
c.argument('enable_apiserver_vnet_integration', action='store_true', is_preview=True)
382383
c.argument('apiserver_subnet_id', validator=validate_apiserver_subnet_id, is_preview=True)
384+
c.argument('enable_keda', action='store_true', is_preview=True)
385+
c.argument('disable_keda', action='store_true', is_preview=True)
383386

384387
with self.argument_context('aks scale') as c:
385388
c.argument('nodepool_name',

src/aks-preview/azext_aks_preview/custom.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ def aks_create(cmd,
819819
apiserver_subnet_id=None,
820820
dns_zone_resource_id=None,
821821
enable_custom_ca_trust=False,
822+
enable_keda=False,
822823
yes=False):
823824
# DO NOT MOVE: get all the original parameters and save them as a dictionary
824825
raw_parameters = locals()
@@ -911,6 +912,8 @@ def aks_update(cmd, # pylint: disable=too-many-statements,too-many-branches,
911912
azure_keyvault_kms_key_id=None,
912913
enable_apiserver_vnet_integration=False,
913914
apiserver_subnet_id=None,
915+
enable_keda=False,
916+
disable_keda=False,
914917
):
915918
# DO NOT MOVE: get all the original parameters and save them as a dictionary
916919
raw_parameters = locals()

src/aks-preview/azext_aks_preview/decorator.py

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@
9999
AzureKeyVaultKms = TypeVar('AzureKeyVaultKms')
100100
ManagedClusterIngressProfile = TypeVar('ManagedClusterIngressProfile')
101101
ManagedClusterIngressProfileWebAppRouting = TypeVar('ManagedClusterIngressProfileWebAppRouting')
102+
ManagedClusterWorkloadAutoScalerProfile = TypeVar('ManagedClusterWorkloadAutoScalerProfile')
103+
ManagedClusterWorkloadAutoScalerProfileKeda = TypeVar('ManagedClusterWorkloadAutoScalerProfileKeda')
102104

103105

104106
# pylint: disable=too-many-instance-attributes,too-few-public-methods
@@ -186,6 +188,16 @@ def __init__(self, cmd: AzCommandsLoader, resource_type: ResourceType):
186188
resource_type=self.resource_type,
187189
operation_group="managed_clusters",
188190
)
191+
self.ManagedClusterWorkloadAutoScalerProfile = self.__cmd.get_models(
192+
"ManagedClusterWorkloadAutoScalerProfile",
193+
resource_type=self.resource_type,
194+
operation_group="managed_clusters",
195+
)
196+
self.ManagedClusterWorkloadAutoScalerProfileKeda = self.__cmd.get_models(
197+
"ManagedClusterWorkloadAutoScalerProfileKeda",
198+
resource_type=self.resource_type,
199+
operation_group="managed_clusters",
200+
)
189201
# holder for nat gateway related models
190202
self.__nat_gateway_models = None
191203
# holder for pod identity related models
@@ -2141,6 +2153,76 @@ def get_apiserver_subnet_id(self) -> Union[str, None]:
21412153
"""
21422154
return self._get_apiserver_subnet_id(enable_validation=True)
21432155

2156+
def _get_enable_keda(self, enable_validation: bool = False) -> bool:
2157+
"""Internal function to obtain the value of enable_keda.
2158+
2159+
This function supports the option of enable_validation. When enabled, if both enable_keda and disable_keda are
2160+
specified, raise a MutuallyExclusiveArgumentError.
2161+
2162+
:return: bool
2163+
"""
2164+
# Read the original value passed by the command.
2165+
enable_keda = self.raw_param.get("enable_keda")
2166+
2167+
# In create mode, try to read the property value corresponding to the parameter from the `mc` object.
2168+
if self.decorator_mode == DecoratorMode.CREATE:
2169+
if (
2170+
self.mc and
2171+
self.mc.workload_auto_scaler_profile and
2172+
self.mc.workload_auto_scaler_profile.keda
2173+
):
2174+
enable_keda = self.mc.workload_auto_scaler_profile.keda.enabled
2175+
2176+
# This parameter does not need dynamic completion.
2177+
if enable_validation:
2178+
if enable_keda and self._get_disable_keda(enable_validation=False):
2179+
raise MutuallyExclusiveArgumentError(
2180+
"Cannot specify --enable-keda and --disable-keda at the same time."
2181+
)
2182+
2183+
return enable_keda
2184+
2185+
def get_enable_keda(self) -> bool:
2186+
"""Obtain the value of enable_keda.
2187+
2188+
This function will verify the parameter by default. If both enable_keda and disable_keda are specified, raise a
2189+
MutuallyExclusiveArgumentError.
2190+
2191+
:return: bool
2192+
"""
2193+
return self._get_enable_keda(enable_validation=True)
2194+
2195+
def _get_disable_keda(self, enable_validation: bool = False) -> bool:
2196+
"""Internal function to obtain the value of disable_keda.
2197+
2198+
This function supports the option of enable_validation. When enabled, if both enable_keda and disable_keda are
2199+
specified, raise a MutuallyExclusiveArgumentError.
2200+
2201+
:return: bool
2202+
"""
2203+
# Read the original value passed by the command.
2204+
disable_keda = self.raw_param.get("disable_keda")
2205+
2206+
# This option is not supported in create mode, hence we do not read the property value from the `mc` object.
2207+
# This parameter does not need dynamic completion.
2208+
if enable_validation:
2209+
if disable_keda and self._get_enable_keda(enable_validation=False):
2210+
raise MutuallyExclusiveArgumentError(
2211+
"Cannot specify --enable-keda and --disable-keda at the same time."
2212+
)
2213+
2214+
return disable_keda
2215+
2216+
def get_disable_keda(self) -> bool:
2217+
"""Obtain the value of disable_keda.
2218+
2219+
This function will verify the parameter by default. If both enable_keda and disable_keda are specified, raise a
2220+
MutuallyExclusiveArgumentError.
2221+
2222+
:return: bool
2223+
"""
2224+
return self._get_disable_keda(enable_validation=True)
2225+
21442226

21452227
class AKSPreviewCreateDecorator(AKSCreateDecorator):
21462228
# pylint: disable=super-init-not-called
@@ -2558,6 +2640,21 @@ def set_up_api_server_access_profile(self, mc: ManagedCluster) -> ManagedCluster
25582640

25592641
return mc
25602642

2643+
def set_up_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedCluster:
2644+
"""Set up workload auto-scaler profile for the ManagedCluster object.
2645+
2646+
:return: the ManagedCluster object
2647+
"""
2648+
if not isinstance(mc, self.models.ManagedCluster):
2649+
raise CLIInternalError(f"Unexpected mc object with type '{type(mc)}'.")
2650+
2651+
if self.context.get_enable_keda():
2652+
if mc.workload_auto_scaler_profile is None:
2653+
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
2654+
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=True)
2655+
2656+
return mc
2657+
25612658
def construct_mc_preview_profile(self) -> ManagedCluster:
25622659
"""The overall controller used to construct the preview ManagedCluster profile.
25632660
@@ -2590,6 +2687,8 @@ def construct_mc_preview_profile(self) -> ManagedCluster:
25902687

25912688
mc = self.set_up_storage_profile(mc)
25922689

2690+
mc = self.set_up_workload_auto_scaler_profile(mc)
2691+
25932692
return mc
25942693

25952694
def create_mc_preview(self, mc: ManagedCluster) -> ManagedCluster:
@@ -2742,7 +2841,7 @@ def check_raw_parameters(self):
27422841
'"--disable-local-accounts" or '
27432842
'"--enable-public-fqdn" or '
27442843
'"--disable-public-fqdn"'
2745-
'"--enble-windows-gmsa" or '
2844+
'"--enable-windows-gmsa" or '
27462845
'"--nodepool-labels" or '
27472846
'"--enable-oidc-issuer" or '
27482847
'"--http-proxy-config" or '
@@ -2755,7 +2854,9 @@ def check_raw_parameters(self):
27552854
'"--disable-snapshot-controller" or '
27562855
'"--enable-azure-keyvault-kms" or '
27572856
'"--enable-workload-identity" or '
2758-
'"--disable-workload-identity".'
2857+
'"--disable-workload-identity" or '
2858+
'"--enable-keda" or '
2859+
'"--disable-keda".'
27592860
)
27602861

27612862
def update_load_balancer_profile(self, mc: ManagedCluster) -> ManagedCluster:
@@ -2980,6 +3081,25 @@ def update_api_server_access_profile(self, mc: ManagedCluster) -> ManagedCluster
29803081

29813082
return mc
29823083

3084+
def update_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedCluster:
3085+
"""Update workload auto-scaler profile for the ManagedCluster object.
3086+
3087+
:return: the ManagedCluster object
3088+
"""
3089+
self._ensure_mc(mc)
3090+
3091+
if self.context.get_enable_keda():
3092+
if mc.workload_auto_scaler_profile is None:
3093+
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
3094+
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=True)
3095+
3096+
if self.context.get_disable_keda():
3097+
if mc.workload_auto_scaler_profile is None:
3098+
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
3099+
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=False)
3100+
3101+
return mc
3102+
29833103
def patch_mc(self, mc: ManagedCluster) -> ManagedCluster:
29843104
"""Helper function to patch the ManagedCluster object.
29853105
@@ -3027,6 +3147,8 @@ def update_mc_preview_profile(self) -> ManagedCluster:
30273147

30283148
mc = self.update_storage_profile(mc)
30293149

3150+
mc = self.update_workload_auto_scaler_profile(mc)
3151+
30303152
return mc
30313153

30323154
def update_mc_preview(self, mc: ManagedCluster) -> ManagedCluster:

0 commit comments

Comments
 (0)