Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{AKS} Add support for KEDA workload auto-scaler #4905

Merged
merged 1 commit into from
Jun 3, 2022
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
+++++++

0.5.79
++++++

* Add support for KEDA workload auto-scaler.
* Fix `az aks addon list`, `az aks addon list-available` and `az aks addon show` commands when dealing with the web application routing addon.
* Update to use 2022-05-02-preview api version.

Expand Down
9 changes: 9 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@
- name: --enable-custom-ca-trust
type: bool
short-summary: Enable Custom CA Trust on agent node pool.
- name: --enable-keda
type: bool
short-summary: Enable KEDA workload auto-scaler.
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 @@ -761,6 +764,12 @@
- name: --apiserver-subnet-id
type: string
short-summary: The ID of a subnet in an existing VNet into which to assign control plane apiserver pods(requires --enable-apiserver-vnet-integration)
- name: --enable-keda
type: bool
short-summary: Enable KEDA workload auto-scaler.
- name: --disable-keda
type: bool
short-summary: Disable KEDA workload auto-scaler.
examples:
- name: Reconcile the cluster back to its current state.
text: az aks update -g MyResourceGroup -n MyManagedCluster
Expand Down
3 changes: 3 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ def load_arguments(self, _):
c.argument('dns-zone-resource-id')
# no validation for aks create because it already only supports Linux.
c.argument('enable_custom_ca_trust', action='store_true')
c.argument('enable_keda', action='store_true', is_preview=True)

with self.argument_context('aks update') as c:
# managed cluster paramerters
Expand Down Expand Up @@ -380,6 +381,8 @@ def load_arguments(self, _):
c.argument('azure_keyvault_kms_key_id', validator=validate_azure_keyvault_kms_key_id, is_preview=True)
c.argument('enable_apiserver_vnet_integration', action='store_true', is_preview=True)
c.argument('apiserver_subnet_id', validator=validate_apiserver_subnet_id, is_preview=True)
c.argument('enable_keda', action='store_true', is_preview=True)
c.argument('disable_keda', action='store_true', is_preview=True)

with self.argument_context('aks scale') as c:
c.argument('nodepool_name',
Expand Down
3 changes: 3 additions & 0 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ def aks_create(cmd,
apiserver_subnet_id=None,
dns_zone_resource_id=None,
enable_custom_ca_trust=False,
enable_keda=False,
yes=False):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down Expand Up @@ -911,6 +912,8 @@ def aks_update(cmd, # pylint: disable=too-many-statements,too-many-branches,
azure_keyvault_kms_key_id=None,
enable_apiserver_vnet_integration=False,
apiserver_subnet_id=None,
enable_keda=False,
disable_keda=False,
):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down
126 changes: 124 additions & 2 deletions src/aks-preview/azext_aks_preview/decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@
AzureKeyVaultKms = TypeVar('AzureKeyVaultKms')
ManagedClusterIngressProfile = TypeVar('ManagedClusterIngressProfile')
ManagedClusterIngressProfileWebAppRouting = TypeVar('ManagedClusterIngressProfileWebAppRouting')
ManagedClusterWorkloadAutoScalerProfile = TypeVar('ManagedClusterWorkloadAutoScalerProfile')
ManagedClusterWorkloadAutoScalerProfileKeda = TypeVar('ManagedClusterWorkloadAutoScalerProfileKeda')


# pylint: disable=too-many-instance-attributes,too-few-public-methods
Expand Down Expand Up @@ -186,6 +188,16 @@ def __init__(self, cmd: AzCommandsLoader, resource_type: ResourceType):
resource_type=self.resource_type,
operation_group="managed_clusters",
)
self.ManagedClusterWorkloadAutoScalerProfile = self.__cmd.get_models(
"ManagedClusterWorkloadAutoScalerProfile",
resource_type=self.resource_type,
operation_group="managed_clusters",
)
self.ManagedClusterWorkloadAutoScalerProfileKeda = self.__cmd.get_models(
"ManagedClusterWorkloadAutoScalerProfileKeda",
resource_type=self.resource_type,
operation_group="managed_clusters",
)
# holder for nat gateway related models
self.__nat_gateway_models = None
# holder for pod identity related models
Expand Down Expand Up @@ -2141,6 +2153,76 @@ def get_apiserver_subnet_id(self) -> Union[str, None]:
"""
return self._get_apiserver_subnet_id(enable_validation=True)

def _get_enable_keda(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of enable_keda.

This function supports the option of enable_validation. When enabled, if both enable_keda and disable_keda are
specified, raise a MutuallyExclusiveArgumentError.

:return: bool
"""
# Read the original value passed by the command.
enable_keda = self.raw_param.get("enable_keda")

