Skip to content

Commit 5cb5fd1

Browse files
authored
[AKS] support premium tier and add supportPlan (#26795)
1 parent 5307e35 commit 5cb5fd1

File tree

125 files changed

+86408
-59287
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+86408
-59287
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
@@ -60,6 +60,7 @@
6060
# ManagedClusterSKU Tier
6161
CONST_MANAGED_CLUSTER_SKU_TIER_FREE = "free"
6262
CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD = "standard"
63+
CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM = "premium"
6364

6465
# outbound type
6566
CONST_OUTBOUND_TYPE_LOAD_BALANCER = "loadBalancer"

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,9 @@
427427
- name: --node-resource-group
428428
type: string
429429
short-summary: The node resource group is the resource group where all customer's resources will be created in, such as virtual machines.
430+
- name: --k8s-support-plan
431+
type: string
432+
short-summary: Choose from "KubernetesOfficial" or "AKSLongTermSupport", with "AKSLongTermSupport" you get 1 extra year of CVE patchs.
430433
- name: --enable-defender
431434
type: bool
432435
short-summary: Enable Microsoft Defender security profile.
@@ -726,6 +729,9 @@
726729
- name: --rotation-poll-interval
727730
type: string
728731
short-summary: Set interval of rotation poll. Use with azure-keyvault-secrets-provider addon.
732+
- name: --k8s-support-plan
733+
type: string
734+
short-summary: Choose from "KubernetesOfficial" or "AKSLongTermSupport", with "AKSLongTermSupport" you get 1 extra year of CVE patchs.
729735
- name: --enable-windows-gmsa
730736
type: bool
731737
short-summary: Enable Windows gmsa on cluster.

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@
1717
CONST_GPU_INSTANCE_PROFILE_MIG3_G, CONST_GPU_INSTANCE_PROFILE_MIG4_G,
1818
CONST_GPU_INSTANCE_PROFILE_MIG7_G, CONST_LOAD_BALANCER_SKU_BASIC,
1919
CONST_LOAD_BALANCER_SKU_STANDARD, CONST_MANAGED_CLUSTER_SKU_TIER_FREE,
20-
CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD, CONST_NETWORK_DATAPLANE_AZURE,
21-
CONST_NETWORK_DATAPLANE_CILIUM, CONST_NETWORK_PLUGIN_AZURE,
22-
CONST_NETWORK_PLUGIN_KUBENET, CONST_NETWORK_PLUGIN_MODE_OVERLAY,
23-
CONST_NETWORK_PLUGIN_NONE, CONST_NODE_IMAGE_UPGRADE_CHANNEL,
20+
CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD, CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM,
21+
CONST_NETWORK_DATAPLANE_AZURE, CONST_NETWORK_DATAPLANE_CILIUM,
22+
CONST_NETWORK_PLUGIN_AZURE, CONST_NETWORK_PLUGIN_KUBENET,
23+
CONST_NETWORK_PLUGIN_MODE_OVERLAY, CONST_NETWORK_PLUGIN_NONE,
24+
CONST_NODE_IMAGE_UPGRADE_CHANNEL, CONST_NONE_UPGRADE_CHANNEL,
2425
CONST_NODEPOOL_MODE_SYSTEM, CONST_NODEPOOL_MODE_USER,
25-
CONST_NONE_UPGRADE_CHANNEL, CONST_OS_DISK_TYPE_EPHEMERAL,
26-
CONST_OS_DISK_TYPE_MANAGED, CONST_OS_SKU_AZURELINUX,
27-
CONST_OS_SKU_CBLMARINER, CONST_OS_SKU_MARINER, CONST_OS_SKU_UBUNTU,
26+
CONST_OS_DISK_TYPE_EPHEMERAL, CONST_OS_DISK_TYPE_MANAGED,
27+
CONST_OS_SKU_AZURELINUX, CONST_OS_SKU_CBLMARINER, CONST_OS_SKU_MARINER, CONST_OS_SKU_UBUNTU,
2828
CONST_OS_SKU_WINDOWS2019, CONST_OS_SKU_WINDOWS2022,
2929
CONST_OUTBOUND_TYPE_LOAD_BALANCER, CONST_OUTBOUND_TYPE_MANAGED_NAT_GATEWAY,
3030
CONST_OUTBOUND_TYPE_USER_ASSIGNED_NAT_GATEWAY,
@@ -56,7 +56,7 @@
5656
validate_pod_subnet_id, validate_ppg, validate_priority,
5757
validate_registry_name, validate_sku_tier, validate_snapshot_id,
5858
validate_snapshot_name, validate_spot_max_price, validate_ssh_key,
59-
validate_taints, validate_vm_set_type, validate_vnet_subnet_id)
59+
validate_taints, validate_vm_set_type, validate_vnet_subnet_id, validate_k8s_support_plan)
6060
from azure.cli.core.commands.parameters import (
6161
edge_zone_type, file_type, get_enum_type,
6262
get_resource_name_completion_list, get_three_state_flag, name_type,
@@ -67,7 +67,6 @@
6767
# pylint: disable=line-too-long,too-many-statements
6868

6969
# candidates for enumeration, no longer maintained
70-
orchestrator_types = ["Custom", "DCOS", "Kubernetes", "Swarm", "DockerCE"]
7170
regions_in_preview = [
7271
"canadacentral",
7372
"canadaeast",
@@ -112,7 +111,7 @@
112111

113112
# consts for ManagedCluster
114113
load_balancer_skus = [CONST_LOAD_BALANCER_SKU_BASIC, CONST_LOAD_BALANCER_SKU_STANDARD]
115-
sku_tiers = [CONST_MANAGED_CLUSTER_SKU_TIER_FREE, CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD]
114+
sku_tiers = [CONST_MANAGED_CLUSTER_SKU_TIER_FREE, CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD, CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM]
116115
network_plugins = [CONST_NETWORK_PLUGIN_KUBENET, CONST_NETWORK_PLUGIN_AZURE, CONST_NETWORK_PLUGIN_NONE]
117116
network_plugin_modes = [CONST_NETWORK_PLUGIN_MODE_OVERLAY]
118117
network_dataplanes = [CONST_NETWORK_DATAPLANE_AZURE, CONST_NETWORK_DATAPLANE_CILIUM]
@@ -141,6 +140,7 @@
141140
def load_arguments(self, _):
142141

143142
acr_arg_type = CLIArgumentType(metavar='ACR_NAME_OR_RESOURCE_ID')
143+
k8s_support_plans = self.get_models("KubernetesSupportPlan", resource_type=ResourceType.MGMT_CONTAINERSERVICE, operation_group='managed_clusters')
144144

145145
# AKS command argument configuration
146146
with self.argument_context('aks', resource_type=ResourceType.MGMT_CONTAINERSERVICE, operation_group='managed_clusters') as c:
@@ -221,6 +221,7 @@ def load_arguments(self, _):
221221
c.argument('attach_acr', acr_arg_type)
222222
c.argument('skip_subnet_role_assignment', action='store_true')
223223
c.argument('node_resource_group')
224+
c.argument('k8s_support_plan', arg_type=get_enum_type(k8s_support_plans), validator=validate_k8s_support_plan)
224225
c.argument('enable_defender', action='store_true')
225226
c.argument('defender_config', validator=validate_defender_config_parameter)
226227
c.argument('disable_disk_driver', action='store_true')
@@ -251,6 +252,7 @@ def load_arguments(self, _):
251252
c.argument('enable_secret_rotation', action='store_true')
252253
c.argument('rotation_poll_interval')
253254
c.argument('enable_sgxquotehelper', action='store_true')
255+
254256
# nodepool paramerters
255257
c.argument('nodepool_name', default='nodepool1',
256258
help='Node pool name, up to 12 alphanumeric characters', validator=validate_nodepool_name)
@@ -321,6 +323,7 @@ def load_arguments(self, _):
321323
c.argument('aad_tenant_id')
322324
c.argument('aad_admin_group_object_ids')
323325
c.argument('enable_oidc_issuer', action='store_true')
326+
c.argument('k8s_support_plan', arg_type=get_enum_type(k8s_support_plans), validator=validate_k8s_support_plan)
324327
c.argument('windows_admin_password')
325328
c.argument('enable_ahub', action='store_true')
326329
c.argument('disable_ahub', action='store_true')

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
from ipaddress import ip_network
1111
from math import isclose, isnan
1212

13+
from azure.mgmt.containerservice.models import KubernetesSupportPlan
1314
from azure.cli.command_modules.acs._consts import (
1415
CONST_MANAGED_CLUSTER_SKU_TIER_FREE,
1516
CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD,
17+
CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM,
1618
CONST_OS_SKU_AZURELINUX,
1719
CONST_OS_SKU_CBLMARINER,
1820
CONST_OS_SKU_MARINER,
@@ -201,8 +203,19 @@ def validate_sku_tier(namespace):
201203
if namespace.tier is not None:
202204
if namespace.tier == '':
203205
return
204-
if namespace.tier.lower() not in (CONST_MANAGED_CLUSTER_SKU_TIER_FREE, CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD):
205-
raise InvalidArgumentValueError("--tier can only be free or standard")
206+
if namespace.tier.lower() not in (
207+
CONST_MANAGED_CLUSTER_SKU_TIER_FREE, CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD,
208+
CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM):
209+
raise InvalidArgumentValueError("--tier can only be free, standard and premium")
210+
211+
212+
def validate_k8s_support_plan(namespace):
213+
if namespace.k8s_support_plan is not None:
214+
if namespace.k8s_support_plan == '':
215+
return
216+
if namespace.k8s_support_plan.lower() not in (
217+
KubernetesSupportPlan.KUBERNETES_OFFICIAL.lower(), KubernetesSupportPlan.AKS_LONG_TERM_SUPPORT.lower()):
218+
raise InvalidArgumentValueError("--k8s-support-plan can only be KubernetesOfficial or AKSLongTermSupport")
206219

207220

208221
def validate_load_balancer_outbound_ips(namespace):

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
CONST_VIRTUAL_NODE_SUBNET_NAME,
6060
DecoratorEarlyExitException,
6161
)
62+
6263
from azure.cli.command_modules.acs._helpers import get_snapshot_by_snapshot_id
6364
from azure.cli.command_modules.acs._resourcegroup import get_rg_location
6465
from azure.cli.command_modules.acs._validators import extract_comma_separated_string
@@ -434,6 +435,7 @@ def aks_create(
434435
attach_acr=None,
435436
skip_subnet_role_assignment=False,
436437
node_resource_group=None,
438+
k8s_support_plan=None,
437439
enable_defender=False,
438440
defender_config=None,
439441
disable_disk_driver=False,
@@ -574,6 +576,7 @@ def aks_update(
574576
aad_tenant_id=None,
575577
aad_admin_group_object_ids=None,
576578
enable_oidc_issuer=False,
579+
k8s_support_plan=None,
577580
windows_admin_password=None,
578581
enable_ahub=False,
579582
disable_ahub=False,

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

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
from types import SimpleNamespace
1010
from typing import Dict, List, Optional, Tuple, TypeVar, Union
1111

12+
from azure.mgmt.containerservice.models import KubernetesSupportPlan
13+
1214
from azure.cli.command_modules.acs._consts import (
1315
CONST_LOAD_BALANCER_SKU_BASIC,
1416
CONST_LOAD_BALANCER_SKU_STANDARD,
1517
CONST_MANAGED_CLUSTER_SKU_TIER_FREE,
1618
CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD,
19+
CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM,
1720
CONST_OUTBOUND_TYPE_LOAD_BALANCER,
1821
CONST_OUTBOUND_TYPE_MANAGED_NAT_GATEWAY,
1922
CONST_OUTBOUND_TYPE_USER_ASSIGNED_NAT_GATEWAY,
@@ -4045,6 +4048,10 @@ def get_cluster_autoscaler_profile(self) -> Union[Dict[str, str], None]:
40454048
"""
40464049
return self._get_cluster_autoscaler_profile()
40474050

4051+
def _get_k8s_support_plan(self) -> KubernetesSupportPlan:
4052+
support_plan = self.raw_param.get("k8s_support_plan")
4053+
return support_plan
4054+
40484055
def _get_uptime_sla(self, enable_validation: bool = False) -> bool:
40494056
"""Internal function to obtain the value of uptime_sla.
40504057
@@ -4690,6 +4697,24 @@ def get_node_resource_group(self) -> Union[str, None]:
46904697
# this parameter does not need validation
46914698
return node_resource_group
46924699

4700+
def get_k8s_support_plan(self) -> Union[str, None]:
4701+
"""Obtain the value of kubernetes_support_plan.
4702+
4703+
:return: string or None
4704+
"""
4705+
# default to None
4706+
support_plan = None
4707+
# try to read the property value corresponding to the parameter from the `mc` object
4708+
if self.mc and hasattr(self.mc, "support_plan") and self.mc.support_plan is not None:
4709+
support_plan = self.mc.support_plan
4710+
4711+
# if specified by customer, use the specified value
4712+
support_plan = self.raw_param.get("k8s_support_plan")
4713+
4714+
# this parameter does not need dynamic completion
4715+
# this parameter does not need validation
4716+
return support_plan
4717+
46934718
def get_yes(self) -> bool:
46944719
"""Obtain the value of yes.
46954720
@@ -5811,6 +5836,12 @@ def set_up_sku(self, mc: ManagedCluster) -> ManagedCluster:
58115836
name="Base",
58125837
tier="Standard"
58135838
)
5839+
5840+
if self.context.get_tier() == CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM:
5841+
mc.sku = self.models.ManagedClusterSKU(
5842+
name="Base",
5843+
tier="Premium"
5844+
)
58145845
return mc
58155846

58165847
def set_up_extended_location(self, mc: ManagedCluster) -> ManagedCluster:
@@ -5838,6 +5869,20 @@ def set_up_node_resource_group(self, mc: ManagedCluster) -> ManagedCluster:
58385869
mc.node_resource_group = self.context.get_node_resource_group()
58395870
return mc
58405871

5872+
def set_up_k8s_support_plan(self, mc: ManagedCluster) -> ManagedCluster:
5873+
"""Set up supportPlan for the ManagedCluster object.
5874+
:return: the ManagedCluster object
5875+
"""
5876+
self._ensure_mc(mc)
5877+
5878+
support_plan = self.context.get_k8s_support_plan()
5879+
if support_plan == KubernetesSupportPlan.AKS_LONG_TERM_SUPPORT:
5880+
if mc is None or mc.sku is None or mc.sku.tier.lower() != CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM.lower():
5881+
raise AzCLIError("Long term support is only available for premium tier clusters.")
5882+
5883+
mc.support_plan = support_plan
5884+
return mc
5885+
58415886
def set_up_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster:
58425887
"""Set up azure monitor profile for the ManagedCluster object.
58435888
:return: the ManagedCluster object
@@ -5926,6 +5971,8 @@ def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) ->
59265971
mc = self.set_up_http_proxy_config(mc)
59275972
# set up workload autoscaler profile
59285973
mc = self.set_up_workload_auto_scaler_profile(mc)
5974+
# setup k8s support plan
5975+
mc = self.set_up_k8s_support_plan(mc)
59295976
# set up azure monitor metrics profile
59305977
mc = self.set_up_azure_monitor_profile(mc)
59315978

@@ -6341,6 +6388,13 @@ def update_sku(self, mc: ManagedCluster) -> ManagedCluster:
63416388
"""
63426389
self._ensure_mc(mc)
63436390

6391+
# Premium without LTS is ok (not vice versa)
6392+
if self.context.get_tier() == CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM:
6393+
mc.sku = self.models.ManagedClusterSKU(
6394+
name="Base",
6395+
tier="Premium"
6396+
)
6397+
63446398
if self.context.get_uptime_sla() or self.context.get_tier() == CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD:
63456399
mc.sku = self.models.ManagedClusterSKU(
63466400
name="Base",
@@ -6469,6 +6523,7 @@ def update_windows_profile(self, mc: ManagedCluster) -> ManagedCluster:
64696523
enable_windows_gmsa = self.context.get_enable_windows_gmsa()
64706524

64716525
if any([enable_ahub, disable_ahub, windows_admin_password, enable_windows_gmsa]) and not mc.windows_profile:
6526+
# seems we know the error
64726527
raise UnknownError(
64736528
"Encounter an unexpected error while getting windows profile from the cluster in the process of update."
64746529
)
@@ -6821,6 +6876,20 @@ def update_workload_identity_profile(self, mc: ManagedCluster) -> ManagedCluster
68216876

68226877
return mc
68236878

6879+
def update_k8s_support_plan(self, mc: ManagedCluster) -> ManagedCluster:
6880+
"""Update supportPlan for the ManagedCluster object.
6881+
:return: the ManagedCluster object
6882+
"""
6883+
self._ensure_mc(mc)
6884+
6885+
support_plan = self.context.get_k8s_support_plan()
6886+
if support_plan == KubernetesSupportPlan.AKS_LONG_TERM_SUPPORT:
6887+
if mc is None or mc.sku is None or mc.sku.tier.lower() != CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM.lower():
6888+
raise AzCLIError("Long term support is only available for premium tier clusters.")
6889+
6890+
mc.support_plan = support_plan
6891+
return mc
6892+
68246893
def update_azure_keyvault_kms(self, mc: ManagedCluster) -> ManagedCluster:
68256894
"""Update security profile azureKeyvaultKms for the ManagedCluster object.
68266895
@@ -7058,6 +7127,8 @@ def update_mc_profile_default(self) -> ManagedCluster:
70587127
mc = self.update_http_proxy_config(mc)
70597128
# update workload autoscaler profile
70607129
mc = self.update_workload_auto_scaler_profile(mc)
7130+
# update kubernetes support plan
7131+
mc = self.update_k8s_support_plan(mc)
70617132
# update azure monitor metrics profile
70627133
mc = self.update_azure_monitor_profile(mc)
70637134
return mc

0 commit comments

Comments
 (0)