Azure Management Groups ile Çoklu Abonelik Yönetimi

Onlarca abonelik, yüzlerce kaynak grubu, farklı ekipler ve farklı bütçeler… Büyük kurumsal ortamlarda Azure yönetimi bir noktadan sonra gerçek bir kaosa dönüşebilir. İşte tam bu noktada Azure Management Groups devreye giriyor ve sana “hepsini tek yerden yönet” demek yerine, gerçekten işe yarayan bir hiyerarşi sunuyor.

Bu yazıda Management Groups’u sıfırdan kurumsal ölçekte nasıl kullanacağını, policy atamalarını, RBAC stratejilerini ve maliyet yönetimi entegrasyonunu gerçek dünya senaryolarıyla anlatacağım.

Management Groups Nedir ve Neden Gerekli?

Azure’da işe yeni başlayan birinin tek bir aboneliği olur, her şeyi orada çalıştırır ve hayat güzeldir. Sonra şirket büyür, compliance gereksinimleri gelir, farklı departmanlar ayrı abonelik ister, bir de bakarsın elinizde 30-40 abonelik var ve her birini ayrı ayrı yönetiyorsunuz.

Management Groups, abonelikleri ve diğer management group’ları hiyerarşik olarak organize etmeni sağlayan bir kapsayıcı yapısıdır. Policy, RBAC ve maliyet yönetimi gibi ayarları bu hiyerarşinin herhangi bir düzeyine uygulayabilirsin ve bu ayarlar altındaki tüm abonelikler için geçerli olur.

Yapının temel özellikleri:

  • Root Management Group: Her Azure AD tenant’ı için otomatik oluşturulur, tüm yapının tepesindedir
  • 6 seviye derinlik: Root hariç 6 seviye management group iç içe geçirebilirsin
  • Kalıtım (inheritance): Üst seviyede atanan policy ve RBAC roller alt seviyelere otomatik kalıtılır
  • 10.000 management group: Tek bir tenant altında bu kadar group oluşturabilirsin
  • Bir abonelik, bir parent: Her abonelik sadece bir management group altında olabilir

Tipik Kurumsal Hiyerarşi Tasarımı

Gerçek bir senaryo üzerinden gidelim. Diyelim ki orta ölçekli bir fintech şirketindesin. Şirketin şu departmanlara sahip:

  • Yazılım geliştirme ekibi (dev, test, prod ortamları)
  • Veri analitiği ekibi
  • Güvenlik ve compliance ekibi
  • Finans ve operasyon

Bu durumda önerilen hiyerarşi şöyle olabilir:

Root Management Group (Tenant Seviyesi)
├── Platform MG
│   ├── Identity Subscription
│   ├── Connectivity Subscription
│   └── Management Subscription
├── Landing Zones MG
│   ├── Corp MG
│   │   ├── Dev Subscription
│   │   ├── Test Subscription
│   │   └── Prod Subscription
│   ├── DataAnalytics MG
│   │   ├── Analytics-Dev Subscription
│   │   └── Analytics-Prod Subscription
│   └── Finance MG
│       └── Finance-Prod Subscription
└── Sandbox MG
    └── Developer-Sandbox Subscriptions

Bu yapı Microsoft’un Azure Landing Zone mimarisinden ilham alıyor ve production’da gerçekten işe yarıyor.

Azure CLI ile Management Group Kurulumu

Teoriden pratiğe geçelim. Azure CLI ile management group hiyerarşisini sıfırdan nasıl kurarsın:

# Azure CLI ile login
az login
az account set --subscription "Management-Subscription-ID"

# Root Management Group ID'sini öğren
az account management-group list --query "[?displayName=='Tenant Root Group'].id" -o tsv

# Ana management group'ları oluştur
az account management-group create 
  --name "mg-platform" 
  --display-name "Platform" 
  --parent "tenant-root-group-id"

az account management-group create 
  --name "mg-landing-zones" 
  --display-name "Landing Zones" 
  --parent "tenant-root-group-id"