# In create mode, try to read the property value corresponding to the parameter from the `mc` object.
if self.decorator_mode == DecoratorMode.CREATE:
if (
self.mc and
self.mc.workload_auto_scaler_profile and
self.mc.workload_auto_scaler_profile.keda
):
enable_keda = self.mc.workload_auto_scaler_profile.keda.enabled

# This parameter does not need dynamic completion.
if enable_validation:
if enable_keda and self._get_disable_keda(enable_validation=False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-keda and --disable-keda at the same time."
)

return enable_keda

def get_enable_keda(self) -> bool:
"""Obtain the value of enable_keda.

This function will verify the parameter by default. If both enable_keda and disable_keda are specified, raise a
MutuallyExclusiveArgumentError.

:return: bool
"""
return self._get_enable_keda(enable_validation=True)

def _get_disable_keda(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of disable_keda.

This function supports the option of enable_validation. When enabled, if both enable_keda and disable_keda are
specified, raise a MutuallyExclusiveArgumentError.

:return: bool
"""
# Read the original value passed by the command.
disable_keda = self.raw_param.get("disable_keda")

# This option is not supported in create mode, hence we do not read the property value from the `mc` object.
# This parameter does not need dynamic completion.
if enable_validation:
if disable_keda and self._get_enable_keda(enable_validation=False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-keda and --disable-keda at the same time."
)

return disable_keda

def get_disable_keda(self) -> bool:
"""Obtain the value of disable_keda.

This function will verify the parameter by default. If both enable_keda and disable_keda are specified, raise a
MutuallyExclusiveArgumentError.

:return: bool
"""
return self._get_disable_keda(enable_validation=True)


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

return mc

def set_up_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Set up workload auto-scaler profile for the ManagedCluster object.

:return: the ManagedCluster object
"""
if not isinstance(mc, self.models.ManagedCluster):
raise CLIInternalError(f"Unexpected mc object with type '{type(mc)}'.")

if self.context.get_enable_keda():
if mc.workload_auto_scaler_profile is None:
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=True)

return mc

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

Expand Down Expand Up @@ -2590,6 +2687,8 @@ def construct_mc_preview_profile(self) -> ManagedCluster:

mc = self.set_up_storage_profile(mc)

mc = self.set_up_workload_auto_scaler_profile(mc)

return mc

def create_mc_preview(self, mc: ManagedCluster) -> ManagedCluster:
Expand Down Expand Up @@ -2742,7 +2841,7 @@ def check_raw_parameters(self):
'"--disable-local-accounts" or '
'"--enable-public-fqdn" or '
'"--disable-public-fqdn"'
'"--enble-windows-gmsa" or '
'"--enable-windows-gmsa" or '
'"--nodepool-labels" or '
'"--enable-oidc-issuer" or '
'"--http-proxy-config" or '
Expand All @@ -2755,7 +2854,9 @@ def check_raw_parameters(self):
'"--disable-snapshot-controller" or '
'"--enable-azure-keyvault-kms" or '
'"--enable-workload-identity" or '
'"--disable-workload-identity".'
'"--disable-workload-identity" or '
'"--enable-keda" or '
'"--disable-keda".'
)

def update_load_balancer_profile(self, mc: ManagedCluster) -> ManagedCluster:
Expand Down Expand Up @@ -2980,6 +3081,25 @@ def update_api_server_access_profile(self, mc: ManagedCluster) -> ManagedCluster

return mc

def update_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""Update workload auto-scaler profile for the ManagedCluster object.

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

if self.context.get_enable_keda():
if mc.workload_auto_scaler_profile is None:
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=True)

if self.context.get_disable_keda():
if mc.workload_auto_scaler_profile is None:
mc.workload_auto_scaler_profile = self.models.ManagedClusterWorkloadAutoScalerProfile()
mc.workload_auto_scaler_profile.keda = self.models.ManagedClusterWorkloadAutoScalerProfileKeda(enabled=False)

return mc

def patch_mc(self, mc: ManagedCluster) -> ManagedCluster:
"""Helper function to patch the ManagedCluster object.

Expand Down Expand Up @@ -3027,6 +3147,8 @@ def update_mc_preview_profile(self) -> ManagedCluster:

mc = self.update_storage_profile(mc)

mc = self.update_workload_auto_scaler_profile(mc)

return mc

def update_mc_preview(self, mc: ManagedCluster) -> ManagedCluster:
Expand Down
Loading