kertenkerem_
· DevOps · 5 dk okuma

Ephemeral Environment’larda ‘Token Budget’ Yönetimi: Otomasyon Giderlerini Kontrol Altına Alın

PR bazlı preview ya da ephemeral environment altyapıları kurmak artık sektörde standart. Ancak işin içine kod analiz eden, sentetik test verisi üreten veya migrasyon doğrulayan otonom AI ajanları girince, kontrolsüz otomasyon bulut maliyeti grafiklerini saatler içinde darmadağın edebiliyor. Sonsuz döngüye giren bir agent’ın ephemeral pipeline içinde OpenAI veya Anthropic faturalarını tüketmesini izlemek istemiyorsanız, CI/CD hattınıza deterministik bir token budget mekanizması koymanız gerekiyor.

Bu yazıda geçici ortamlarda koşan AI iş yükleri için in-line bir “Token Gate” mimarisinin nasıl kurulacağını anlatıyorum. PR yaşam döngüsüyle senkronize bütçe tahsisine ve acil durum devre kesicilerine (circuit breaker) de değiniyorum.

FinOps uyarıları neden CI/CD hızına yetişemiyor?

Geleneksel FinOps araçları ve cloud provider fatura alarmları post-mortem çalışır. AWS Cost Anomaly Detection veya OpenAI Usage Webhook’ları genelde saatlik ya da günlük batch gecikmelerle tetiklenir. Oysa bir GitHub Actions runner’ı üzerinde koşan ve hatalı bir prompt yüzünden recursive döngüye giren bir test ajanı, 25 dakikalık bir test koşumunda yüz binlerce token tüketip 400 doları sessizce harcayabilir.

Sorun yalnızca faturanın kabarması değil, ephemeral environment’ın doğası gereği geçici olması. PR kapandığında pod’lar silinir, namespace yok edilir, geriye LLM provider panelinde nedeni belirsiz büyük bir kullanım grafiği kalır. Bu yüzden bütçe denetimini harici bir fatura kontrolü olarak değil, deployment pipeline’ının içine gömülü bir gatekeeper olarak konumlandırmalıyız.

Mimari: proxy tabanlı Token Gate

Agent’ların doğrudan public LLM API’lerine gitmesi en büyük governance hatasıdır. Bu yüzden ajan ile LLM arasına hafif, stateless’a yakın bir proxy katmanı koyuyoruz. Açık kaynaklı LiteLLM Proxy ya da Envoy tabanlı bir custom egress filter kullanabiliriz. Ben prodüksiyonda kendini kanıtlamış Redis destekli LiteLLM Proxy modelini baz alacağım.

Model şöyle işler:

  1. CI pipeline başladığında ephemeral environment ID’si (örn. pr-842) için proxy üzerinde tek kullanımlık bir Virtual Key üretilir.
  2. Bu key’e izole bir harcama limiti (max spend) ve TTL atanır.
  3. Ephemeral environment içindeki tüm agent’lar ve otomasyon araçları LLM endpoint’i olarak bu proxy’yi görür.
  4. Bütçe tükendiği anda proxy doğrudan 429 BudgetExceeded döner. Pipeline runner’ı kilitlemeden, kontrollü bir exit code ile fail eder.
  5. PR merge veya close olduğunda key ve ilişkili Redis state’i tamamen silinir.

Adım 1: LiteLLM Proxy ve Redis konfigürasyonu

Önce proxy katmanını Kubernetes üzerinde ya da CI cluster’ınızın ortak tooling namespace’inde ayağa kaldırıyoruz. Aşağıdaki konfigürasyon harcama verilerini Redis’te tuttuğu için stateless proxy instance’ları birbiriyle tam senkron çalışır.

# config.yaml
model_list:
  - model_name: claude-3-5-sonnet
    litellm_params:
      model: anthropic/claude-3-5-sonnet-20241022
      api_key: os.environ/ANTHROPIC_API_KEY
  - model_name: gpt-4o-mini
    litellm_params:
      model: openai/gpt-4o-mini
      api_key: os.environ/OPENAI_API_KEY