az account management-group create 
  --name "mg-sandbox" 
  --display-name "Sandbox" 
  --parent "tenant-root-group-id"

# Alt management group'ları oluştur
az account management-group create 
  --name "mg-corp" 
  --display-name "Corp" 
  --parent "mg-landing-zones"

az account management-group create 
  --name "mg-data-analytics" 
  --display-name "Data Analytics" 
  --parent "mg-landing-zones"

# Mevcut aboneliği management group'a taşı
az account management-group subscription add 
  --name "mg-corp" 
  --subscription "prod-subscription-id"

PowerShell ile Toplu Abonelik Yönetimi

Bazen onlarca aboneliği bir anda taşıman ya da listelemen gerekir. PowerShell burada çok daha esnek:

# Az module ile bağlan
Connect-AzAccount
Import-Module Az.Resources

# Tüm management group'ları hiyerarşik listele
function Get-ManagementGroupHierarchy {
    param(
        [string]$ManagementGroupId,
        [int]$Depth = 0
    )
    
    $mg = Get-AzManagementGroup -GroupId $ManagementGroupId -Expand -Recurse
    $indent = "  " * $Depth
    
    Write-Host "$indent[$($mg.DisplayName)] - ID: $($mg.Name)"
    
    foreach ($child in $mg.Children) {
        if ($child.Type -eq "/providers/Microsoft.Management/managementGroups") {
            Get-ManagementGroupHierarchy -ManagementGroupId $child.Name -Depth ($Depth + 1)
        } else {
            Write-Host "$indent  -> Subscription: $($child.DisplayName)"
        }
    }
}

# Root group ID'ni buraya yaz
Get-ManagementGroupHierarchy -ManagementGroupId "your-tenant-id"

# Belirli bir management group altındaki tüm abonelikleri getir
$subscriptions = Get-AzManagementGroupSubscription -GroupId "mg-corp"
foreach ($sub in $subscriptions) {
    Write-Host "Subscription: $($sub.DisplayName) - ID: $($sub.Id)"
}

# Aboneliği yeni management group'a taşı
New-AzManagementGroupSubscription -GroupId "mg-landing-zones" -SubscriptionId "target-subscription-id"

Azure Policy ile Güvenlik Standartlarını Zorunlu Kılmak

Management Groups’un en güçlü yanlarından biri policy atamasıdır. Bir policy’yi management group seviyesinde atarsan, altındaki tüm abonelikler ve kaynak grupları için geçerli olur.

Gerçek bir senaryo: Tüm corp aboneliklerinde “belirli region’lar dışında kaynak oluşturulamaz” kuralını zorunlu kılmak istiyorsun.

# Mevcut built-in policy tanımlarını listele
az policy definition list 
  --query "[?policyType=='BuiltIn'].{Name:displayName, ID:name}" 
  -o table | grep -i "location"

# Allowed Locations policy'sini management group seviyesinde ata
az policy assignment create 
  --name "allowed-locations-corp" 
  --display-name "Corp - Izin Verilen Lokasyonlar" 
  --policy "e56962a6-4747-49cd-b67b-bf8b01975c4c" 
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp" 
  --params '{
    "listOfAllowedLocations": {
      "value": ["westeurope", "northeurope", "germanywestcentral"]
    }
  }' 
  --enforcement-mode Default

# Policy atamalarını listele
az policy assignment list 
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp" 
  --query "[].{Name:displayName, Policy:policyDefinitionId}" 
  -o table

Özel Policy Tanımı Oluşturmak

Built-in policy’ler her zaman yetmez. Kendi policy’ni yazman gerekebilir. Örneğin, tüm VM’lerin belirli bir tag şemasına sahip olmasını zorunlu kılalım:

