Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
30532b7
[AKS] aks-preview: add --enable/--disable-control-plane-metrics
davidkydd May 7, 2026
e3c6dff
fix(aks-preview): reject --enable-control-plane-metrics with --disabl…
davidkydd May 12, 2026
a7b923c
fix(aks-preview): trigger control-plane-metrics validation on create …
davidkydd May 12, 2026
9cda233
docs(aks-preview): clarify --enable-control-plane-metrics prerequisit…
davidkydd May 12, 2026
6101e76
docs(aks-preview): move Pending bullets into 20.0.0b7 release section
davidkydd May 12, 2026
3f343fe
test(aks-preview): add control-plane metrics validation/update coverage
davidkydd May 12, 2026
552ef2c
fix(aks-preview): add short aliases for control-plane-metrics flags
davidkydd May 12, 2026
620006a
fix(aks-preview): add inline help= for control-plane-metrics flags
davidkydd May 12, 2026
88a3e2e
fix(aks-preview): wrap long help= and add aliases to help entries
davidkydd May 13, 2026
5fe4614
Merge branch 'main' into dakydd/ccpmetricsga-20260202preview
davidkydd May 15, 2026
b2a70ba
Merge branch 'main' into dakydd/ccpmetricsga-20260202preview
davidkydd May 15, 2026
6d68b02
test(aks-preview): add scenario tests for control-plane-metrics flags
davidkydd May 17, 2026
1688243
Add --disable-azure-monitor-metrics flag for create and update commands
davidkydd May 22, 2026
0983774
Add custom test matrix for control-plane-metrics tests
davidkydd May 22, 2026
c8ff292
Delete src/aks-preview/azcli_aks_live_test/configs/ext_matrix_cpm_onl…
davidkydd May 22, 2026
26d9e27
Fix lint: remove disable-azure-monitor-metrics from aks create, add w…
davidkydd May 22, 2026
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
+++++++

21.0.0b2
++++++
* `az aks create / update`: Add `--enable-control-plane-metrics` and `az aks update`: `--disable-control-plane-metrics` flags to opt clusters into Azure Monitor managed Prometheus control plane metrics (kube-apiserver, etcd, etc.) via the first-class API property in API version `2026-02-02-preview` (replaces the AFEC-gated preview).

