Skip to content

Commit

Permalink
[AKS] az aks: Support IP-based Load Balancer and Instance Level Pub…
Browse files Browse the repository at this point in the history
…lic IP Tags (#27910)

* feat: support `az aks create --load-balancer-backend-pool-type`, `az aks update --load-balancer-backend-pool-type`, `az aks create --node-public-ip-tags` and `az aks nodepool add --node-public-ip-tags`.

* chore: set arg type to enum for backend_pool_type

* chore: remove backend pool type validator

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

Co-authored-by: Xing Zhou <Zhou.Xing@microsoft.com>

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

Co-authored-by: Xing Zhou <Zhou.Xing@microsoft.com>

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

Co-authored-by: Xing Zhou <Zhou.Xing@microsoft.com>

---------

Co-authored-by: Xing Zhou <Zhou.Xing@microsoft.com>
  • Loading branch information
nilo19 and zhoxing-ms authored Dec 11, 2023
1 parent d6f0079 commit e45f1a0
Show file tree
Hide file tree
Showing 14 changed files with 1,384 additions and 13 deletions.
12 changes: 12 additions & 0 deletions linter_exclusions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,12 @@ aks create:
load_balancer_outbound_ports:
rule_exclusions:
- option_length_too_long
load_balancer_backend_pool_type:
rule_exclusions:
- option_length_too_long
node_public_ip_tags:
rule_exclusions:
- option_length_too_long
skip_subnet_role_assignment:
rule_exclusions:
- option_length_too_long
Expand Down Expand Up @@ -407,6 +413,12 @@ aks update:
load_balancer_outbound_ports:
rule_exclusions:
- option_length_too_long
load_balancer_backend_pool_type:
rule_exclusions:
- option_length_too_long
node_public_ip_tags:
rule_exclusions:
- option_length_too_long
enable_managed_identity:
rule_exclusions:
- option_length_too_long
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 @@ -68,6 +68,10 @@
CONST_OUTBOUND_TYPE_MANAGED_NAT_GATEWAY = "managedNATGateway"
CONST_OUTBOUND_TYPE_USER_ASSIGNED_NAT_GATEWAY = "userAssignedNATGateway"

# load balancer backend pool type
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP = "nodeIP"
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP_CONFIGURATION = "nodeIPConfiguration"

# private dns zone mode
CONST_PRIVATE_DNS_ZONE_SYSTEM = "system"
CONST_PRIVATE_DNS_ZONE_NONE = "none"
Expand Down
14 changes: 14 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 @@ -180,6 +180,10 @@
type: int
short-summary: Load balancer idle timeout in minutes.
long-summary: Desired idle timeout for load balancer outbound flows, default is 30 minutes. Please specify a value in the range of [4, 100].
- name: --load-balancer-backend-pool-type
type: string
short-summary: Load balancer backend pool type.
long-summary: Define the LoadBalancer backend pool type of managed inbound backend pool. The nodeIP means the VMs will be attached to the LoadBalancer by adding its private IP address to the backend pool. The nodeIPConfiguration means the VMs will be attached to the LoadBalancer by referencing the backend pool ID in the VM's NIC.
- name: --nat-gateway-managed-outbound-ip-count
type: int
short-summary: NAT gateway managed outbound IP count.
Expand Down Expand Up @@ -518,6 +522,9 @@
- name: --nodepool-asg-ids
type: string
short-summary: The IDs of the application security groups to which the node pool's network interface should belong. When specified, format should be a space-separated list of IDs.
- name: --node-public-ip-tags
type: string
short-summary: The ipTags of the node public IPs.
examples:
- name: Create a Kubernetes cluster with an existing SSH public key.
Expand Down Expand Up @@ -664,6 +671,10 @@
type: int
short-summary: Load balancer idle timeout in minutes.
long-summary: Desired idle timeout for load balancer outbound flows, default is 30 minutes. Please specify a value in the range of [4, 100].
- name: --load-balancer-backend-pool-type
type: string
short-summary: Load balancer backend pool type.
long-summary: Define the LoadBalancer backend pool type of managed inbound backend pool. The nodeIP means the VMs will be attached to the LoadBalancer by adding its private IP address to the backend pool. The nodeIPConfiguration means the VMs will be attached to the LoadBalancer by referencing the backend pool ID in the VM's NIC.
- name: --nat-gateway-managed-outbound-ip-count
type: int
short-summary: NAT gateway managed outbound IP count.
Expand Down Expand Up @@ -1528,6 +1539,9 @@
- name: --asg-ids
type: string
short-summary: The IDs of the application security groups to which the node pool's network interface should belong. When specified, format should be a space-separated list of IDs.
- name: --node-public-ip-tags
type: string
short-summary: The ipTags of the node public IPs.
examples:
- name: Create a nodepool in an existing AKS cluster with ephemeral os enabled.
text: az aks nodepool add -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --node-osdisk-type Ephemeral --node-osdisk-size 48
Expand Down
25 changes: 16 additions & 9 deletions src/azure-cli/azure/cli/command_modules/acs/_loadbalancer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ def set_load_balancer_sku(sku, kubernetes_version):


def update_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout, profile, models):
outbound_ip_prefixes, outbound_ports,
idle_timeout, backend_pool_type, profile, models):
"""parse and update an existing load balancer profile"""
if not is_load_balancer_profile_provided(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout):
outbound_ip_prefixes, outbound_ports, backend_pool_type, idle_timeout):
return profile
if not profile:
if isinstance(models, SimpleNamespace):
Expand All @@ -34,14 +35,15 @@ def update_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv
ManagedClusterLoadBalancerProfile = models.get("ManagedClusterLoadBalancerProfile")
profile = ManagedClusterLoadBalancerProfile()
return configure_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout, profile, models)
outbound_ip_prefixes, outbound_ports, idle_timeout,
backend_pool_type, profile, models)


