Azure 成本优化实战:基于 autoskills azure-cost 技能的工作流完整指南

原创2026-10-08 19:01:411,693 阅读

Azure 成本优化实战:基于 autoskills azure-cost 技能的工作流完整指南

本文围绕 autoskills 仓库中 azure-cost 技能的 成本优化工作流 展开,系统讲解在 Azure 订阅中"找浪费、清孤儿资源、做缩容(rightsizing)"的标准化操作路径:从前置条件校验、专项分析(Redis/AKS)、azqr 扫描、资源发现、真实成本查询、定价验证、利用率指标采集,到最终生成可审计的优化报告。读完本文,你将掌握一套可复制的端到端成本优化方案,并理解每一步背后的 API 调用细节与限流等约束。

工作流定位与核心原则

成本优化工作流属于 azure-cost 技能(见 SKILL.md)的三大工作流之一。该技能在用户表达"optimize costs / reduce spending / find cost savings / orphaned resources / rightsize VMs / reduce waste"等意图时被激活,其路由表将"降低成本、找浪费"这类请求明确指向本文所讲的工作流。

执行本工作流必须遵守以下核心原则(来自 SKILL.md 的 Best Practices):

  • 先查真实成本,绝不估算:所有结论必须基于 Cost Management API 返回的实际数据(ACTUAL DATA),禁止凭空假设;
  • 账单与建议必须同时呈现:任何优化建议都要搭配总账单和成本分解(来自 Cost Query Workflow)一起展示,否则读者无法判断优化的优先级和收益;
  • 定价必须来自官方来源:并充分考虑免费额度(free tier);
  • 成本查询用 REST API:az rest 比 az costmanagement query 更可靠;
  • 留存审计轨迹:保存所有查询与响应;
  • 不执行破坏性操作:删除资源前必须获得明确批准,提供 dry-run 命令与回滚方案。

Step 0:校验前置条件

开始优化前,先确认工具链与权限就绪。

必需工具:

  • Azure CLI 已安装并完成认证(az login);
  • Azure CLI 扩展:costmanagement、resource-graph;
  • Azure Quick Review(azqr)已安装,安装与用法详见 azure-quick-review.md。

必需权限:

  • Cost Management Reader 角色;
  • Monitoring Reader 角色;
  • 订阅/资源组上的 Reader 角色。

验证命令:

az --version
az account show
az extension show --name costmanagement
azqr version

az account show 同时用于确认当前登录的订阅上下文,后续所有 scope 拼接都依赖它。

Step 1:加载成本优化最佳实践

在动手扫描之前,先通过 MCP 工具加载官方最佳实践,为查询设计和建议生成提供依据:

azure__get_azure_bestpractices({
  intent: "Get cost optimization best practices",
  command: "get_bestpractices",
  parameters: { resource: "cost-optimization", action: "all" }
})

该工具在 SKILL.md 的 MCP 工具表中被定义为 azure__get_azure_bestpractices,参数为 intent(优化上下文),作用是"用成本管理最佳实践指导查询设计"。技能整体推荐 优先使用 MCP 工具而非直接 CLI,仅当 MCP 无法覆盖特定操作时才退回 az rest、az monitor metrics list 等 CLI 命令。

Step 1.5 / 1.6:Redis 专项成本优化(条件分支)

如果用户明确提到 "Redis"、"Azure Cache for Redis" 或 "Azure Managed Redis",且关注点是 Redis 资源本身的优化而非整个订阅分析,则切换到专项参考文档:

参考:Azure Redis Cost Optimization

随后需要与用户确认分析范围,等待用户回复后再继续:

  1. 特定订阅 ID(Specific Subscription ID)
  2. 订阅名称(Subscription Name)
  3. 订阅前缀(Subscription Prefix,例如 "CacheTeam")
  4. 我的所有订阅(All My Subscriptions)
  5. 租户级(Tenant-wide)