general_settings:
  master_key: sk-master-infra-gatekeeper-key
  database_url: "redis://redis-sentinel.infra.svc.cluster.local:6379"

router_settings:
  routing_strategy: "least-busy"
  timeout: 30

Proxy’yi Docker üzerinde ayağa kaldırmak için:

docker run -d \
  -p 4000:4000 \
  -v $(pwd)/config.yaml:/app/config.yaml \
  -e ANTHROPIC_API_KEY="sk-ant-live-xxxx" \
  -e OPENAI_API_KEY="sk-proj-live-xxxx" \
  ghcr.io/berriai/litellm:main-v1.49.0 \
  --config /app/config.yaml --port 4000

Adım 2: CI pipeline ile dinamik Token Gate entegrasyonu

Şimdi GitHub Actions veya GitLab CI pipeline’ımızda her preview environment için dinamik bir anahtar üreteceğiz. Her PR için varsayılan tavan bütçeyi 2.50 USD olarak tanımlıyoruz. Testler bu bütçeyi aşarsa pipeline derhal kesilir ve faturaya sürpriz yansımaz.

# .github/workflows/ephemeral-env.yml (Özet Adım)
- name: Provision Ephemeral LLM Token Gate Key
  id: token_gate
  env:
    PROXY_MASTER_KEY: ${{ secrets.LLM_PROXY_MASTER_KEY }}
    PROXY_HOST: "https://llm-gateway.internal.kertenkerem.net"
  run: |
    PR_ID="pr-${{ github.event.pull_request.number }}"
    
    # 2.50$ bütçe ve 2 saatlik TTL ile dinamik key oluştur
    RESPONSE=$(curl -s -X POST "$PROXY_HOST/key/generate" \
      -H "Authorization: Bearer $PROXY_MASTER_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "duration": "2h",
        "max_budget": 2.50,
        "metadata": {
          "environment": "'"$PR_ID"'",
          "actor": "${{ github.actor }}",
          "repo": "${{ github.repository }}"
        }
      }')

    EPHEMERAL_KEY=$(echo $RESPONSE | jq -r '.key')
    
    if [ "$EPHEMERAL_KEY" == "null" ] || [ -z "$EPHEMERAL_KEY" ]; then
      echo "::error::Token Gate anahtarı oluşturulamadı!"
      exit 1
    fi

    # Maskele ve env'ye aktar
    echo "::add-mask::$EPHEMERAL_KEY"
    echo "EPHEMERAL_LLM_KEY=$EPHEMERAL_KEY" >> $GITHUB_ENV
    echo "LLM_BASE_URL=$PROXY_HOST" >> $GITHUB_ENV

Bu adımdan sonra ayağa kalkan ephemeral deployment pod’larına ve otomasyon agent’larına yalnızca şu iki parametre enjekte edilir:

  • OPENAI_BASE_URL: https://llm-gateway.internal.kertenkerem.net
  • OPENAI_API_KEY: ${{ env.EPHEMERAL_LLM_KEY }}

Adım 3: Degraded mode ve circuit breaker mantığı

Token bütçesi tükendiğinde pipeline’ın anında kırılması her zaman istenen bir şey değildir. Özellikle kritik entegrasyon testlerinde ana agent, maliyetli bir modelden (örn. Claude 3.5 Sonnet) daha ucuz bir modele (örn. GPT-4o-mini) “fallback” yapabilmelidir.

Proxy seviyesinde, bütçe tükenmeden hemen önce devreye giren bir model alias stratejisi kullanabilirsiniz. Agent kodunuz bu hatayı ele alacak kadar esnek değilse, test framework’ünüzün curl/HTTP wrapper’ına basit bir circuit breaker mantığı eklemek en güvenli yoldur:

#!/usr/bin/env bash
# run-agent-eval.sh
set -eo pipefail

echo "Starting evaluation agent in ephemeral namespace..."