{
  "mode": "Indexed",
  "displayName": "Zorunlu Tag Seti - VM Kaynaklar",
  "description": "Tum VM kaynaklarinda Environment, Owner ve CostCenter tag bulunmalidir",
  "parameters": {
    "environment": {
      "type": "String",
      "allowedValues": ["prod", "test", "dev", "sandbox"]
    }
  },
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Compute/virtualMachines"
        },
        {
          "anyOf": [
            {
              "field": "tags['Environment']",
              "exists": false
            },
            {
              "field": "tags['Owner']",
              "exists": false
            },
            {
              "field": "tags['CostCenter']",
              "exists": false
            }
          ]
        }
      ]
    },
    "then": {
      "effect": "deny"
    }
  }
}
# Bu policy'yi yükle ve management group'a ata
az policy definition create 
  --name "require-vm-tags" 
  --display-name "Zorunlu VM Tag Seti" 
  --description "VM'lerde Environment, Owner ve CostCenter tag zorunluluğu" 
  --rules ./vm-tag-policy.json 
  --mode Indexed 
  --management-group "mg-corp"

az policy assignment create 
  --name "require-vm-tags-corp" 
  --policy "/providers/Microsoft.Management/managementGroups/mg-corp/providers/Microsoft.Authorization/policyDefinitions/require-vm-tags" 
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp" 
  --params '{"environment": {"value": "prod"}}'

RBAC Stratejisi: Doğru Rolle Doğru Seviyede Erişim

Management Groups ile RBAC kullanımı, “en az yetki” prensibini uygulamanın en temiz yoludur.

# Güvenlik ekibine tüm landing zones için Security Reader rolü ver
New-AzRoleAssignment `
  -ObjectId "security-team-group-object-id" `
  -RoleDefinitionName "Security Reader" `
  -Scope "/providers/Microsoft.Management/managementGroups/mg-landing-zones"

# DevOps ekibine sadece Corp/Dev aboneliği üzerinde Contributor rolü ver
New-AzRoleAssignment `
  -ObjectId "devops-team-object-id" `
  -RoleDefinitionName "Contributor" `
  -Scope "/subscriptions/dev-subscription-id"