注意:若是一般性的订阅级优化,跳过此分支直接进入 Step 2;只有 Redis 专属分析才走该参考文档。

Step 1.7 / 1.8:AKS 专项成本优化(条件分支)

当用户提到 "AKS"、"Kubernetes"、"cluster"、"node pool"、"pod"、"kubectl",或希望启用 AKS 成本分析插件、按命名空间查看成本、报告成本突增/集群利用率异常/预算告警时,进入 AKS 专项分析。

工具选择:

  • 优先使用 MCP:azure__aks 用于 AKS 操作(列集群、获取节点池、检查配置),元数据更丰富,且与本仓库 AKS 技能惯例一致;
  • 退回 CLI:仅当 MCP 无法覆盖特定操作时,使用 az aks 和 kubectl。

按需加载的参考文件(只加载当前请求需要的部分):

AKS 专项分析同样需要先与用户确认分析范围并等待回复:

  1. 特定集群名称 —— 分析单个 AKS 集群
  2. 资源组 —— 分析资源组内所有集群
  3. 订阅 ID —— 分析订阅内所有集群
  4. 我的所有集群 —— 扫描所有可访问订阅下的集群

注意:一般性订阅级优化(包括 AKS 所在资源组)直接进入 Step 2;AKS 聚焦分析按上述参考文档执行。

AKS 成本分析插件启用要点(来自 azure-aks-cost-addon.md)

启用前先检查状态与集群层级:

# 检查插件是否已启用
az aks show \
  --name "<cluster-name>" --resource-group "<resource-group>" \
  --query "addonProfiles.costAnalysis" -o json

# 检查集群层级(插件要求 Standard 或 Premium)
az aks show \
  --name "<cluster-name>" --resource-group "<resource-group>" \
  --query "{tier:sku.tier, name:name}" -o table

Standard/Premium 集群直接启用:

az aks update \
  --name "<cluster-name>" --resource-group "<resource-group>" \
  --enable-cost-analysis

若集群处于 Free 层级,必须先警告用户:从 Free 升级到 Standard 会引入持续的集群管理费用,需通过官方 AKS 定价页或本技能的定价验证步骤确认当前费用,获得用户明确批准后再执行:

az aks update \
  --name "<cluster-name>" --resource-group "<resource-group>" \
  --tier standard

az aks update \
  --name "<cluster-name>" --resource-group "<resource-group>" \
  --enable-cost-analysis

启用后,命名空间级成本数据可从 Azure Portal 的 AKS 集群 → Cost Analysis 面板查看,也可在 Azure Cost Management 中按集群资源 ID + kubernetes namespace 维度过滤。插件本身启用风险低,但 Free → Standard 升级有成本,务必先确认。

Step 2:运行 Azure Quick Review(azqr)扫描

azqr 用于发现孤儿资源,是立即可兑现的成本节约来源。执行方式见 azure-quick-review.md:

azure__extension_azqr
  subscription: "<SUBSCRIPTION_ID>"
  resource-group: "<RESOURCE_GROUP>"  # optional

重点排查对象:

  • 孤儿资源:未挂载的磁盘(unattached disks)、未使用的 NIC、空闲的 NAT 网关;
  • 过度配置:过长的保留周期、过大的 SKU;
  • 缺失成本标签(missing cost tags)。

用 filters.yaml 聚焦成本扫描

为保证扫描聚焦于成本主题,可创建 filters.yaml:

includeSections:
  - Costs
  - Advisor
  - Inventory
  - Orphaned
excludeSections:
  - Recommendations
  - AzurePolicy
  - DefenderRecommendations

也可以直接走 CLI(MCP 不可用时):

azqr scan --subscription "<SUBSCRIPTION_ID>" --resource-group "<RESOURCE_GROUP>" --filters ./filters.yaml --output json