def create_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout, models):
outbound_ip_prefixes, outbound_ports, idle_timeout, backend_pool_type, models):
"""parse and build load balancer profile"""
if not is_load_balancer_profile_provided(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout):
outbound_ip_prefixes, outbound_ports, backend_pool_type, idle_timeout):
return None

if isinstance(models, SimpleNamespace):
Expand All @@ -50,11 +52,13 @@ def create_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv
ManagedClusterLoadBalancerProfile = models.get("ManagedClusterLoadBalancerProfile")
profile = ManagedClusterLoadBalancerProfile()
return configure_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout, profile, models)
outbound_ip_prefixes, outbound_ports, idle_timeout,
backend_pool_type, profile, models)


def configure_load_balancer_profile(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips,
outbound_ip_prefixes, outbound_ports, idle_timeout, profile, models):
outbound_ip_prefixes, outbound_ports, idle_timeout,
backend_pool_type, profile, models):
"""configure a load balancer with customer supplied values"""
if any([managed_outbound_ip_count,
managed_outbound_ipv6_count,
Expand Down Expand Up @@ -110,17 +114,20 @@ def configure_load_balancer_profile(managed_outbound_ip_count, managed_outbound_
profile.allocated_outbound_ports = outbound_ports
if idle_timeout:
profile.idle_timeout_in_minutes = idle_timeout
if backend_pool_type:
profile.backend_pool_type = backend_pool_type
return profile


def is_load_balancer_profile_provided(managed_outbound_ip_count, managed_outbound_ipv6_count, outbound_ips, ip_prefixes,
outbound_ports, idle_timeout):
outbound_ports, backend_pool_type, idle_timeout):
return any([managed_outbound_ip_count,
managed_outbound_ipv6_count,
outbound_ips,
ip_prefixes,
outbound_ports,
idle_timeout])
idle_timeout,
backend_pool_type])


def _get_load_balancer_outbound_ips(load_balancer_outbound_ips, models):
Expand Down
18 changes: 16 additions & 2 deletions src/azure-cli/azure/cli/command_modules/acs/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
CONST_ABSOLUTEMONTHLY_MAINTENANCE_SCHEDULE, CONST_RELATIVEMONTHLY_MAINTENANCE_SCHEDULE,
CONST_WEEKINDEX_FIRST, CONST_WEEKINDEX_SECOND,
CONST_WEEKINDEX_THIRD, CONST_WEEKINDEX_FOURTH,
CONST_WEEKINDEX_LAST)
CONST_WEEKINDEX_LAST,
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP,
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP_CONFIGURATION)
from azure.cli.command_modules.acs._validators import (
validate_acr, validate_agent_pool_name, validate_assign_identity,
validate_assign_kubelet_identity, validate_azure_keyvault_kms_key_id,
Expand All @@ -68,7 +70,8 @@
validate_nodepool_taints, validate_vm_set_type, validate_vnet_subnet_id, validate_k8s_support_plan,
validate_utc_offset, validate_start_date, validate_start_time,
validate_force_upgrade_disable_and_enable_parameters,
validate_allowed_host_ports, validate_application_security_groups)
validate_allowed_host_ports, validate_application_security_groups,
validate_node_public_ip_tags)
from azure.cli.core.commands.parameters import (
edge_zone_type, file_type, get_enum_type,
get_resource_name_completion_list, get_three_state_flag, name_type,
Expand Down Expand Up @@ -171,6 +174,11 @@
CONST_WEEKINDEX_LAST,
]

