Fluffy white clouds against a bright blue sky. — Azure Container Apps: Sunucusuz Konteyner Yönetimi.

Kahramanmaraş merkezli 32 kişilik bir B2B fintech startup, Series A öncesi AKS cluster’ını yönetme yükünden kurtulmak istedi. 14 microservice’i 3 ayda Azure Container Apps’e taşıdı. Sonuç: aylık maliyet $1.840 → $960 (%48 düşüş), DevOps zamanı %35 azalma, scale-to-zero ile gece/hafta sonu maliyet sıfır. Bu yazı sahadaki teknik notlar.

Container Apps vs AKS Karar Matrisi

Boyut AKS Container Apps
Kontrol seviyesi Tam (kubectl, Helm, custom CRD) Sınırlı (managed)
Yönetim yükü Yüksek (cluster, node, upgrade) Sıfır
Scaling HPA + Cluster Autoscaler KEDA (HTTP, queue, custom)
Scale-to-zero Hayır (default) Evet (KEDA)
Cold start ~~yok (warm pod) ~~1-3 sn (cold start)
Service mesh Istio, Linkerd Dapr (built-in)
Min cost ~~$200/ay (system node) ~~$0 (scale-to-zero)
İdeal use case Karmaşık platform, çok sayıda team Microservice, async worker, Dapr-friendly

14 microservice + küçük DevOps ekibi → Container Apps açık kazanç.

Workload Profiles

Container Apps Environment 2 workload profile ile:

  • Consumption: Tüm API’ler ve worker’lar (auto-scale, scale-to-zero)
  • Dedicated D4 (1 instance): ML inference servisi (warm tutulması lazım)
az containerapp env create -g rg-fintech -n cae-prod 
  --location northeurope 
  --infrastructure-subnet-resource-id /subscriptions/.../subnets/cae-subnet 
  --internal-only false 
  --enable-workload-profiles

az containerapp env workload-profile add 
  --resource-group rg-fintech --name cae-prod 
  --workload-profile-name dedicated-d4 
  --workload-profile-type D4 
  --min-nodes 1 --max-nodes 1

Container App Tanımı

properties:
  managedEnvironmentId: /subscriptions/.../containerEnvironments/cae-prod
  workloadProfileName: Consumption
  configuration:
    ingress:
      external: true
      targetPort: 8080
      traffic:
        - revisionName: api-payment--v1.4.2
          weight: 100
    secrets:
      - name: db-connection
        keyVaultUrl: https://kv-fintech.vault.azure.net/secrets/db-conn
        identity: system
    dapr:
      enabled: true
      appId: payment-api
      appPort: 8080
  template:
    containers:
      - name: api
        image: fintech.azurecr.io/payment-api:1.4.2
        resources:
          cpu: 0.5
          memory: 1Gi
        env:
          - name: DB_CONNECTION
            secretRef: db-connection
    scale:
      minReplicas: 0
      maxReplicas: 30
      rules:
        - name: http-rule
          http:
            metadata: { concurrentRequests: "100" }
        - name: queue-rule
          custom:
            type: azure-servicebus
            metadata:
              queueName: payment-queue
              messageCount: "20"
            auth:
              - secretRef: sb-conn
                triggerParameter: connection

Dapr ile Microservice Communication

14 servis arasındaki çağrılar Dapr service invocation üzerinden:

// payment-api'den order-api'ye çağrı
var client = new DaprClientBuilder().Build();
var order = await client.InvokeMethodAsync<Order>(
    HttpMethod.Get,
    "order-api",        // Dapr app ID
    $"orders/{orderId}");

Dapr otomatik mTLS, retry policy, circuit breaker, observability sağlıyor.

Pub/Sub with Dapr + Service Bus

# Dapr component (Service Bus pub/sub)
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
  name: pubsub
spec:
  type: pubsub.azure.servicebus.queues
  version: v1
  metadata:
    - name: connectionString
      secretKeyRef: { name: sb-conn, key: sb-conn }
// Publish
await client.PublishEventAsync("pubsub", "payment-completed", paymentEvent);

// Subscribe (controller)
[Topic("pubsub", "payment-completed")]
[HttpPost("payment-completed")]
public async Task<IActionResult> OnPaymentCompleted(PaymentEvent evt)
{
    await _orderService.MarkPaidAsync(evt.OrderId);
    return Ok();
}

Revisions ve Blue/Green Deployment

Yeni versiyon deploy edildiğinde önceki revision çalışmaya devam ediyor. Traffic kademeli yönlendirilir:

# Yeni revision deploy (traffic 0)
az containerapp update -g rg-fintech -n payment-api 
  --image fintech.azurecr.io/payment-api:1.4.3 
  --revision-suffix v1-4-3

# Trafik yönlendirme: %20 yeni
az containerapp ingress traffic set -g rg-fintech -n payment-api 
  --revision-weight payment-api--v1-4-2=80 payment-api--v1-4-3=20

# Doğrulama → %100 yeni
az containerapp ingress traffic set -g rg-fintech -n payment-api 
  --revision-weight payment-api--v1-4-3=100

KEDA Scaling Rules

Service Scaling rule Min/Max
payment-api HTTP (100 req/replica) 0-30
order-worker Service Bus queue (20 msg) 0-15
notification-worker Service Bus queue (50 msg) 0-8
kyc-processor Cron + queue 0-5
ml-inference HTTP (10 req/replica) 1-4 (warm tutmak için min 1)

Maliyet Karşılaştırması

Kalem AKS (önce) Container Apps (sonra)
Cluster (system + user nodes) $1.420
Container Apps Environment (Consumption) $420
Workload profile D4 (1 dedicated) $280
Log Analytics + App Insights $220 $180
Container Registry $60 $60
Storage + Service Bus $140 $120
Toplam $1.840 $960

%48 tasarruf. Sebep: 14 servisin %60’ı gece + hafta sonu scale-to-zero. AKS’de cluster ayakta kalıyor (idle bile olsa ödüyorsun).

Sahada Düşülen Üç Tuzak

  1. Scale-to-zero’yu cold start kabul etmeden uygulamak: 1-3 sn cold start latency-critical API’de fark edilir. Müşteri-facing API’lere min 1 replica.
  2. Container size’ı küçük tutmak: 0.25 CPU + 0.5 GB ile bazı .NET app yavaş başlıyor. Profile + uygun size.
  3. Dapr learning curve’ünü hafife almak: Service invocation + pub/sub + state management config’i Day 1 kolay değil. Pilot servis ile öğrenilmeli.

CloudSpark olarak Azure Container Apps deployment, AKS → Container Apps migration, Dapr entegrasyonu ve KEDA-based autoscaling projeleri için danışmanlık veriyoruz.

🇹🇷 Türkçe🇬🇧 English🇩🇪 Deutsch🇫🇷 Français🇸🇦 العربية🇷🇺 Русский🇪🇸 Español