输出管理约定:

  1. 创建 output/ 文件夹(mkdir output,若不存在);
  2. 将报告保存为 output/azqr_report_<YYYYMMDD_HHMMSS>.json;
  3. 扫描完成后删除临时 filters.yaml。

扫描产生的 JSON 报告按影响级别(High/Medium/Low)分类给出建议,包含:孤儿资源(NIC、磁盘、IP)、Azure Advisor 成本建议、资源清单、按资源的成本分解。需要强调的是:azqr 提供的是定性治理建议,任何发现都必须先用真实成本数据验证后再做变更,且工具要求订阅/资源组上的 Reader 角色。

Step 3:发现资源

使用 Azure Resource Graph(ARG)实现跨订阅的高效资源发现,孤儿资源检测模式见 azure-resource-graph.md。

az account show
az resource list --subscription "<SUBSCRIPTION_ID>" --resource-group "<RESOURCE_GROUP>"

ARG 常用查询模式

ARG 通过 az graph query 以 KQL 执行(前置条件:az extension add --name resource-graph)。也可用 MCP 工具 azure__extension_cli_generate 生成命令:

azure__extension_cli_generate
  intent: "query Azure Resource Graph to <describe what you want to find>"
  cli-type: "az"

核心数据表:Resources(所有 ARM 资源)、ResourceContainers(订阅/资源组/管理组)、AdvisorResources(成本与性能建议)。

查找孤儿(未挂载)托管磁盘:

Resources
| where type =~ 'microsoft.compute/disks'
| where isempty(managedBy)
| project name, resourceGroup, location, diskSizeGb=properties.diskSizeGB, sku=sku.name

查找未关联公网 IP:

Resources
| where type =~ 'microsoft.network/publicipaddresses'
| where isempty(properties.ipConfiguration)
| project name, resourceGroup, location, sku=sku.name

查找孤儿网络接口:

Resources
| where type =~ 'microsoft.network/networkinterfaces'
| where isempty(properties.virtualMachine)
| project name, resourceGroup, location

按 SKU/层级统计资源数(发现过大 SKU):

Resources
| where isnotempty(sku.name)
| summarize count() by type, tostring(sku.name)
| order by count_ desc

成本分配标签覆盖率:

Resources
| extend hasCostCenter = isnotnull(tags['CostCenter'])
| summarize total=count(), tagged=countif(hasCostCenter) by type
| extend coverage=round(100.0 * tagged / total, 1)
| order by total desc

空闲负载均衡器(无后端池):

Resources
| where type =~ 'microsoft.network/loadbalancers'
| where array_length(properties.backendAddressPools) == 0
| project name, resourceGroup, location, sku=sku.name

获取 Advisor 成本建议:

AdvisorResources
| where properties.category == 'Cost'
| project name, impact=properties.impact, description=properties.shortDescription.solution

实用提示:资源类型默认小写,用 =~ 做大小写不敏感匹配;属性用 properties.fieldName 导航;--first N 限制结果数;--subscriptions 限定订阅范围;孤儿资源的判定结果要与 Cost Management API 的真实成本数据交叉验证后再下结论。

Step 4:查询真实成本

从 Azure Cost Management API 获取最近 30 天的真实成本数据。按照 Cost Query Workflow 的配置创建请求体。

创建 temp/cost-query.json:

{
  "type": "ActualCost",
  "timeframe": "Custom",
  "timePeriod": {
    "from": "<START_DATE>",
    "to": "<END_DATE>"
  },
  "dataset": {
    "granularity": "None",
    "aggregation": {
      "totalCost": {
        "name": "Cost",
        "function": "Sum"
      }
    },
    "grouping": [
      {
        "type": "Dimension",
        "name": "ResourceId"
      }
    ]
  }
}

必做计算:<START_DATE> = 30 天前的日期,<END_DATE> = 今天,均采用 ISO 8601 格式。

执行并保存结果到 output/cost-query-result<timestamp>.json。所有 Cost Management API 请求必须携带 --headers "ClientType=GitHubCopilotForAzure" 头。