# Agent'ı çalıştır ve HTTP status kodlarını kontrol et
if ! python3 -m agents.evaluator --target-env http://frontend.pr-${PR_ID}.svc.local; then
  EXIT_CODE=$?
  
  # Proxy'nin budget aşım loglarını sorgula
  CURRENT_SPEND=$(curl -s -X GET "$LLM_BASE_URL/key/info?key=$EPHEMERAL_LLM_KEY" \
    -H "Authorization: Bearer $PROXY_MASTER_KEY" | jq -r '.info.spend')
    
  MAX_BUDGET=$(curl -s -X GET "$LLM_BASE_URL/key/info?key=$EPHEMERAL_LLM_KEY" \
    -H "Authorization: Bearer $PROXY_MASTER_KEY" | jq -r '.info.max_budget')

  echo "Execution failed with code $EXIT_CODE."
  echo "Current Token Spend: \$$CURRENT_SPEND / Max: \$$MAX_BUDGET"

  if (( $(echo "$CURRENT_SPEND >= $MAX_BUDGET" | bc -l) )); then
    echo "CRITICAL: Agent bütçe limitine çarptı. Olası recursive prompt döngüsü tespit edildi."
    echo "PR yazarına bildirim gönderiliyor..."
    exit 42 # FinOps gate violation exit code
  fi

  exit $EXIT_CODE
fi

Adım 4: Ephemeral environment teardown ve muhasebe

Preview ortamları yok edilirken açılan virtual key’lerin revoke edilmesi ve tüketim verisinin kalıcı metrik sunucusuna yazılması gerekir. Çoğu mühendis bu kısmı atlar. Oysa harcamanın hangi PR’da, hangi geliştirici tarafından ve hangi prompt şablonuyla yapıldığını bilmek FinOps optimizasyonunun temelidir.

# PR Close workflow adımında çalıştırılır:
- name: Teardown Token Budget & Export Metrics
  if: always()
  run: |
    # Key kullanım detaylarını topla
    USAGE_DATA=$(curl -s -X GET "$LLM_BASE_URL/key/info?key=$EPHEMERAL_LLM_KEY" \
      -H "Authorization: Bearer $PROXY_MASTER_KEY")
      
    TOTAL_TOKENS=$(echo $USAGE_DATA | jq -r '.info.total_tokens // 0')
    TOTAL_SPEND=$(echo $USAGE_DATA | jq -r '.info.spend // 0')
    
    echo "PR-$PR_ID LLM Kullanım Özeti: $TOTAL_TOKENS token (\$$TOTAL_SPEND)"

    # Prometheus Pushgateway'e metrikleri ilet
    cat <<EOF | curl --data-binary @- http://pushgateway.infra.svc:9091/metrics/job/ephemeral_ci/instance/pr-${{ github.event.pull_request.number }}
    ephemeral_llm_tokens_total{repo="${{ github.repository }}",actor="${{ github.actor }}"} $TOTAL_TOKENS
    ephemeral_llm_cost_usd{repo="${{ github.repository }}",actor="${{ github.actor }}"} $TOTAL_SPEND
    EOF

    # Virtual key'i kalıcı olarak iptal et
    curl -s -X POST "$LLM_BASE_URL/key/delete" \
      -H "Authorization: Bearer $PROXY_MASTER_KEY" \
      -H "Content-Type: application/json" \
      -d '{"keys": ["'"$EPHEMERAL_LLM_KEY"'"]}'

Neden bu mimari?

Bu yaklaşımın üç temel avantajı var:

  1. Blast Radius kısıtlaması: Geliştiricinin yazdığı deneysel bir agent kodu infinite loop’a girse bile maksimum zarar 2.50 USD ile sınırlı kalır. Production key’lerini riske atmazsınız.
  2. Zero-Trust Credential Isolation: Ephemeral pod’lara master API anahtarları hiçbir zaman enjekte edilmez. Pipeline bittiğinde anahtar anında çöpe gider.
  3. Granüler görünürlük: Fatura ay sonunda geldiğinde hangi feature branch’in ne kadar LLM maliyeti yarattığını Prometheus üzerinden nokta atışı görebilirsiniz.

AI destekli CI/CD akışları artık bir lüks değil, hız kazandıran bir zorunluluk. Ama kontrolsüz otomasyon hız kazandırmaz, yalnızca AWS ve OpenAI faturalarınızı katlar. Ephemeral mimarilerinize token budget kapılarını bugünden ekleyin.