Skip to content
Open
Show file tree
Hide file tree
Changes from 9 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
1 change: 1 addition & 0 deletions src/azure-cli/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Release History
* `az aks nodepool rollback`: Show an accurate warning when only the node OS upgrade channel is enabled (#33854)
* Implement enable/disable flags for user-defined scheduler configuration (#33934)
* `az aks update`: Fix Azure Container Storage configuration detection for lowercase and boolean extension settings (#33938)
* `az aks create`, `az aks update`: Add `--outbound-type-sku` to select the managed NAT gateway SKU (`Standard` or `StandardV2`) with `--outbound-type managedNATGateway`, the GA shape of NAT Gateway V2. `StandardV2` also supports IPv6 (`--nat-gateway-managed-outbound-ipv6-count`), user-provided public IPs (`--nat-gateway-outbound-ips`), and user-provided IP prefixes (`--nat-gateway-outbound-ip-prefixes`).
Comment thread
christine33-creator marked this conversation as resolved.
Outdated

**App Config**

Expand Down
4 changes: 4 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@
CONST_OUTBOUND_TYPE_USER_ASSIGNED_NAT_GATEWAY = "userAssignedNATGateway"
CONST_OUTBOUND_TYPE_NONE = "none"

# managed NAT gateway SKU
CONST_NAT_GATEWAY_SKU_STANDARD = "Standard"
CONST_NAT_GATEWAY_SKU_STANDARD_V2 = "StandardV2"

# load balancer backend pool type
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP = "nodeIP"
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP_CONFIGURATION = "nodeIPConfiguration"
Expand Down
8 changes: 8 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@
type: int
short-summary: NAT gateway idle timeout in minutes.
long-summary: Desired idle timeout for NAT gateway outbound flows, default is 4 minutes. Please specify a value in the range of [4, 120]. Valid for Standard SKU load balancer cluster with managedNATGateway outbound type only.
- name: --outbound-type-sku
type: string
short-summary: SKU of the managed NAT Gateway (Standard or StandardV2).
long-summary: Only valid with --outbound-type managedNATGateway. Omit to default to StandardV2 where the region supports it, otherwise Standard. StandardV2 adds zone resiliency, IPv6 support, and higher bandwidth.
Comment thread
christine33-creator marked this conversation as resolved.
- name: --outbound-type
type: string
short-summary: How outbound traffic will be configured for a cluster.
Expand Down Expand Up @@ -867,6 +871,10 @@
type: int
short-summary: NAT gateway idle timeout in minutes.
long-summary: Desired idle timeout for NAT gateway outbound flows, default is 4 minutes. Please specify a value in the range of [4, 120]. Valid for Standard SKU load balancer cluster with managedNATGateway outbound type only.
- name: --outbound-type-sku
type: string
short-summary: SKU of the managed NAT Gateway (Standard or StandardV2).
long-summary: Only valid with --outbound-type managedNATGateway. Migrate an existing Standard (V1) cluster to StandardV2 by passing StandardV2. StandardV2 adds zone resiliency, IPv6 support, and higher bandwidth. Downgrade from StandardV2 to Standard is not supported.
- name: --outbound-type
type: string
short-summary: How outbound traffic will be configured for a cluster.
Expand Down
106 changes: 93 additions & 13 deletions src/azure-cli/azure/cli/command_modules/acs/_natgateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,117 @@
from types import SimpleNamespace


def create_nat_gateway_profile(managed_outbound_ip_count, idle_timeout, models: SimpleNamespace):
def create_nat_gateway_profile(
managed_outbound_ip_count,
idle_timeout,
models: SimpleNamespace,
managed_outbound_ipv6_count=None,
outbound_ip_ids=None,
outbound_ip_prefix_ids=None,
nat_gateway_sku=None,
):
"""parse and build NAT gateway profile"""
if not is_nat_gateway_profile_provided(managed_outbound_ip_count, idle_timeout):
if not is_nat_gateway_profile_provided(
managed_outbound_ip_count, idle_timeout,
managed_outbound_ipv6_count, outbound_ip_ids, outbound_ip_prefix_ids,
nat_gateway_sku,
):
return None

profile = models.ManagedClusterNATGatewayProfile()
return configure_nat_gateway_profile(managed_outbound_ip_count, idle_timeout, profile, models)
return configure_nat_gateway_profile(
managed_outbound_ip_count, idle_timeout, profile, models,
managed_outbound_ipv6_count, outbound_ip_ids, outbound_ip_prefix_ids,
nat_gateway_sku,
)


def update_nat_gateway_profile(managed_outbound_ip_count, idle_timeout, profile, models: SimpleNamespace):
def update_nat_gateway_profile(
managed_outbound_ip_count,
idle_timeout,
profile,
models: SimpleNamespace,
managed_outbound_ipv6_count=None,
outbound_ip_ids=None,
outbound_ip_prefix_ids=None,
nat_gateway_sku=None,
):
"""parse and update an existing NAT gateway profile"""
if not is_nat_gateway_profile_provided(managed_outbound_ip_count, idle_timeout):
if not is_nat_gateway_profile_provided(
managed_outbound_ip_count, idle_timeout,
managed_outbound_ipv6_count, outbound_ip_ids, outbound_ip_prefix_ids,
nat_gateway_sku,
):
return profile
if not profile:
profile = models.ManagedClusterNATGatewayProfile()
return configure_nat_gateway_profile(managed_outbound_ip_count, idle_timeout, profile, models)
return configure_nat_gateway_profile(
managed_outbound_ip_count, idle_timeout, profile, models,
managed_outbound_ipv6_count, outbound_ip_ids, outbound_ip_prefix_ids,
nat_gateway_sku,
)


def is_nat_gateway_profile_provided(managed_outbound_ip_count, idle_timeout):
return any([managed_outbound_ip_count is not None, idle_timeout])
def is_nat_gateway_profile_provided(
managed_outbound_ip_count,
idle_timeout,
managed_outbound_ipv6_count=None,
outbound_ip_ids=None,
outbound_ip_prefix_ids=None,
nat_gateway_sku=None,
):
return any([
managed_outbound_ip_count is not None,
idle_timeout,
managed_outbound_ipv6_count is not None,
outbound_ip_ids is not None,
outbound_ip_prefix_ids is not None,
nat_gateway_sku is not None,
])


def configure_nat_gateway_profile(managed_outbound_ip_count, idle_timeout, profile, models: SimpleNamespace):
def configure_nat_gateway_profile(
managed_outbound_ip_count,
idle_timeout,
profile,
models: SimpleNamespace,
managed_outbound_ipv6_count=None,
outbound_ip_ids=None,
outbound_ip_prefix_ids=None,
nat_gateway_sku=None,
):
"""configure a NAT Gateway with customer supplied values"""
if managed_outbound_ip_count is not None:
if managed_outbound_ip_count is not None or managed_outbound_ipv6_count is not None:
ManagedClusterManagedOutboundIPProfile = models.ManagedClusterManagedOutboundIPProfile
profile.managed_outbound_ip_profile = ManagedClusterManagedOutboundIPProfile(
count=managed_outbound_ip_count
)
if not profile.managed_outbound_ip_profile:
profile.managed_outbound_ip_profile = ManagedClusterManagedOutboundIPProfile()
if managed_outbound_ip_count is not None:
profile.managed_outbound_ip_profile.count = managed_outbound_ip_count
elif profile.managed_outbound_ip_profile.count is None:
# SDK 41.6 no longer materializes the IPv4 default; keep the documented default of 1.
profile.managed_outbound_ip_profile.count = 1
if managed_outbound_ipv6_count is not None:
profile.managed_outbound_ip_profile.count_ipv6 = managed_outbound_ipv6_count

if idle_timeout:
profile.idle_timeout_in_minutes = idle_timeout

if outbound_ip_ids is not None:
ManagedClusterNATGatewayProfileOutboundIPs = models.ManagedClusterNATGatewayProfileOutboundIPs
if ManagedClusterNATGatewayProfileOutboundIPs is None:
raise ValueError("The selected AKS API profile/SDK does not support setting NAT gateway outbound IPs.")
ip_id_list = [x.strip() for x in outbound_ip_ids.split(',') if x.strip()]
profile.outbound_i_ps = ManagedClusterNATGatewayProfileOutboundIPs(public_i_ps=ip_id_list)

if outbound_ip_prefix_ids is not None:
ManagedClusterNATGatewayProfileOutboundIpPrefixes = models.ManagedClusterNATGatewayProfileOutboundIpPrefixes
prefix_id_list = [x.strip() for x in outbound_ip_prefix_ids.split(',') if x.strip()]
profile.outbound_ip_prefixes = ManagedClusterNATGatewayProfileOutboundIpPrefixes(
public_ip_prefixes=prefix_id_list
)

if nat_gateway_sku is not None:
# GA shape: V2 is expressed as outboundType=managedNATGateway + natGatewayProfile.sku.
profile.sku = nat_gateway_sku

return profile
38 changes: 35 additions & 3 deletions src/azure-cli/azure/cli/command_modules/acs/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
CONST_OS_SKU_CBLMARINER, CONST_OS_SKU_MARINER,
CONST_OS_SKU_UBUNTU, CONST_OS_SKU_UBUNTU2204, CONST_OS_SKU_UBUNTU2404,
CONST_OS_SKU_WINDOWS2019, CONST_OS_SKU_WINDOWS2022, CONST_OS_SKU_WINDOWS2025,
CONST_NAT_GATEWAY_SKU_STANDARD, CONST_NAT_GATEWAY_SKU_STANDARD_V2,
CONST_OUTBOUND_TYPE_LOAD_BALANCER, CONST_OUTBOUND_TYPE_MANAGED_NAT_GATEWAY,
CONST_OUTBOUND_TYPE_USER_ASSIGNED_NAT_GATEWAY,
CONST_OUTBOUND_TYPE_USER_DEFINED_ROUTING, CONST_OUTBOUND_TYPE_NONE,
Expand Down Expand Up @@ -119,7 +120,11 @@
validate_load_balancer_outbound_ips, validate_load_balancer_outbound_ports,
validate_load_balancer_sku, validate_max_surge, validate_max_unavailable,
validate_nat_gateway_idle_timeout,
validate_nat_gateway_managed_outbound_ip_count, validate_network_policy,
validate_nat_gateway_managed_outbound_ip_count,
validate_nat_gateway_managed_outbound_ipv6_count,
validate_nat_gateway_v2_params, validate_nat_gateway_v2_params_for_update,
validate_network_policy,
validate_outbound_type_sku, validate_outbound_type_sku_for_update,
validate_nodepool_id, validate_nodepool_labels, validate_nodepool_name,
validate_nodepool_tags, validate_nodes_count, validate_os_sku,
validate_pod_subnet_id, validate_ppg, validate_priority,
Expand Down Expand Up @@ -197,6 +202,7 @@

# consts for ManagedCluster
load_balancer_skus = [CONST_LOAD_BALANCER_SKU_BASIC, CONST_LOAD_BALANCER_SKU_STANDARD]
nat_gateway_skus = [CONST_NAT_GATEWAY_SKU_STANDARD, CONST_NAT_GATEWAY_SKU_STANDARD_V2]
sku_names = [CONST_MANAGED_CLUSTER_SKU_NAME_BASE, CONST_MANAGED_CLUSTER_SKU_NAME_AUTOMATIC]
sku_tiers = [CONST_MANAGED_CLUSTER_SKU_TIER_FREE, CONST_MANAGED_CLUSTER_SKU_TIER_STANDARD, CONST_MANAGED_CLUSTER_SKU_TIER_PREMIUM]
network_plugins = [CONST_NETWORK_PLUGIN_KUBENET, CONST_NETWORK_PLUGIN_AZURE, CONST_NETWORK_PLUGIN_NONE]
Expand Down Expand Up @@ -428,8 +434,21 @@ def load_arguments(self, _):
c.argument('load_balancer_backend_pool_type', arg_type=get_enum_type(backend_pool_types))
c.argument('nrg_lockdown_restriction_level', arg_type=get_enum_type(nrg_lockdown_restriction_levels))
c.argument('nat_gateway_managed_outbound_ip_count', type=int, validator=validate_nat_gateway_managed_outbound_ip_count)
c.argument('nat_gateway_managed_outbound_ipv6_count',
options_list=['--nat-gateway-managed-outbound-ipv6-count', '--nat-gw-ipv6-count'],
type=int, validator=validate_nat_gateway_managed_outbound_ipv6_count,
help='NAT gateway managed outbound IPv6 count. Only valid with --outbound-type '
'managedNATGateway and --outbound-type-sku StandardV2.')
c.argument('nat_gateway_idle_timeout', type=int, validator=validate_nat_gateway_idle_timeout)
c.argument('outbound_type', arg_type=get_enum_type(outbound_types))
c.argument('nat_gateway_sku', options_list=['--outbound-type-sku'], arg_type=get_enum_type(nat_gateway_skus), validator=validate_outbound_type_sku)
c.argument('nat_gateway_outbound_ip_ids', options_list=['--nat-gateway-outbound-ips', '--nat-gw-ips'],
help='Comma-separated public IP resource IDs for the cluster NAT gateway. '
'Only valid with --outbound-type-sku StandardV2.')
c.argument('nat_gateway_outbound_ip_prefix_ids',
options_list=['--nat-gateway-outbound-ip-prefixes', '--nat-gw-prefixes'],
help='Comma-separated public IP prefix resource IDs for the cluster NAT gateway. '
'Only valid with --outbound-type-sku StandardV2.')
c.argument('outbound_type', arg_type=get_enum_type(outbound_types), validator=validate_nat_gateway_v2_params)
c.argument('network_plugin', arg_type=get_enum_type(network_plugins))
c.argument('network_plugin_mode', arg_type=get_enum_type(network_plugin_modes))
c.argument('network_policy', validator=validate_network_policy)
Expand Down Expand Up @@ -695,11 +714,24 @@ def load_arguments(self, _):
c.argument("load_balancer_sku", arg_type=get_enum_type([CONST_LOAD_BALANCER_SKU_STANDARD]), validator=validate_load_balancer_sku)
c.argument('nrg_lockdown_restriction_level', arg_type=get_enum_type(nrg_lockdown_restriction_levels))
c.argument('nat_gateway_managed_outbound_ip_count', type=int, validator=validate_nat_gateway_managed_outbound_ip_count)
c.argument('nat_gateway_managed_outbound_ipv6_count',
options_list=['--nat-gateway-managed-outbound-ipv6-count', '--nat-gw-ipv6-count'],
type=int, validator=validate_nat_gateway_managed_outbound_ipv6_count,
help='NAT gateway managed outbound IPv6 count. Only valid with --outbound-type '
'managedNATGateway and --outbound-type-sku StandardV2.')
c.argument('nat_gateway_idle_timeout', type=int, validator=validate_nat_gateway_idle_timeout)
c.argument('nat_gateway_sku', options_list=['--outbound-type-sku'], arg_type=get_enum_type(nat_gateway_skus), validator=validate_outbound_type_sku_for_update)
c.argument('nat_gateway_outbound_ip_ids', options_list=['--nat-gateway-outbound-ips', '--nat-gw-ips'],
help='Comma-separated public IP resource IDs for the cluster NAT gateway. '
'Only valid with --outbound-type-sku StandardV2.')
c.argument('nat_gateway_outbound_ip_prefix_ids',
options_list=['--nat-gateway-outbound-ip-prefixes', '--nat-gw-prefixes'],
help='Comma-separated public IP prefix resource IDs for the cluster NAT gateway. '
'Only valid with --outbound-type-sku StandardV2.')
c.argument('network_dataplane', arg_type=get_enum_type(network_dataplanes))
c.argument('network_plugin', arg_type=get_enum_type(network_plugins))
c.argument('network_policy', arg_type=get_enum_type(network_policies))
c.argument('outbound_type', arg_type=get_enum_type(outbound_types))
c.argument('outbound_type', arg_type=get_enum_type(outbound_types), validator=validate_nat_gateway_v2_params_for_update)
c.argument('auto_upgrade_channel', arg_type=get_enum_type(auto_upgrade_channels))
c.argument('cluster_autoscaler_profile', nargs='+', options_list=["--cluster-autoscaler-profile", "--ca-profile"],
help="Comma-separated list of key=value pairs for configuring cluster autoscaler. Pass an empty string to clear the profile.")
Expand Down
Loading
Loading