建议:同时运行一个按 ServiceName 分组的 cost-by-service 查询,以便在给出优化建议的同时呈现总账单分解。可参考 examples.md。

警告(限流):同一 scope 的顺序查询共享按 scope 的限流(4 次请求/分钟)。收到 429 时,检查所有 x-ms-ratelimit-microsoft.costmanagement-*-retry-after 响应头,在最长 retry-after 时间完全过去之前不要继续发送请求。

成本查询请求体解析(来自 request-body-schema.md)

Cost Management Query API 端点为 POST {scope}/providers/Microsoft.CostManagement/query?api-version=2023-11-01。请求体核心字段:

字段 必填 说明
type 是 ActualCost(实际账单含采购)、AmortizedCost(预留/节省计划摊分到使用期)、Usage
timeframe 是 预定义窗口或 Custom:WeekToDate / MonthToDate / BillingMonthToDate / YearToDate / TheLastWeek / TheLastMonth / TheLastBillingMonth / TheLastYear / TheLast7Days / TheLast3Months / Custom
timePeriod 条件 仅当 timeframe 为 Custom 时必填,含 from/to ISO 8601 日期
dataset.granularity 是 None(最长 12 个月)、Daily(最长 31 天)、Monthly(最长 12 个月)
dataset.aggregation 是 仅支持 Sum 函数,来源列 Cost / PreTaxCost / UsageQuantity,键为输出别名(如 totalCost)
dataset.grouping 是 最多 2 个维度,type 为 Dimension(内置)或 TagKey(资源标签),不允许重复
dataset.filter 否 支持 and/or(至少 2 个子表达式)与 not(恰好 1 个);比较操作符 In/Equal/Contains/LessThan/GreaterThan/NotEqual;目标类型 dimensions 或 tags
dataset.sorting 否 direction(Ascending/Descending)+ name(必须是聚合或分组中的列)

执行成本查询(REST 方式,比 az costmanagement query 更可靠):

# 创建 temp 文件夹
New-Item -ItemType Directory -Path "temp" -Force

