云计算成本管理
概览
云计算成本管理涉及监控、分析和优化云支出。通过使用预留实例、竞价定价、适当尺寸和成本分配等策略来最大化投资回报率并防止预算超支。
使用场景
- 降低云基础设施成本
- 优化计算支出
- 管理数据库成本
- 存储优化
- 数据传输成本降低
- 预留容量规划
- 收费回溯和成本分配
- 预算预测和警报
实施示例
1. AWS成本优化与AWS CLI
# 启用成本浏览器
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics "UnblendedCost" \
--group-by Type=DIMENSION,Key=SERVICE
# 列出EC2实例以正确尺寸
aws ec2 describe-instances \
--query 'Reservations[*].Instances[*].[InstanceId,InstanceType,State.Name,LaunchTime,Tag]' \
--output table
# 查找未附加的EBS卷
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].[VolumeId,Size,State,CreateTime]'
# 识别未附加的弹性IP
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null]'
# 获取RDS实例成本
aws rds describe-db-instances \
--query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceClass,StorageType,AllocatedStorage]'
# 创建预算警报
aws budgets create-budget \
--account-id 123456789012 \
--budget BudgetName=MyBudget,BudgetLimit='{Amount=1000,Unit=USD}',TimeUnit=MONTHLY,BudgetType=COST \
--notifications-with-subscribers \
'Notification={NotificationType=ACTUAL,ComparisonOperator=GREATER_THAN,Threshold=80},Subscribers=[{SubscriptionType=EMAIL,Address=user@example.com}]'
# 列出节省计划
aws savingsplans describe-savings-plans
# 获取预留实例
aws ec2 describe-reserved-instances \
--query 'ReservedInstances[*].[ReservedInstancesId,InstanceType,State,OfferingType,Duration]'
2. Terraform成本管理配置
# cost-management.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
variable "monthly_budget" {
default = 10000
description = "每月预算限制"
}
# CloudWatch成本异常检测
resource "aws_ce_anomaly_monitor" "cost_anomaly" {
monitor_name = "cost-anomaly-detection"
monitor_type = "DIMENSIONAL"
monitor_dimension = "SERVICE"
monitor_specification = jsonencode({
Dimensions = {
Key = "SERVICE"
Values = ["Amazon EC2", "Amazon RDS", "AWS Lambda"]
}
})
}
# 异常警报
resource "aws_ce_anomaly_subscription" "cost_alert" {
account_id = data.aws_caller_identity.current.account_id
display_name = "Cost Alert"
threshold = 100
frequency = "DAILY"
monitor_arn = aws_ce_anomaly_monitor.cost_anomaly.arn
subscription_type = "EMAIL"
subscription_notification_type = "FORECASTED"
}
# 带警报的预算
resource "aws_budgets_budget" "monthly" {
name = "monthly-budget"
budget_type = "COST"
limit_amount = var.monthly_budget
limit_unit = "USD"
time_period_start = "2024-01-01_00:00"
time_period_end = "2099-12-31_23:59"
time_unit = "MONTHLY"
tags = {
Name = "monthly-budget"
}
}
# 预算通知
resource "aws_budgets_budget_notification" "monthly_alert" {
account_id = data.aws_caller_identity.current.account_id
budget_name = aws_budgets_budget.monthly.name
comparison_operator = "GREATER_THAN"
notification_type = "ACTUAL"
threshold = 80
threshold_type = "PERCENTAGE"
notification_subscribers {
address = "user@example.com"
subscription_type = "EMAIL"
}
}
# 节省计划承诺
resource "aws_savingsplans_savings_plan" "compute" {
commitment = 10000
payment_option = "ALL_UPFRONT"
plan_type = "COMPUTE_SAVINGS_PLAN"
term_in_months = 12
tags = {
Name = "compute-savings"
}
}
# 预留实例
resource "aws_ec2_instance" "app" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
tags = {
Name = "app-instance"
}
}
# 预留实例
resource "aws_ec2_capacity_reservation" "app" {
availability_zone = "us-east-1a"
instance_count = 1
instance_platform = "Linux/UNIX"
instance_type = aws_ec2_instance.app.instance_type
reservation_type = "default"
tags = {
Name = "app-reservation"
}
}
# CloudWatch仪表板用于成本监控
resource "aws_cloudwatch_dashboard" "cost_dashboard" {
dashboard_name = "cost-dashboard"
dashboard_body = jsonencode({
widgets = [
{
type = "metric"
properties = {
metrics = [
["AWS/Billing", "EstimatedCharges", { stat = "Average" }]
]
period = 86400
stat = "Average"
region = var.aws_region
title = "Estimated Monthly Charges"
yAxis = {
left = {
min = 0
}
}
}
}
]
})
}
# 当前账户数据
data "aws_caller_identity" "current" {}
# 标签合规性和成本分配
resource "aws_ec2_instance" "tagged_instance" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.small"
tags = {
Name = "cost-tracked-instance"
CostCenter = "engineering"
Environment = "production"
Project = "web-app"
ManagedBy = "terraform"
ChargebackEmail = "ops@example.com"
}
}
3. Azure成本管理
# 安装Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | bash
# 获取成本分析
az costmanagement query \
--timeframe MonthToDate \
--type Usage \
--dataset aggregation='{"totalCost":{"name":"PreTaxCost","function":"Sum"}}' \
--dataset grouping='[{"type":"Dimension","name":"ResourceType"}]'
# 创建预算警报
az consumption budget create \
--name MyBudget \
--category Cost \
--amount 5000 \
--time-grain Monthly \
--start-date 2024-01-01 \
--notifications-enabled True
# 列出建议
az advisor recommendation list \
--category Cost
# 导出成本数据
az costmanagement export create \
--name MonthlyExport \
--dataset aggregation='{"totalCost":{"name":"PreTaxCost","function":"Sum"}}' \
--timeframe TheLastMonth \
--schedule-status Active
# 获取VM尺寸建议
az advisor recommendation list \
--category Performance \
--query "[?properties.category=='Compute']"
4. GCP成本优化
# 获取账单数据
gcloud billing accounts list
# 创建预算
gcloud billing budgets create \
--billing-account=BILLING_ACCOUNT_ID \
--display-name="Monthly Budget" \
--budget-amount=10000 \
--threshold-rule=percent=50 \
--threshold-rule=percent=90 \
--threshold-rule=percent=100
# 列出成本建议
gcloud compute instances list \
--format='table(name,machineType.machine_type(),CPUS:format="@(scheduling.nodeAffinities[0].nodeAffinities[0].key): \
(@(scheduling.nodeAffinities[0].nodeAffinities[0].values[0]))")'
# 启用承诺使用折扣
gcloud compute commitments create my-commitment \
--plan=one-year \
--resources=RESOURCE_TYPE=INSTANCES,RESOURCE_SPEC=MACHINE_TYPE=n1-standard-4,COUNT=10 \
--region=us-central1
# 获取存储成本估算
gsutil du -s gs://my-bucket
5. 成本监控仪表板
# Python成本监控工具
import boto3
from datetime import datetime, timedelta
from typing import Dict, List
import json
class CloudCostMonitor:
def __init__(self):
self.ce_client = boto3.client('ce')
self.ec2_client = boto3.client('ec2')
self.rds_client = boto3.client('rds')
def get_monthly_costs_by_service(self, months=3) -> Dict:
"""按服务获取月度成本分解"""
end_date = datetime.now().date()
start_date = end_date - timedelta(days=30*months)
response = self.ce_client.get_cost_and_usage(
TimePeriod={
'Start': start_date.isoformat(),
'End': end_date.isoformat()
},
Granularity='MONTHLY',
Metrics=['UnblendedCost'],
GroupBy=[
{'Type': 'DIMENSION', 'Key': 'SERVICE'}
]
)
costs = {}
for result in response['ResultsByTime']:
for group in result['Groups']:
service = group['Keys'][0]
cost = float(group['Metrics']['UnblendedCost']['Amount'])
if service not in costs:
costs[service] = []
costs[service].append({
'date': result['TimePeriod']['Start'],
'cost': cost
})
return costs
def identify_savings_opportunities(self) -> Dict:
"""识别可以优化的资源"""
opportunities = {
'unattached_ebs_volumes': [],
'unassociated_eips': [],
'underutilized_instances': [],
'unattached_network_interfaces': []
}
# 检查EBS卷
volumes_response = self.ec2_client.describe_volumes(
Filters=[{'Name': 'status', 'Values': ['available']}]
)
for volume in volumes_response['Volumes']:
opportunities['unattached_ebs_volumes'].append({
'volume_id': volume['VolumeId'],
'size_gb': volume['Size'],
'estimated_monthly_cost': volume['Size'] * 0.10
})
# 检查弹性IP
addresses_response = self.ec2_client.describe_addresses()
for address in addresses_response['Addresses']:
if 'AssociationId' not in address:
opportunities['unassociated_eips'].append({
'public_ip': address['PublicIp'],
'estimated_monthly_cost': 3.60
})
# 检查利用率低的实例
instances_response = self.ec2_client.describe_instances()
for reservation in instances_response['Reservations']:
for instance in reservation['Instances']:
opportunities['underutilized_instances'].append({
'instance_id': instance['InstanceId'],
'instance_type': instance['InstanceType'],
'state': instance['State']['Name'],
'recommendation': 'Consider downsizing or terminating'
})
return opportunities
def calculate_potential_savings(self, opportunities: Dict) -> Dict:
"""计算潜在节省"""
savings = {
'ebs_volumes': sum(op['estimated_monthly_cost'] for op in opportunities['unattached_ebs_volumes']),
'eips': sum(op['estimated_monthly_cost'] for op in opportunities['unassociated_eips']),
'total_monthly': 0
}
savings['total_monthly'] = savings['ebs_volumes'] + savings['eips']
savings['total_annual'] = savings['total_monthly'] * 12
return savings
def generate_cost_report(self) -> str:
"""生成全面成本报告"""
costs_by_service = self.get_monthly_costs_by_service()
opportunities = self.identify_savings_opportunities()
savings = self.calculate_potential_savings(opportunities)
report = f"""
===== 云成本报告 =====
生成: {datetime.now().isoformat()}
当前成本按服务:
"""
for service, costs in costs_by_service.items():
total = sum(c['cost'] for c in costs)
report += f"
{service}: ${total:.2f}"
report += f"""
节省机会:
- 未附加EBS卷: ${savings['ebs_volumes']:.2f}/month
- 未关联EIP: ${savings['eips']:.2f}/month
潜在月节省: ${savings['total_monthly']:.2f}
潜在年节省: ${savings['total_annual']:.2f}
"""
return report
# 使用
monitor = CloudCostMonitor()
print(monitor.generate_cost_report())
最佳实践
✅ 做
- 对稳定工作负载使用预留实例
- 为灵活性实施节省计划
- 根据指标对实例进行正确尺寸调整
- 对容错工作负载使用竞价实例
- 定期删除未使用的资源
- 启用详细计费和成本分配
- 使用CloudWatch/成本浏览器监控成本
- 设置预算警报
- 审查月度成本报告
❌ 不做
- 不要让未使用的资源运行
- 不要忽略成本优化建议
- 对可预测的工作负载使用按需服务
- 跳过标记资源
- 忽略数据传输成本
- 忘记存储生命周期策略
成本优化策略
- 预留实例: 20-40%节省
- 竞价实例: 70-90%节省
- 节省计划: 15-30%节省
- 存储优化: 30-50%节省
- 数据传输优化: 10-20%节省