backend_pool_types = [
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP,
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP_CONFIGURATION,
]


def load_arguments(self, _):

Expand Down Expand Up @@ -217,6 +225,7 @@ def load_arguments(self, _):
c.argument('load_balancer_outbound_ip_prefixes', validator=validate_load_balancer_outbound_ip_prefixes)
c.argument('load_balancer_outbound_ports', type=int, validator=validate_load_balancer_outbound_ports)
c.argument('load_balancer_idle_timeout', type=int, validator=validate_load_balancer_idle_timeout)
c.argument('load_balancer_backend_pool_type', arg_type=get_enum_type(backend_pool_types))
c.argument('nat_gateway_managed_outbound_ip_count', type=int, validator=validate_nat_gateway_managed_outbound_ip_count)
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))
Expand Down Expand Up @@ -330,6 +339,8 @@ def load_arguments(self, _):
c.argument('ksm_metric_annotations_allow_list')
c.argument('grafana_resource_id', validator=validate_grafanaresourceid)
c.argument('enable_windows_recording_rules', action='store_true')
c.argument('node_public_ip_tags', arg_type=tags_type, validator=validate_node_public_ip_tags,
help='space-separated tags: key[=value] [key[=value] ...].')
# misc
c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true')

Expand All @@ -343,6 +354,7 @@ def load_arguments(self, _):
c.argument('load_balancer_outbound_ip_prefixes', validator=validate_load_balancer_outbound_ip_prefixes)
c.argument('load_balancer_outbound_ports', type=int, validator=validate_load_balancer_outbound_ports)
c.argument('load_balancer_idle_timeout', type=int, validator=validate_load_balancer_idle_timeout)
c.argument('load_balancer_backend_pool_type', arg_type=get_enum_type(backend_pool_types))
c.argument('nat_gateway_managed_outbound_ip_count', type=int, validator=validate_nat_gateway_managed_outbound_ip_count)
c.argument('nat_gateway_idle_timeout', type=int, validator=validate_nat_gateway_idle_timeout)
c.argument('network_dataplane', arg_type=get_enum_type(network_dataplanes))
Expand Down Expand Up @@ -572,6 +584,8 @@ def load_arguments(self, _):
c.argument('gpu_instance_profile', arg_type=get_enum_type(gpu_instance_profiles))
c.argument('allowed_host_ports', nargs='+', validator=validate_allowed_host_ports)
c.argument('asg_ids', nargs='+', validator=validate_application_security_groups)
c.argument('node_public_ip_tags', arg_type=tags_type, validator=validate_node_public_ip_tags,
help='space-separated tags: key[=value] [key[=value] ...].')