# 调用 REST API
az rest --method post `
  --url "<scope>/providers/Microsoft.CostManagement/query?api-version=2023-11-01" `
  --headers "ClientType=GitHubCopilotForAzure" `
  --body '@temp/cost-query.json'

scope 路径可参考 SKILL.md 中的 Scope Reference 表:订阅 /subscriptions/<subscription-id>、资源组 /subscriptions/<subscription-id>/resourceGroups/<resource-group-name>、管理组、账单账户、账单配置文件等。

关键护栏(来自 guardrails.md)

规则 约束
Daily 粒度最大范围 31 天
Monthly/None 粒度最大范围 12 个月
API 绝对最大范围 37 个月(超出返回 HTTP 400)
最大 GroupBy 维度数 2
ResourceId 分组作用域 仅订阅与资源组支持,更高 scope 不支持
每页最大行数 5,000(默认 1,000)
Custom 时间窗 必须提供 timePeriod 的 from/to
and/or 过滤器 必须至少 2 个表达式

其他值得注意的行为:未指定时间窗时默认"本月第一天 → 今天";from 晚于 to 时系统会静默交换;两个日期都在未来时整个区间平移至去年同期,仅 to 在未来时 to 调整为今天——这些静默调整务必警惕;最早允许的 from 日期为 2014-05-01。EA 账号在管理组作用域按 SubscriptionName 过滤必须同时附带 SubscriptionId 过滤器,否则报错。按 ResourceId 分组在高 scope(计费账户、管理组)不可用,此时应改用 ServiceName、SubscriptionName 等维度,或先收窄到具体订阅。

分页:响应中若出现 nextLink,需继续请求后续页面直到其为 null。

错误处理速查(来自 workflow.md)

HTTP 状态 错误 处理建议
400 无效请求体 检查 schema、日期范围与维度兼容性
401 未授权 重新认证(az login)
403 禁止访问 确认 scope 上有 Cost Management Reader 角色
404 未找到 scope 核对 scope URL 与资源 ID
429 请求过多 检查所有 x-ms-ratelimit-microsoft.costmanagement-*-retry-after 头(qpu/entity/tenant),等待最长值,最多重试 3 次
503 服务不可用 查看 Azure 状态页

Step 5:验证定价

使用 fetch_webpage 从官方 Azure 定价页面获取当前定价:

重点验证的服务:

  • Container Apps:https://azure.microsoft.com/pricing/details/container-apps/
  • 虚拟机:https://azure.microsoft.com/pricing/details/virtual-machines/
  • App Service:https://azure.microsoft.com/pricing/details/app-service/
  • Log Analytics:https://azure.microsoft.com/pricing/details/monitor/

重要:检查免费额度(free tier)——许多 Azure 服务有慷慨的免费限制,忽略它们会导致建议失真。

在 SKILL.md 的数据分类中,来自官方定价页的数据被标记为 VALIDATED PRICING,与 ACTUAL DATA(Cost Management API)、ACTUAL METRICS(Azure Monitor)一起构成计算 ESTIMATED SAVINGS 的三大依据——三者缺一不可。

Step 6:采集利用率指标

查询 Azure Monitor 获取最近 14 天的利用率数据,用于支撑缩容(rightsizing)建议:

$startTime = (Get-Date).AddDays(-14).ToString("yyyy-MM-ddTHH:mm:ssZ")
$endTime = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"

# VM CPU 利用率
az monitor metrics list `
  --resource "<RESOURCE_ID>" `
  --metric "Percentage CPU" `
  --interval PT1H `
  --aggregation Average `
  --start-time $startTime `
  --end-time $endTime

典型的缩容决策路径:先拿到 30 天真实成本(Step 4),再验证官方定价(Step 5),最后用 14 天利用率指标判断资源是否长期低水位运行。若资源成本低于 10 美元/月(SKILL.md 建议),应把重点放在运维改进而非财务节约上。

AKS 异常调查的指标配合(来自 azure-aks-anomalies.md)

当用户报告成本/利用率突增时,按时间窗关联三类证据:

  1. 成本数据:Daily 粒度、按 ResourceId 分组的 ActualCost 查询;
  2. 节点数与扩缩容事件:先 az monitor metrics list-definitions 确认可用指标,再拉取节点数指标;用 kubectl get events --all-namespaces --field-selector reason=SuccessfulRescale --sort-by='.lastTimestamp' 查看 HPA 扩缩容事件;
  3. Top 消费者:kubectl top nodes 与 kubectl top pods --all-namespaces --sort-by=cpu。

常见诱因对照:非高峰节点数激增 → HPA/VPA 配置问题(检查 HPA min replicas);单 Pod 占满 CPU → 内存泄漏或失控进程(查日志、加资源限制);某天成本突增 → 批处理任务意外运行(检查 CronJob 调度);节点数居高不下 → CAS 缩容受阻(检查 PodDisruptionBudgets、系统 Pod);某命名空间成本突增 → 新部署未设资源限制(补 requests/limits)。

调查完成后可创建月度预算告警(80% 阈值):

az consumption budget create \
  --budget-name "aks-monthly-budget" \
  --amount <budget-amount> \
  --time-grain Monthly \
  --start-date "<YYYY-MM-01>" \
  --end-date "<YYYY-MM-01>" \
  --resource-group "<resource-group>" \
  --threshold 80 \
  --contact-emails "<contact-email>"

Step 7:生成优化报告

生成报告到 output/costoptimizereport<YYYYMMDD_HHMMSS>.md,完整模板见 report-template.md。报告必须包含:执行摘要(executive summary)、按服务的成本分解、免费额度分析、孤儿资源清单、按优先级排序的优化建议、实施命令;同时将成本查询结果保存为 output/cost-query-result<YYYYMMDD_HHMMSS>.json 作为审计轨迹,最后清理临时文件。

报告结构模板:

# Azure Cost Optimization Report
**Generated**: <timestamp>

## Executive Summary
- Total Monthly Cost: $X (ACTUAL DATA from Cost Management API)
- Top Cost Drivers: [List top 3 services with costs]
- Potential Savings: $Y/month

## Cost Breakdown by Service
| Service | Cost (USD) | % of Total |
|---------|-----------|------------|
| ... | ... | ... |
| **Total** | **$X** | **100%** |

## Free Tier Analysis
[Resources operating within free tiers]

## Orphaned Resources (Immediate Savings)
[From azqr — resources that can be deleted immediately]

## Optimization Recommendations
### Priority 1: High Impact, Low Risk
- ACTUAL cost: $X/month
- ESTIMATED savings: $Y/month
- Commands to execute
### Priority 2: Medium Impact, Medium Risk
- ACTUAL baseline, ACTUAL metrics, VALIDATED pricing
- ESTIMATED savings with commands
### Priority 3: Long-term Optimization
[Reserved Instances, Storage tiering]

## Total Estimated Savings
- Monthly: $X | Annual: $Y

## Implementation Commands
[Safe commands with approval warnings]

## Validation Appendix
- Cost Query Results: `output/cost-query-result<timestamp>.json`
- Pricing Sources: [Links]

报告要点:

  • 优先级划分:Priority 1(高影响、低风险,如删除孤儿资源)必须给出真实成本与估算节约额;Priority 2 必须同时具备 ACTUAL baseline、ACTUAL metrics、VALIDATED pricing 三项证据;Priority 3 面向长期优化(预留实例、存储分层);
  • Portal 链接格式:所有资源附带 Azure Portal 链接,统一使用:
    https://portal.azure.com/#@<TENANT_ID>/resource/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/<RESOURCE_PROVIDER>/<RESOURCE_TYPE>/<RESOURCE_NAME>/overview
    
  • 审计轨迹:成本查询结果 JSON 必须归档以便复现;
  • 清理:报告生成后删除临时文件:
    Remove-Item -Path "temp" -Recurse -Force -ErrorAction SilentlyContinue
    

常见坑与安全要求

来自 SKILL.md 的实践约束,同样适用于本工作流:

常见坑:

  • 凭空假设成本:必须查询 Cost Management API 的真实数据;
  • 忽略免费额度:许多服务有可观免费额度;
  • 日期范围错误:成本用 30 天、利用率用 14 天;
  • 不展示账单:优化建议必须搭配成本分解呈现;
  • 成本查询失败:用 az rest + JSON 请求体,不要用 az costmanagement query。

安全要求:

  • 删除资源前必须获得批准;
  • 变更先在非生产环境测试;
  • 提供 dry-run 命令用于验证;
  • 附上回滚流程。

总结:一条完整的优化执行链

将上述步骤串起来,一次完整的 Azure 成本优化会话遵循:校验环境(Step 0)→ 加载最佳实践(Step 1)→ 判断是否走 Redis/AKS 专项(Step 1.5–1.8)→ azqr 扫描找孤儿资源(Step 2)→ ARG 跨订阅发现资源(Step 3)→ 拉取 30 天真实成本(Step 4)→ 验证官方定价与免费额度(Step 5)→ 采集 14 天利用率指标(Step 6)→ 生成带审计轨迹的优化报告(Step 7)。每一步的证据边界都清晰可查:真实成本来自 Cost Management API、利用率来自 Azure Monitor、定价来自官方页面,三者交叉验证后才给出可执行的节约建议——这正是 azure-cost 技能在 SKILL.md 中反复强调的数据分类原则在实战中的落地。

登录后查看全文
autoskills