21.0.0b1
++++++
* [BREAKING CHANGE] `az aks create/update`: Remove `--disk-driver-version` option as the `version` field has been removed from the API spec for `ManagedClusterStorageProfileDiskCSIDriver`.
Expand Down
12 changes: 12 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,9 @@
- name: --enable-azure-monitor-metrics
type: bool
short-summary: Enable Azure Monitor Metrics Profile
- name: --enable-control-plane-metrics --enable-cp-metrics
type: bool
short-summary: Enable collection of Azure Monitor managed Prometheus control plane metrics for managed cluster components (kube-apiserver, etcd, etc). Requires Azure Monitor metrics to be enabled (already enabled or via --enable-azure-monitor-metrics). See aka.ms/aks/controlplane-metrics.
- name: --azure-monitor-workspace-resource-id
type: string
short-summary: Resource ID of the Azure Monitor Workspace
Expand Down Expand Up @@ -1285,6 +1288,12 @@
- name: --enable-azure-monitor-metrics
type: bool
short-summary: Enable Azure Monitor Metrics Profile
- name: --disable-azure-monitor-metrics
type: bool
short-summary: Disable Azure Monitor Metrics Profile
- name: --enable-control-plane-metrics --enable-cp-metrics
type: bool
short-summary: Enable collection of Azure Monitor managed Prometheus control plane metrics for managed cluster components (kube-apiserver, etcd, etc). Requires Azure Monitor metrics to be enabled (already enabled or via --enable-azure-monitor-metrics). See aka.ms/aks/controlplane-metrics.
- name: --azure-monitor-workspace-resource-id
type: string
short-summary: Resource ID of the Azure Monitor Workspace
Expand All @@ -1306,6 +1315,9 @@
- name: --disable-azure-monitor-metrics
type: bool
short-summary: Disable Azure Monitor Metrics Profile. This will delete all DCRA's associated with the cluster, any linked DCRs with the data stream = prometheus-stream and the recording rule groups created by the addon for this AKS cluster.
- name: --disable-control-plane-metrics --disable-cp-metrics
type: bool
short-summary: Disable collection of Azure Monitor managed Prometheus control plane metrics. Leaves Azure Monitor metrics enabled. See aka.ms/aks/controlplane-metrics.
- name: --enable-azure-monitor-app-monitoring
type: bool
short-summary: Enable Azure Monitor Application Monitoring
Expand Down
30 changes: 30 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,16 @@ 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(
"enable_control_plane_metrics",
options_list=["--enable-control-plane-metrics", "--enable-cp-metrics"],
action="store_true",
help=(
"Enable collection of Azure Monitor managed Prometheus control plane metrics for managed "
"cluster components (kube-apiserver, etcd, etc). Requires Azure Monitor metrics to be enabled "
"(already enabled or via --enable-azure-monitor-metrics). See aka.ms/aks/controlplane-metrics."
),
)
c.argument("enable_azure_monitor_app_monitoring",
is_preview=True,
action="store_true"
Expand Down Expand Up @@ -1579,6 +1589,7 @@ def load_arguments(self, _):
),
)
c.argument("enable_azure_monitor_metrics", action="store_true")
c.argument("disable_azure_monitor_metrics", action="store_true")
c.argument(
"azure_monitor_workspace_resource_id",
validator=validate_azuremonitorworkspaceresourceid,
Expand All @@ -1596,6 +1607,25 @@ def load_arguments(self, _):
hide=True,
),
)
c.argument(
"enable_control_plane_metrics",
options_list=["--enable-control-plane-metrics", "--enable-cp-metrics"],
action="store_true",
help=(
"Enable collection of Azure Monitor managed Prometheus control plane metrics for managed "
"cluster components (kube-apiserver, etcd, etc). Requires Azure Monitor metrics to be enabled "
"(already enabled or via --enable-azure-monitor-metrics). See aka.ms/aks/controlplane-metrics."
),
)
c.argument(
"disable_control_plane_metrics",
options_list=["--disable-control-plane-metrics", "--disable-cp-metrics"],
action="store_true",
help=(
"Disable collection of Azure Monitor managed Prometheus control plane metrics. "
"Sets azureMonitorProfile.metrics.controlPlane.enabled=false on the cluster."
),
)
c.argument("enable_azure_monitor_app_monitoring",
action="store_true",
is_preview=True
Expand Down
3 changes: 2 additions & 1 deletion src/aks-preview/azext_aks_preview/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,12 @@ def load_command_table(self, _):

# AKS nodepool auto-scale command
with self.command_group(
"aks nodepool auto-scale", managed_clusters_sdk, client_factory=cf_agent_pools
"aks nodepool auto-scale", agent_pools_sdk, client_factory=cf_agent_pools
) as g:
g.custom_command("add", "aks_agentpool_auto_scale_add", supports_no_wait=True)
g.custom_command("update", "aks_agentpool_auto_scale_update", supports_no_wait=True)
g.custom_command("delete", "aks_agentpool_auto_scale_delete", supports_no_wait=True)
g.wait_command("wait")

with self.command_group(
"aks machine", machines_sdk, client_factory=cf_machines
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 @@ -1136,6 +1136,7 @@ def aks_create(
ksm_metric_annotations_allow_list=None,
grafana_resource_id=None,
enable_windows_recording_rules=False,
enable_control_plane_metrics=False,
# azure monitor profile - app monitoring
enable_azure_monitor_app_monitoring=False,
# opentelemetry parameters
Expand Down Expand Up @@ -1361,6 +1362,8 @@ def aks_update(
enable_windows_recording_rules=False,
disable_azuremonitormetrics=False,
disable_azure_monitor_metrics=False,
enable_control_plane_metrics=False,
disable_control_plane_metrics=False,
# azure monitor profile - app monitoring
enable_azure_monitor_app_monitoring=False,
disable_azure_monitor_app_monitoring=False,
Expand Down
121 changes: 121 additions & 0 deletions src/aks-preview/azext_aks_preview/managed_cluster_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2596,6 +2596,91 @@ def get_disable_azure_monitor_metrics(self) -> bool:
"""
return self._get_disable_azure_monitor_metrics(enable_validation=True)

def _get_enable_control_plane_metrics(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of enable_control_plane_metrics.
This function supports the option of enable_validation. When enabled, if both
enable_control_plane_metrics and disable_control_plane_metrics are specified, raise a
MutuallyExclusiveArgumentError. Additionally, --enable-control-plane-metrics requires Azure
Monitor metrics to either already be enabled on the cluster or to be enabled in the same
command via --enable-azure-monitor-metrics.

:return: bool
"""
# Read the original value passed by the command.
enable_control_plane_metrics = self.raw_param.get("enable_control_plane_metrics")
# 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.azure_monitor_profile and
self.mc.azure_monitor_profile.metrics and
self.mc.azure_monitor_profile.metrics.control_plane
):
enable_control_plane_metrics = self.mc.azure_monitor_profile.metrics.control_plane.enabled
# This parameter does not need dynamic completion.
if enable_validation:
if enable_control_plane_metrics and self._get_disable_control_plane_metrics(False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-control-plane-metrics and --disable-control-plane-metrics "
"at the same time."
)
if enable_control_plane_metrics:
# Reject combining enable-control-plane-metrics with disable-azure-monitor-metrics
# in the same command — the resulting payload would be inconsistent.
if self._get_disable_azure_monitor_metrics(False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-control-plane-metrics together with "
"--disable-azure-monitor-metrics."
)
# Must have Azure Monitor metrics enabled (either already or in this command).
already_enabled = (
self.mc and
self.mc.azure_monitor_profile and
self.mc.azure_monitor_profile.metrics and
self.mc.azure_monitor_profile.metrics.enabled
)
enabling_now = self._get_enable_azure_monitor_metrics(False)
if not already_enabled and not enabling_now:
raise RequiredArgumentMissingError(
"--enable-control-plane-metrics requires Azure Monitor metrics to be enabled. "
"Specify --enable-azure-monitor-metrics or run on a cluster that already has "
"Azure Monitor metrics enabled."
)
Comment thread
davidkydd marked this conversation as resolved.
return enable_control_plane_metrics

def get_enable_control_plane_metrics(self) -> bool:
"""Obtain the value of enable_control_plane_metrics.
This function will verify the parameter by default. If both enable_control_plane_metrics and
disable_control_plane_metrics are specified, raise a MutuallyExclusiveArgumentError.
:return: bool
"""
return self._get_enable_control_plane_metrics(enable_validation=True)

def _get_disable_control_plane_metrics(self, enable_validation: bool = False) -> bool:
"""Internal function to obtain the value of disable_control_plane_metrics.
This function supports the option of enable_validation. When enabled, if both
enable_control_plane_metrics and disable_control_plane_metrics are specified, raise a
MutuallyExclusiveArgumentError.
:return: bool
"""
# Read the original value passed by the command.
disable_control_plane_metrics = self.raw_param.get("disable_control_plane_metrics")
if enable_validation:
if disable_control_plane_metrics and self._get_enable_control_plane_metrics(False):
raise MutuallyExclusiveArgumentError(
"Cannot specify --enable-control-plane-metrics and --disable-control-plane-metrics "
"at the same time."
)
return disable_control_plane_metrics

def get_disable_control_plane_metrics(self) -> bool:
"""Obtain the value of disable_control_plane_metrics.
This function will verify the parameter by default. If both enable_control_plane_metrics and
disable_control_plane_metrics are specified, raise a MutuallyExclusiveArgumentError.
:return: bool
"""
return self._get_disable_control_plane_metrics(enable_validation=True)

def _get_enable_azure_monitor_app_monitoring(self, enable_validation=True) -> bool:
"""Internal function to obtain the value of enable_azure_monitor_app_monitoring.
This function supports the option of enable_validation. When enabled, if both
Expand Down Expand Up @@ -4622,6 +4707,13 @@ def _setup_azure_monitor_metrics(self, mc: ManagedCluster) -> None:
metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)
))
mc.azure_monitor_profile.metrics.kube_state_metrics = kube_state_metrics

# Enable control plane metrics if requested.
if self.context.get_enable_control_plane_metrics():
mc.azure_monitor_profile.metrics.control_plane = (
self.models.ManagedClusterAzureMonitorProfileMetricsControlPlane(enabled=True)
)

Comment on lines +4711 to +4716
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a7b923c — set_up_azure_monitor_profile now calls get_enable_control_plane_metrics() unconditionally so passing --enable-control-plane-metrics without the parent flag raises RequiredArgumentMissingError on create instead of being silently ignored when _setup_azure_monitor_metrics is skipped.

self.context.set_intermediate("azuremonitormetrics_addon_enabled", True, overwrite_exists=True)

def _setup_azure_monitor_app_monitoring(self, mc: ManagedCluster) -> None:
Expand Down Expand Up @@ -4741,6 +4833,11 @@ def set_up_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster:
"""
self._ensure_mc(mc)

# Trigger control-plane-metrics validation even if the parent metrics flag was
# not specified, so users get a clear error instead of silent ignore when they
# pass --enable-control-plane-metrics on its own.
self.context.get_enable_control_plane_metrics()

if self.context.get_enable_azure_monitor_metrics():
self._setup_azure_monitor_metrics(mc)

Expand Down Expand Up @@ -6908,6 +7005,30 @@ def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster:
if self.context.get_disable_azure_monitor_metrics():
self._disable_azure_monitor_metrics(mc)

# Handle enable / disable of control plane metrics independently of the parent metrics flag,
# so users can toggle control plane metrics on a cluster that already has metrics enabled.
if self.context.get_enable_control_plane_metrics():
if mc.azure_monitor_profile is None:
mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() # pylint: disable=no-member
if mc.azure_monitor_profile.metrics is None:
# Should not normally happen — validation requires metrics to be enabled — but guard
# against partially-populated profiles to avoid AttributeError.
mc.azure_monitor_profile.metrics = (
self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=True) # pylint: disable=no-member
)
mc.azure_monitor_profile.metrics.control_plane = (
self.models.ManagedClusterAzureMonitorProfileMetricsControlPlane(enabled=True) # pylint: disable=no-member
)

if self.context.get_disable_control_plane_metrics():
if (
mc.azure_monitor_profile and
mc.azure_monitor_profile.metrics
):
mc.azure_monitor_profile.metrics.control_plane = (
self.models.ManagedClusterAzureMonitorProfileMetricsControlPlane(enabled=False) # pylint: disable=no-member
)
Comment on lines +7008 to +7030
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 3f343fe — added 5 update-decorator tests covering: (1) enable-cp without parent flag raises RequiredArgumentMissingError, (2) enable-cp succeeds when AM metrics already on cluster, (3) enable-cp + disable-am-metrics raises MutuallyExclusiveArgumentError, (4) enable-cp + disable-cp together raises MutuallyExclusiveArgumentError, (5) disable-cp writes control_plane.enabled=False.


if self.context.get_enable_azure_monitor_app_monitoring():
if mc.azure_monitor_profile is None:
mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile()
Expand Down
Loading
Loading