with self.argument_context('aks nodepool update', resource_type=ResourceType.MGMT_CONTAINERSERVICE, operation_group='agent_pools') as c:
c.argument('enable_cluster_autoscaler', options_list=[
Expand Down
8 changes: 8 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,14 @@ def validate_ppg(namespace):
raise CLIError("--ppg is not a valid Azure resource ID.")


def validate_node_public_ip_tags(ns):
if isinstance(ns.node_public_ip_tags, list):
tags_dict = {}
for item in ns.node_public_ip_tags:
tags_dict.update(validate_tag(item))
ns.node_public_ip_tags = tags_dict


def validate_nodepool_labels(namespace):
"""Validates that provided node labels is a valid format"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
Snapshot = TypeVar("Snapshot")
KubeletConfig = TypeVar("KubeletConfig")
LinuxOSConfig = TypeVar("LinuxOSConfig")
IPTag = TypeVar("IPTag")

# TODO:
# 1. Add extra type checking for getter functions
Expand Down Expand Up @@ -1294,6 +1295,17 @@ def get_allowed_host_ports(self) -> Union[List[PortRange], None]:
))
return port_ranges

def get_ip_tags(self) -> Union[List[IPTag], None]:
ip_tags = self.raw_param.get("node_public_ip_tags")
res = []
if ip_tags:
for k, v in ip_tags.items():
res.append(self.models.IPTag(
ip_tag_type=k,
tag=v,
))
return res


class AKSAgentPoolAddDecorator:
def __init__(
Expand Down Expand Up @@ -1587,6 +1599,13 @@ def set_up_agentpool_network_profile(self, agentpool: AgentPool) -> AgentPool:
agentpool.network_profile = self.models.AgentPoolNetworkProfile()
agentpool.network_profile.allowed_host_ports = allowed_host_ports
agentpool.network_profile.application_security_groups = asg_ids

ip_tags = self.context.get_ip_tags()
if ip_tags:
if not agentpool.network_profile:
agentpool.network_profile = self.models.AgentPoolNetworkProfile()
agentpool.network_profile.node_public_ip_tags = ip_tags

return agentpool

def construct_agentpool_profile_default(self, bypass_restore_defaults: bool = False) -> AgentPool:
Expand Down Expand Up @@ -1833,7 +1852,7 @@ def update_network_profile(self, agentpool: AgentPool) -> AgentPool:

asg_ids = self.context.get_asg_ids()
allowed_host_ports = self.context.get_allowed_host_ports()
if asg_ids or allowed_host_ports:
if (asg_ids or allowed_host_ports) and not agentpool.network_profile:
agentpool.network_profile = self.models.AgentPoolNetworkProfile()
if asg_ids is not None:
agentpool.network_profile.application_security_groups = asg_ids
Expand Down
4 changes: 4 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ def aks_create(
load_balancer_outbound_ip_prefixes=None,
load_balancer_outbound_ports=None,
load_balancer_idle_timeout=None,
load_balancer_backend_pool_type=None,
nat_gateway_managed_outbound_ip_count=None,
nat_gateway_idle_timeout=None,
outbound_type=None,
Expand Down Expand Up @@ -611,6 +612,7 @@ def aks_create(
yes=False,
no_wait=False,
aks_custom_headers=None,
node_public_ip_tags=None,
):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down Expand Up @@ -665,6 +667,7 @@ def aks_update(
load_balancer_outbound_ip_prefixes=None,
load_balancer_outbound_ports=None,
load_balancer_idle_timeout=None,
load_balancer_backend_pool_type=None,
nat_gateway_managed_outbound_ip_count=None,
nat_gateway_idle_timeout=None,
outbound_type=None,
Expand Down Expand Up @@ -2197,6 +2200,7 @@ def aks_agentpool_add(
gpu_instance_profile=None,
allowed_host_ports=None,
asg_ids=None,
node_public_ip_tags=None,
):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1874,6 +1874,19 @@ def get_load_balancer_idle_timeout(self) -> Union[int, None]:
"load_balancer_idle_timeout"
)

def get_load_balancer_backend_pool_type(self) -> Union[str, None]:
"""Obtain the value of load_balancer_backend_pool_type.
:return: string
"""
# read the original value passed by the command
load_balancer_backend_pool_type = self.raw_param.get(
"load_balancer_backend_pool_type"
)

# this parameter does not need dynamic completion
# this parameter does not need validation
return load_balancer_backend_pool_type

def get_nat_gateway_managed_outbound_ip_count(self) -> Union[int, None]:
"""Obtain the value of nat_gateway_managed_outbound_ip_count.
Expand Down Expand Up @@ -5345,6 +5358,7 @@ def set_up_network_profile(self, mc: ManagedCluster) -> ManagedCluster:
self.context.get_load_balancer_outbound_ip_prefixes(),
self.context.get_load_balancer_outbound_ports(),
self.context.get_load_balancer_idle_timeout(),
self.context.get_load_balancer_backend_pool_type(),
models=self.models.load_balancer_models,
)

Expand Down Expand Up @@ -6600,6 +6614,7 @@ def update_load_balancer_profile(self, mc: ManagedCluster) -> ManagedCluster:
outbound_ip_prefixes=self.context.get_load_balancer_outbound_ip_prefixes(),
outbound_ports=self.context.get_load_balancer_outbound_ports(),
idle_timeout=self.context.get_load_balancer_idle_timeout(),
backend_pool_type=self.context.get_load_balancer_backend_pool_type(),
profile=mc.network_profile.load_balancer_profile,
models=self.models.load_balancer_models)
return mc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def test_configure_load_balancer_profile(self):
outbound_ip_prefixes,
outbound_ports,
idle_timeout,
None,
profile,
lb_models,
)
Expand Down
Loading

0 comments on commit e45f1a0

Please sign in to comment.