# Platform ekibine tüm abonelikler için Owner rolü ver (yalnızca platform MG altında)
New-AzRoleAssignment `
  -ObjectId "platform-team-object-id" `
  -RoleDefinitionName "Owner" `
  -Scope "/providers/Microsoft.Management/managementGroups/mg-platform"

# Mevcut rol atamalarını management group seviyesinde listele
Get-AzRoleAssignment -Scope "/providers/Microsoft.Management/managementGroups/mg-landing-zones" |
  Select-Object DisplayName, RoleDefinitionName, SignInName, Scope |
  Format-Table -AutoSize

Maliyet Yönetimi Entegrasyonu

Management Groups, Azure Cost Management ile mükemmel entegre çalışır. Hiyerarşi üzerinden maliyet görünürlüğü elde etmek için:

# Management group seviyesinde budget oluştur
az consumption budget create 
  --budget-name "corp-monthly-budget" 
  --amount 50000 
  --time-grain Monthly 
  --start-date 2024-01-01 
  --end-date 2025-12-31 
  --category Cost 
  --resource-group-filter "" 
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp"

# Alert threshold ayarla (%80 ve %100 kullanımında bildirim)
az consumption budget create 
  --budget-name "corp-monthly-budget-with-alert" 
  --amount 50000 
  --time-grain Monthly 
  --start-date 2024-01-01 
  --end-date 2025-12-31 
  --category Cost 
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp" 
  --notifications '{
    "actual_GreaterThan_80Percent": {
      "enabled": true,
      "operator": "GreaterThan",
      "threshold": 80,
      "contactEmails": ["[email protected]", "[email protected]"],
      "thresholdType": "Actual"
    },
    "actual_GreaterThan_100Percent": {
      "enabled": true,
      "operator": "GreaterThan",
      "threshold": 100,
      "contactEmails": ["[email protected]"],
      "thresholdType": "Actual"
    }
  }'

Terraform ile Infrastructure as Code Yaklaşımı

Manuel portal veya CLI işlemleri bir noktada sürdürülemez hale gelir. Management Groups yapını Terraform ile kod olarak yönetmek çok daha sağlıklı:

# variables.tf
variable "tenant_id" {
  description = "Azure AD Tenant ID"
  type        = string
}

variable "root_management_group_id" {
  description = "Root Management Group ID (genellikle tenant ID ile aynı)"
  type        = string
}

# management_groups.tf
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

# Platform Management Group
resource "azurerm_management_group" "platform" {
  name         = "mg-platform"
  display_name = "Platform"
  parent_management_group_id = "/providers/Microsoft.Management/managementGroups/${var.root_management_group_id}"
}

# Landing Zones Management Group
resource "azurerm_management_group" "landing_zones" {
  name         = "mg-landing-zones"
  display_name = "Landing Zones"
  parent_management_group_id = "/providers/Microsoft.Management/managementGroups/${var.root_management_group_id}"
}

# Corp Management Group (Landing Zones altında)
resource "azurerm_management_group" "corp" {
  name         = "mg-corp"
  display_name = "Corp"
  parent_management_group_id = azurerm_management_group.landing_zones.id
}

# Sandbox Management Group
resource "azurerm_management_group" "sandbox" {
  name         = "mg-sandbox"
  display_name = "Sandbox"
  parent_management_group_id = "/providers/Microsoft.Management/managementGroups/${var.root_management_group_id}"
}

# Allowed Locations Policy Assignment
resource "azurerm_management_group_policy_assignment" "allowed_locations" {
  name                 = "allowed-locations"
  management_group_id  = azurerm_management_group.corp.id
  policy_definition_id = "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c"
  display_name         = "Corp - Izin Verilen Lokasyonlar"
  
  parameters = jsonencode({
    listOfAllowedLocations = {
      value = ["westeurope", "northeurope", "germanywestcentral"]
    }
  })
}

# Security Reader Role Assignment for Security Team
resource "azurerm_role_assignment" "security_reader" {
  scope                = azurerm_management_group.landing_zones.id
  role_definition_name = "Security Reader"
  principal_id         = var.security_team_object_id
}

Policy Compliance Durumunu İzlemek

Policy atadıktan sonra işin bitmediğini biliyorsun. Compliance durumunu düzenli izlemen gerekir:

# Management group altındaki tüm policy compliance durumunu getir
az policy state list 
  --management-group "mg-corp" 
  --filter "complianceState eq 'NonCompliant'" 
  --query "[].{
    Resource: resourceId,
    Policy: policyDefinitionId,
    State: complianceState,
    Timestamp: timestamp
  }" 
  --output table

# Compliance özetini al
az policy state summarize 
  --management-group "mg-corp" 
  --query "{
    Total: results.resourceDetails[?complianceState=='noncompliant'].count | [0],
    Compliant: results.resourceDetails[?complianceState=='compliant'].count | [0]
  }"

# Remediation task oluştur (deployIfNotExists policy'leri için)
az policy remediation create 
  --name "vm-tag-remediation-$(date +%Y%m%d)" 
  --management-group "mg-corp" 
  --policy-assignment "require-vm-tags-corp" 
  --resource-discovery-mode ReEvaluateCompliance

Gerçek Dünya Senaryosu: Güvenlik İhlali Sonrası Hızlı Müdahale

Diyelim ki güvenlik ekibin bir abonelikte şüpheli aktivite tespit etti ve tüm corp ortamında belirli VM boyutlarını hemen kısıtlaman gerekiyor. Management Groups olmadan her aboneliğe tek tek girmek zorunda kalırsın. Management Groups ile:

# Anında tüm corp aboneliklerine VM SKU kısıtlaması uygula
POLICY_ID="cccc23c7-8427-4f31-a4b0-e444226ed5d4"  # Allowed VM SKUs policy

az policy assignment create 
  --name "emergency-vm-sku-restriction" 
  --display-name "ACIL: VM SKU Kisitlamasi" 
  --policy "$POLICY_ID" 
  --scope "/providers/Microsoft.Management/managementGroups/mg-corp" 
  --enforcement-mode Default 
  --params '{
    "listOfAllowedSKUs": {
      "value": [
        "Standard_B1s",
        "Standard_B2s", 
        "Standard_D2s_v3",
        "Standard_D4s_v3"
      ]
    }
  }'

echo "Policy atandı. Compliance durumu birkaç dakika içinde güncellenecek."

# Sandbox ortamına deny effect yerine audit modunda uygula
az policy assignment create 
  --name "audit-vm-sku-sandbox" 
  --display-name "Audit: VM SKU Kontrolu" 
  --policy "$POLICY_ID" 
  --scope "/providers/Microsoft.Management/managementGroups/mg-sandbox" 
  --enforcement-mode DoNotEnforce 
  --params '{
    "listOfAllowedSKUs": {
      "value": ["Standard_B1s", "Standard_B2s"]
    }
  }'

Bu komutla 5 dakikadan kısa sürede tüm corp ortamın güvence altına alınmış olur. Eski dünyada bu işlem saatler alırdı.

Dikkat Edilmesi Gereken Noktalar

Management Groups kurarken sıkça karşılaşılan sorunlar ve çözümleri:

  • Root Management Group erişimi: Global Admin rolü Management Groups için otomatik yetki vermez. “Tenant Root Group” üzerinde ayrıca “User Access Administrator” rolü atamanız gerekebilir. Bunu Azure Portal > Azure AD > Properties > Access management for Azure resources ayarından yapabilirsin.
  • Policy kalıtımı geri alınamaz mı?: Üst seviyede atanan policy’yi alt seviyede “disable” edemezsin, ama exemption oluşturabilirsin. Sandbox ortamı için sıkça kullanılan bir pattern.
  • Management group silme sorunu: Altında abonelik veya child management group bulunan bir group’u silemezsin. Önce bunları başka bir group’a taşıman gerekir.
  • Deployment gecikmesi: Management group seviyesinde yapılan policy atamaları 30-60 dakika içinde tüm kaynaklara yayılır. Hemen compliance görmek bekleme.
  • Terraform state yönetimi: Management Groups Terraform ile yönetirken state dosyasını güvenli bir backend’de (Azure Blob Storage) tutmayı unutma. Yanlış bir terraform destroy felakete yol açabilir.
  • Naming convention: Management group isimlerinde Türkçe karakter kullanma, küçük harf ve tire ile devam et. Sonradan değiştirmek çok zahmetli.

Sonuç

Azure Management Groups, kurumsal ölçekteki çoklu abonelik ortamlarının yönetimini gerçekten basitleştiren ve standardize eden bir yapı sunuyor. Tek bir policy atamasıyla onlarca aboneliği etkileyen güvenlik kuralları koyabilmek, maliyet görünürlüğünü hiyerarşik olarak sağlamak ve RBAC’ı merkezi bir noktadan kontrol etmek… Bunlar Management Groups’un somut faydaları.

Ancak bu yapıyı kurarken acele etme. Hiyerarşiyi kağıt üzerinde tasarla, ekiplerin ihtiyaçlarını dinle ve yavaş yavaş büyüt. İlk kurduğun yapıyı değiştirmek zahmetlidir, ama imkansız değil. Özellikle Terraform gibi bir IaC aracıyla tüm yapını kod olarak yönetmek, ileride yapacağın değişiklikleri çok daha güvenli hale getirir.

Son olarak şunu söyleyeyim: Management Groups’u kurmak bir proje değil, bir pratik. Küçük bir pilot management group ile başla, birkaç policy dene, compliance raporlarına bak ve sonra kurumsal yapına doğru genişlet. Doğru kurulduğunda, sabahın 3’ünde güvenlik ihlali için tüm aboneliklere tek tek girmek zorunda kalmaktan kurtulursun.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir