AWS Budgets ile Harcama Alarmı Kurulumu
AWS hesabınızı açtığınızda her şey güzel görünür. Birkaç EC2 instance, bir RDS, belki bir Lambda fonksiyonu. Ay sonu faturaya bakana kadar. “Bu kadar mı tuttu?” sorusu sysadmin’lerin en çok duyduğu sorulardan biridir ve bu soruyu sormamak için AWS Budgets tam olarak var. Bugün bu servisi A’dan Z’ye kuracağız, hem konsol üzerinden hem de AWS CLI ve Terraform ile.
AWS Budgets Nedir ve Neden Kullanmalısınız
AWS Budgets, belirlediğiniz eşik değerlere göre sizi e-posta, SMS veya SNS üzerinden uyaran bir maliyet yönetim aracıdır. Sadece “para harcandı” diye uyarmakla kalmaz, kullanım miktarı, rezervasyon kapsamı ve Savings Plans kullanım oranı gibi metrikler için de alarm kurabilirsiniz.
Gerçek hayatta bunu neden önemsemeliyiz? Şöyle bir senaryo düşünün: Geliştirici ekibinizden biri test ortamında bir p3.8xlarge instance ayağa kaldırdı ve kapatmayı unuttu. Saatte 12 dolar. Hafta sonu dahil 48 saat çalışırsa 576 dolar sadece bir instance’tan. Eğer bir budget alarmınız yoksa bunu ancak fatura geldiğinde fark edersiniz.
AWS Budgets’ın sunduğu alarm tipleri şunlardır:
- Cost Budget: Belirli bir dolar miktarını aştığınızda uyarır
- Usage Budget: Belirli bir servis için kullanım saatini veya miktarını takip eder
- Reservation Budget: EC2, RDS gibi rezervasyonlarınızın kullanım oranını izler
- Savings Plans Budget: Savings Plans kapsamınızı takip eder
Konsol Üzerinden İlk Budget’ınızı Kurmak
AWS Console’a girip “AWS Budgets” sayfasına gidin. Üst menüden “Billing and Cost Management” altında bulabilirsiniz. “Create budget” butonuna tıklayın.
Basit bir aylık 100 dolarlık maliyet alarmı kuralım. Bu, küçük projelerde veya kişisel AWS hesaplarında başlangıç için iyi bir eşik noktasıdır.
Kurulum adımları:
- Budget type: Cost seçin
- Budget name:
monthly-total-cost-alarmgibi anlamlı bir isim verin - Period: Monthly seçin
- Budget renewal type: Recurring (her ay otomatik sıfırlanır)
- Start month: Mevcut ay
- Budgeting method: Fixed, 100 dolar girin
- Alert threshold: %80 ve %100 için iki ayrı alert ekleyin
İki alert eşiği koymanın sebebi şudur: %80’de “dikkat et” mesajı alırsınız, %100’de ise “artık aştın” uyarısı gelir. Bu şekilde proaktif davranabilirsiniz.
AWS CLI ile Budget Kurulumu
Konsol güzel ama tekrarlanabilir değil. Infrastructure as Code mantığıyla düşünürsek, budget’larımızı da kod olarak yönetmeliyiz. CLI ile nasıl yapacağımıza bakalım.
Önce AWS CLI’ın kurulu ve yapılandırılmış olduğunu varsayıyoruz. Account ID’nizi almak için:
aws sts get-caller-identity --query Account --output text
Şimdi bir JSON dosyası oluşturalım. Budget tanımını bir dosyaya yazacağız:
cat > monthly-budget.json << 'EOF'
{
"BudgetName": "monthly-total-cost",
"BudgetLimit": {
"Amount": "100",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST",
"CostTypes": {
"IncludeTax": true,
"IncludeSubscription": true,
"UseBlended": false,
"IncludeRefund": false,
"IncludeCredit": false,
"IncludeUpfront": true,
"IncludeRecurring": true,
"IncludeOtherSubscription": true,
"IncludeSupport": true,
"IncludeDiscount": true,
"UseAmortized": false
}
}
EOF
Ardından notification (bildirim) tanımını oluşturalım. E-posta adresinizi değiştirmeyi unutmayın:
cat > notifications.json << 'EOF'
[
{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [
{
"SubscriptionType": "EMAIL",
"Address": "[email protected]"
}
]
},
{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 100,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [
{
"SubscriptionType": "EMAIL",
"Address": "[email protected]"
}
]
},
{
"Notification": {
"NotificationType": "FORECASTED",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 100,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [
{
"SubscriptionType": "EMAIL",
"Address": "[email protected]"
}
]
}
]
EOF
Buradaki üçüncü notification tipi çok değerlidir. FORECASTED tipi, AWS’nin mevcut kullanım hızına bakarak ay sonunda ne kadar harcayacağınızı tahmin etmesini sağlar. Yani henüz limiti aşmadan “bu gidişle aşacaksın” uyarısı alırsınız.
Budget’ı oluşturalım. ACCOUNT_ID kısmını değiştirin:
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws budgets create-budget
--account-id $ACCOUNT_ID
--budget file://monthly-budget.json
--notifications-with-subscribers file://notifications.json
Oluşturduğunuz budget’ları listelemek için:
aws budgets describe-budgets
--account-id $ACCOUNT_ID
--query 'Budgets[*].{Name:BudgetName,Limit:BudgetLimit.Amount,Type:BudgetType}'
--output table
Servis Bazlı Budget Alarmları
Genel maliyet alarmı iyi bir başlangıçtır ama asıl güç servis bazlı alarmlardan gelir. Örneğin EC2 için ayrı, RDS için ayrı, S3 için ayrı alarmlar kurabilirsiniz. Bu sayede hangi servisin maliyeti artırdığını anında tespit edebilirsiniz.
EC2 için özel bir budget oluşturalım:
cat > ec2-budget.json << 'EOF'
{
"BudgetName": "ec2-monthly-cost",
"BudgetLimit": {
"Amount": "50",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST",
"CostFilters": {
"Service": ["Amazon Elastic Compute Cloud - Compute"]
},
"CostTypes": {
"IncludeTax": false,
"IncludeSubscription": true,
"UseBlended": false,
"IncludeRefund": false,
"IncludeCredit": false,
"IncludeUpfront": true,
"IncludeRecurring": true,
"IncludeOtherSubscription": true,
"IncludeSupport": false,
"IncludeDiscount": true,
"UseAmortized": false
}
}
EOF
cat > ec2-notifications.json << 'EOF'
[
{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 75,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [
{
"SubscriptionType": "EMAIL",
"Address": "[email protected]"
}
]
}
]
EOF
aws budgets create-budget
--account-id $ACCOUNT_ID
--budget file://ec2-budget.json
--notifications-with-subscribers file://ec2-notifications.json
Servis isimlerini doğru yazmak çok önemlidir. AWS’nin kullandığı servis isimlerinin listesini görmek için Cost Explorer’dan yararlanabilirsiniz ya da şu komutu kullanabilirsiniz:
aws ce get-dimension-values
--time-period Start=2024-01-01,End=2024-12-31
--dimension SERVICE
--query 'DimensionValues[*].Value'
--output text | tr 't' 'n' | sort
Tag Bazlı Budget Alarmları
Büyük organizasyonlarda cost center’lara göre ayrım yapmak gerekir. Geliştirme ortamı ne kadar, production ne kadar, hangi proje ne kadar harcıyor? Bunun için resource tag’lerini kullanıyoruz.
Önce tag’lerin Cost Allocation Tag olarak aktif edilmesi gerekir. AWS Console’dan “Billing > Cost Allocation Tags” menüsüne gidin ve kullandığınız tag’leri aktif edin. Tag aktivasyonu 24 saate kadar sürebilir.
Diyelim ki tüm kaynaklarınızı Environment: production ve Environment: development şeklinde tag’liyorsunuz. Sadece production ortamı için bir budget oluşturalım:
cat > prod-budget.json << 'EOF'
{
"BudgetName": "production-environment-cost",
"BudgetLimit": {
"Amount": "500",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST",
"CostFilters": {
"TagKeyValue": ["user:Environment$production"]
},
"CostTypes": {
"IncludeTax": true,
"IncludeSubscription": true,
"UseBlended": false,
"IncludeRefund": false,
"IncludeCredit": false,
"IncludeUpfront": true,
"IncludeRecurring": true,
"IncludeOtherSubscription": true,
"IncludeSupport": true,
"IncludeDiscount": true,
"UseAmortized": false
}
}
EOF
Tag filtresi formatı önemlidir: user:TagAnahtari$TagDegeri şeklinde yazılır. User prefix’i sizin koyduğunuz tag’ler içindir, AWS managed tag’ler için ise aws: prefix’i kullanılır.
Terraform ile Budget Yönetimi
Gerçek dünyada onlarca farklı budget alarmı yönetmeniz gerekebilir. Bu noktada Terraform devreye girer. Bir kez yazarsınız, her ortamda tekrar kullanırsınız.
Ana modül dosyamızı oluşturalım:
cat > main.tf << 'EOF'
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
data "aws_caller_identity" "current" {}
locals {
account_id = data.aws_caller_identity.current.account_id
}
variable "budget_configs" {
description = "Budget konfigurasyonlari"
type = list(object({
name = string
limit_usd = number
threshold = number
email = string
}))
default = [
{
name = "total-monthly-cost"
limit_usd = 100
threshold = 80
email = "[email protected]"
},
{
name = "ec2-monthly-cost"
limit_usd = 50
threshold = 75
email = "[email protected]"
}
]
}
resource "aws_budgets_budget" "cost_budgets" {
for_each = { for b in var.budget_configs : b.name => b }
name = each.value.name
budget_type = "COST"
limit_amount = tostring(each.value.limit_usd)
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = each.value.threshold
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = [each.value.email]
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED"
subscriber_email_addresses = [each.value.email]
}
}
output "budget_names" {
value = [for b in aws_budgets_budget.cost_budgets : b.name]
}
EOF
Terraform ile deploy etmek için:
terraform init
terraform plan -out=budgets.plan
terraform apply budgets.plan
SNS ile Gelişmiş Bildirim Sistemi
E-posta tek başına yeterli değildir. Slack’e mesaj atmak, PagerDuty’ye alert göndermek veya otomatik bir Lambda tetiklemek isteyebilirsiniz. Bunun için SNS kullanacağız.
Önce SNS topic oluşturalım:
# SNS Topic olustur
SNS_ARN=$(aws sns create-topic
--name aws-budget-alerts
--query TopicArn
--output text)
echo "SNS Topic ARN: $SNS_ARN"
# E-posta subscription ekle
aws sns subscribe
--topic-arn $SNS_ARN
--protocol email
--notification-endpoint [email protected]
Sonrasında e-postanızı kontrol edin ve subscription’ı onaylayın. AWS, onaylamadan mesaj göndermez.
Şimdi budget’ı SNS ile birlikte oluşturalım:
cat > snsbudget-notifications.json << EOF
[
{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [
{
"SubscriptionType": "EMAIL",
"Address": "[email protected]"
},
{
"SubscriptionType": "SNS",
"Address": "$SNS_ARN"
}
]
}
]
EOF
aws budgets create-budget
--account-id $ACCOUNT_ID
--budget file://monthly-budget.json
--notifications-with-subscribers file://snsbudget-notifications.json
SNS üzerinden Slack’e mesaj göndermek için Lambda fonksiyonu yazabilirsiniz. SNS topic’e bir Lambda abone olur, Lambda da Slack webhook’una mesaj atar. Bu kurulumu ayrı bir yazıda detaylıca ele alacağım.
Budget Action ile Otomatik Müdahale
AWS Budgets’ın en güçlü özelliklerinden biri Budget Actions. Belirli bir eşik aşıldığında sadece uyarmakla kalmaz, otomatik olarak bir aksiyon da alabilir. Örneğin IAM policy’yi değiştirerek yeni kaynak oluşturmayı engelleyebilir veya EC2 instance’ları durdurabilirsiniz.
Senaryo: Aylık 200 doları aştığında otomatik olarak bir IAM policy uygula ve yeni EC2 instance başlatmayı engelle.
Önce kısıtlayıcı IAM policy’yi oluşturalım:
cat > deny-ec2-launch-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"ec2:RunInstances",
"ec2:StartInstances"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalArn": "arn:aws:iam::ACCOUNT_ID:role/AdminRole"
}
}
}
]
}
EOF
aws iam create-policy
--policy-name DenyEC2LaunchOnBudgetExceed
--policy-document file://deny-ec2-launch-policy.json
--description "Budget asiminda EC2 baslatilamaz"
Budget Actions kurulumu konsol üzerinden daha kolaydır. AWS Console’da ilgili budget’ı açın, “Actions” sekmesine geçin ve “Add action” butonuna tıklayın. IAM action seçin, oluşturduğunuz policy’yi seçin ve eşiği belirleyin.
Bu özelliği üretim ortamında kullanırken dikkatli olun. Kritik servisleri de durdurabilir. Mutlaka admin rolünüzü exception olarak ekleyin.
Mevcut Budget’ları Yönetme ve İzleme
Budget’ları kurduktan sonra düzenli olarak gözden geçirmeniz gerekir. İşte işe yarar birkaç CLI komutu:
# Tum budget'lari listele ve mevcut harcamayi goster
aws budgets describe-budgets
--account-id $ACCOUNT_ID
--query 'Budgets[*].{
Ad:BudgetName,
Limit:BudgetLimit.Amount,
Harcanan:CalculatedSpend.ActualSpend.Amount,
Tahmini:CalculatedSpend.ForecastedSpend.Amount
}'
--output table
# Belirli bir budget'in detaylarini gor
aws budgets describe-budget
--account-id $ACCOUNT_ID
--budget-name "monthly-total-cost"
# Budget notification'larini listele
aws budgets describe-notifications-for-budget
--account-id $ACCOUNT_ID
--budget-name "monthly-total-cost"
Bir budget’ı güncellemeniz gerekirse, örneğin limiti 100 dolardan 150 dolara çıkarmak için:
aws budgets update-budget
--account-id $ACCOUNT_ID
--new-budget '{
"BudgetName": "monthly-total-cost",
"BudgetLimit": {
"Amount": "150",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST"
}'
Pratik Öneriler ve Sık Yapılan Hatalar
Gerçek projelerden öğrendiğim birkaç önemli nokta var.
Budget gecikmesi: AWS Budgets verileri gerçek zamanlı değildir. Genellikle 8-24 saatlik bir gecikme olur. Bu yüzden çok hızlı büyüyen maliyetleri yakalamak için sadece budget’a güvenmemek gerekir. CloudWatch billing alarmları daha hızlı tepki verebilir.
Forecasted alarm tuzağı: Ayın ilk günlerinde forecast alarmları çok hassas olabilir. AWS, az veriyle yüksek tahminler yapabilir. Bu yüzden forecasted alarmları sadece %100 üzeri için kurun, %80 gibi düşük bir eşikte kurarsanız ay başında her seferinde gereksiz alarm alırsınız.
Vergi dahil mi değil mi: IncludeTax: true ayarına dikkat edin. Bazı bölgelerde vergi %20’ye kadar çıkabilir. Budget limitinizi belirlerken bunu hesaba katın veya vergiyi dışarıda bırakın ve buna göre limit koyun.
Çok fazla budget sorunu: AWS hesabı başına 20.000 budget limiti var gibi görünse de iyi bir organizasyon için öneri şudur: Her ortam için bir genel budget, her kritik servis için birer servis budget’ı ve her büyük proje için tag bazlı birer budget kurun. 20-30 budget zaten çoğu organizasyon için fazlasıyla yeterlidir.
E-posta subscription onayı: Budget oluşturduktan sonra e-posta adreslerine onay maili gider. Bu onay tıklanmazsa bildirimler gelmez. Yeni ekip üyeleri eklediğinizde bunu hatırlatın.
Multi-Account Organizasyonlarda Budget Yönetimi
Eğer AWS Organizations kullanıyorsanız, master account üzerinden tüm organizasyon için budget kurabilirsiniz. Bu, merkezi maliyet kontrolü açısından çok değerlidir.
# Organizations'daki linked account'lar icin budget
cat > org-linked-budget.json << 'EOF'
{
"BudgetName": "linked-account-dev-cost",
"BudgetLimit": {
"Amount": "200",
"Unit": "USD"
},
"TimeUnit": "MONTHLY",
"BudgetType": "COST",
"CostFilters": {
"LinkedAccount": ["123456789012", "987654321098"]
}
}
EOF
LinkedAccount filtresi ile sadece belirli member account’ların harcamalarını takip edebilirsiniz. Bu özellikle developer hesaplarını ayrı tuttuğunuzda işe yarar.
Sonuç
AWS Budgets, cloud maliyetlerini kontrol altına almanın en basit ve etkili yoludur. Aylık 100 dolarlık basit bir alarm bile sizi büyük sürprizlerden koruyabilir. Kurulumu bir kez yaparsınız, sonrasında arka planda çalışmaya devam eder.
Bugün yapmanız gerekenleri özetleyeyim:
- Genel aylık maliyet için bir budget kurun, hem gerçek hem tahmin alarmı ekleyin
- En çok harcama yaptığınız 2-3 servis için ayrı servis bazlı budget’lar ekleyin
- Kaynaklarınızı Environment ve Project tag’leriyle işaretleyin, tag bazlı budget’larla ortam bazında takip edin
- Budget alarmlarını sadece e-postayla bırakmayın, SNS üzerinden Slack veya PagerDuty’ye bağlayın
- Budget kurulumlarınızı Terraform gibi IaC araçlarıyla yönetin, hesap değişikliklerinde tekrar kurabilin
Cloud maliyetleri kontrol edilmezse sessiz sedasız büyür. AWS Budgets bu sessizliği kıran sistemdir. Kurmak 10 dakika alır, kurtarduğu para ise çok daha fazlasına değer.
