Azure • Haberler • Microsoft

Azure’da inference seçenekleri: Mimar gözüyle 6 yol

azure-inference-cover

Azure’da model servis etmenin 6 yolu: Foundry serverless API, Container Apps serverless GPU, managed compute, KAITO, AKS’te vLLM ve Fireworks.

Azure’da bir modeli servis etmenin (inference) tek bir yolu yok. Tamamen yönetilen bir API’den, GPU düğümlerini ve servis motorunu kendiniz kurduğunuz bir AKS kümesine kadar birçok seçenek var. Microsoft for Startups ekibinin Tech Community’de yayımladığı rehber, bu seçenekleri bir mimarın bakış açısıyla karşılaştırıyor ve ilk beşi için çalıştırılabilir örnekler veriyor. Bütün örneklerde aynı Python istemcisi kullanılıyor; değişen tek şey endpoint.

Rehber Ekim 2026 itibarıyla bir anlık görüntü. Azure’ın inference seçenekleri sürekli değiştiği için sayı ileride artabilir.

Altı seçenek, tek tabloda

#SeçenekAzure servisiNeyi servis edebilirGPT, Claude gibi kapalı modeller
1Serverless APIMicrosoft FoundryAzure’ın sattığı Foundry Models (tüm Azure OpenAI modelleri ile DeepSeek, Llama, Grok, Mistral gibi modeller) ve Anthropic gibi seçili partner modelleri✅ Evet, bunları servis eden tek seçenek
2Serverless GPUAzure Container AppsAçık ağırlıklı (OSS) ya da kendi modelleriniz, fine-tune’lar, özel motorlar: container’a koyduğunuz her şey❌ Hayır
3Managed compute (önizleme)Microsoft FoundryFoundry kataloğunun Hugging Face koleksiyonundaki açık, partner ve sektörel modeller ile NVIDIA NIM❌ Hayır
4KAITOAKSKAITO hazır ayarlarındaki açık modeller (Phi, Llama, Mistral, Qwen, DeepSeek gibi) ya da kendi model ve imajınız❌ Hayır
5vLLMAKSSeçtiğiniz motorun desteklediği açık ya da kendi modelleriniz, fine-tune ve quantize edilmiş dosyalar dahil❌ Hayır
6Fireworks on FoundryMicrosoft FoundryKatalogdaki açık modeller ya da uyumlu kendi ağırlıklarınız (fine-tune ve LoRA adaptörleri önizlemede), Fireworks çalışma ortamında❌ Hayır

İlk filtre, neyin servis edilebildiği. GPT ve Claude gibi kapalı modeller yalnızca hizmet olarak sunuluyor (Seçenek 1); ağırlıkları kendiniz çalıştırmanız için hiçbir zaman verilmiyor. Seçenek 2-6 açık ağırlıklı modelleri ya da sahibi olduğunuz ağırlıkları servis ediyor. Kapalı bir frontier modele ihtiyacınız varsa seçim sizin yerinize yapılmış oluyor: tamamen yönetilen PaaS. Açık ya da özel bir model kullanacaksanız, 2-6 arasında ne kadarını işletmek istediğinize ve nasıl ödemek istediğinize göre seçiyorsunuz. Llama ve DeepSeek gibi bazı açık modeller Seçenek 1’de token başına ödemeli Foundry Models olarak da var.

Seçenek 6 karşılaştırma için listede; rehberde çalıştırılabilir bir örneği yok.

Azure'da inference seçenekleri: modeli, çalışma ortamını ve GPU'ları kimin işlettiği ve faturalandırma birimi
Azure’da inference seçenekleri: modeli, çalışma ortamını ve GPU’ları kimin işlettiği ve faturalandırma birimi

Foundry’deki dağıtım seçenekleri

Microsoft Learn’deki dağıtım genel bakışı iki Foundry dağıtım seçeneği tanımlıyor:

  • Serverless API: Azure’ın sattığı Foundry Models ve seçili partner modelleri için önerilen ve en yetenekli yol. Standard, provisioned throughput, batch ve developer dağıtım tiplerini içeriyor.
  • Managed compute (önizleme): Açık kaynak, partner ve özel modelleri Foundry’nin sizin için yönettiği ayrılmış GPU kapasitesinde çalıştırıyor.

Foundry ayrıca desteklenen modelleri herhangi bir dağıtım oluşturmadan adıyla çağırmayı sağlayan “instant access” (önizleme) seçeneği de sunuyor.

Foundry’ye entegre Fireworks on Foundry ise Microsoft’un birinci taraf bir tüketim hizmeti. Katalogdaki açık kaynak modelleri ve içe aktarılan özel ağırlıkları Fireworks’ün kendi inference motoru ve GPU altyapısında çalıştırıyor. Token başına ödemeli Standard dağıtımları ve provisioned throughput’u destekliyor, Azure ölçümleme kullanıyor ve bir abonelik yöneticisinin açıkça etkinleştirmesini gerektiriyor.

Foundry dışında Azure’da model çalıştırmak için iki yer daha var: Container başına GPU’yu Azure’ın verdiği Azure Container Apps serverless GPU ve kümeyi kendinizin işlettiği AKS. Container Apps dokümantasyonu serverless GPU’yu Foundry kataloğunun serverless API’leri ile managed compute arasında “orta katman” bir seçenek olarak tanımlıyor.

Azure resminde nereye oturuyorlar?

Aşağıdaki tablo, managed compute genel bakışındaki Foundry dağıtım tipleri tablosunu rehberin örneklediği Foundry dışı seçeneklerle (➕ ile işaretli) genişletiyor:

Dağıtım tipiServisNe servis ederGPU ve runtime’ı kim işletirFaturalandırmaSıfıra ölçeklemeEn uygun senaryo
Standard (token başına)FoundryAzure’ın sattığı modeller ve seçili partner modelleri; GPT ve Claude dahilMicrosoftGirdi ve çıktı token’ı başınaGerekmiyor (boşta maliyet yok)En kolay başlangıç, dalgalı trafik, kapasite planlaması yok
Provisioned throughput (PTU)FoundrySeçili Azure modelleri, GPT dahilMicrosoftRezerve throughput birimleriHayırÖngörülebilir, sürekli yük ve tutarlı gecikme
Managed compute (önizleme)FoundryYalnızca OSS: katalogdaki açık kaynak ve topluluk modelleriMicrosoft işletir; şablon, hızlandırıcı ve instance sayısını siz seçersinizHızlandırıcı başına saatlik (önizlemede, güncel fiyat için hesaplayıcıya bakın)Hayır (faturayı durdurmak için silin)Ayrılmış GPU’larda, Foundry yönetimli runtime’larla açık modeller
Fireworks on Foundry (Standard ya da PTU)FoundryOSS ya da uyumlu kendi ağırlıklarınız, fine-tune ve LoRA (önizleme)Fireworks, Microsoft’un alt işleyicisi olarak motoru ve GPU’ları işletirToken başına ya da rezerve birimlerStandard’da gerekmiyor; PTU’da hayırYönetilen, optimize runtime ve Azure yönetişimiyle güncel açık modeller
➕ Serverless GPUContainer AppsContainer içinde OSS ya da kendi ağırlıklarınız, Foundry MLflow modelleri (önizleme) dahilGPU’ları Azure işletir; imaj ve runtime sizdeGPU saniyesi + vCPU ve bellekEvetDalgalı ya da aralıklı trafiği olan özel modeller, küme işletmeden
➕ KAITOAKSYalnızca OSS: KAITO hazır ayarları ya da kendi model ve imajınızKAITO düğümü hazırlar ve vLLM’i ayarlar; küme sizdeGPU VM saatiEk kurulumla (KEDA)GPU yığınını elle kurmadan açık model isteyen AKS kullanıcıları
➕ Kendi yönettiğiniz vLLM (ya da başka motor)AKSOSS ya da kendi ağırlıklarınızHer katman sizdeGPU VM saatiEk kurulumla (KEDA)GPU SKU, sürücü, motor, parametreler ve ağ üzerinde tam kontrol

Foundry yolları Foundry proje yönetişimini ve Azure faturalandırmasını kullanıyor. Fireworks on Foundry bir Microsoft hizmeti olarak kalıyor ama istekleri Fireworks kendi GPU altyapısında, Microsoft’un alt işleyicisi (subprocessor) olarak işliyor. ➕ ile işaretli üç seçeneğin her biri ayrı bir endpoint ve işletim modeli getiriyor. OpenAI uyumlu /v1 API sayesinde altı seçeneğin hepsine uygulama tarafından aynı şekilde istek atılıyor.

Ön koşullar

  • Azure CLI 2.60 ya da üstü, giriş yapılmış (az login); 4. ve 5. seçenekler için kubectl.
  • Python 3 ve pip.
  • 2., 4. ve 5. seçenekler için kullandığınız SKU’da GPU kotası. Seçenek 2, VM kotasından ayrı olan Container Apps managed environment GPU kotasını kullanıyor.
  • Seçenek 3 için hızlandırıcı ailesine ait managed compute kotası. Bu kota Foundry kota süreciyle veriliyor ve Azure VM kotasından ayrı.

Ortak değişkenler:

export LOC=southcentralus
export RG=rg-inferencing-demo
export GPU_VM=Standard_NC4as_T4_v3          # options 4 and 5
az group create -n $RG -l $LOC

4. ve 5. seçenekler için üç ayrı kontrol yapın: Seçtiğiniz GPU VM SKU’su hedef bölgede var mı, VM ailesi ve bölgesel vCPU kotanız yeterli mi ve kurumunuzun Azure Policy’si bu SKU’ya izin veriyor mu? 1., 2. ve 3. seçenekler AKS GPU VM kotası kullanmıyor.

Test istemcisi

Bütün örnekler aynı yerel chat.py ile çağrılıyor. Dosya düz openai SDK’sını kullanıyor ve API anahtarını ya da Microsoft Entra ID token’ını destekliyor (OPENAI_API_KEY=entra).

cat <<'EOF' > chat.py
import os
from openai import OpenAI
base = os.environ["OPENAI_BASE_URL"]
key = os.environ.get("OPENAI_API_KEY", "")
if key in ("", "entra", "aad"):
    from azure.identity import DefaultAzureCredential, get_bearer_token_provider
    token = get_bearer_token_provider(DefaultAzureCredential(), "https://ai.azure.com/.default")
    client = OpenAI(base_url=base, api_key=token)
else:
    client = OpenAI()  # key auth: reads OPENAI_BASE_URL + OPENAI_API_KEY
resp = client.chat.completions.create(
    model=os.environ["OPENAI_MODEL"],
    messages=[{"role": "user", "content": "What is Kubernetes, in one sentence?"}],
    max_tokens=64, temperature=0,
)
print(f"[endpoint] {base}")
print(resp.choices[0].message.content)
EOF

Bağımlılıkları kurun:

cat <<'EOF' > requirements.txt
# Dependencies for the local inference client and managed compute deployment.
# openai >= 1.106 is required to pass an Entra token provider as api_key.
openai>=1.106.0
azure-identity>=1.19.0
# Preview management SDK version used by the managed compute how-to.
azure-mgmt-cognitiveservices==15.0.0b2
EOF
python3 -m pip install -r requirements.txt

Her seçenek için kullanılacak değerler:

SeçenekOPENAI_BASE_URLOPENAI_MODELOPENAI_API_KEY
1. Serverless APIhttps://<res>.openai.azure.com/openai/v1/gpt-4.1-minientra
2. Serverless GPUhttps://<app>.<env>.<region>.azurecontainerapps.io/v1phi-3.5-minivLLM anahtarınız
3. Managed computehttps://<account>.services.ai.azure.com/openai/v1/dağıtım adıentra
4. KAITOhttp://localhost:8000/v1 (port-forward)phi-3.5-mini-instructgerekmiyor (kendi barındırmanız)
5. vLLMhttp://localhost:8000/v1 (port-forward)phi-3.5-minigerekmiyor (kendi barındırmanız)

Seçenek 1: Foundry serverless API

En yönetilen seçenek. GPU, imaj ya da runtime görmüyorsunuz; bir model ve dağıtım tipi seçiyor, token başına ödüyorsunuz.

  • Foundry kaynağı: Model dağıtımlarını barındıran AIServices tipinde bir Cognitive Services hesabı.
  • Model dağıtımı: Bir endpoint arkasında, katalogdaki bir modelin adı verilmiş, çağrılabilir örneği.
  • GlobalStandard: Token başına ödemeli kapasite; hazırlanacak bir şey yok.

Adım 1.1: Kaynağı oluşturup model dağıtın. Foundry kaynağınız için global olarak benzersiz bir ad seçin ve her çalıştırmada aynı değeri kullanın:

export AOAI="<your-foundry-resource-name>"
az cognitiveservices account create \
  -n $AOAI -g $RG -l $LOC \
  --kind AIServices --sku S0 \
  --custom-domain $AOAI --yes
# Model versions retire, so list available OpenAI model versions whose names contain 'mini':
az cognitiveservices account list-models -g $RG -n $AOAI \
  --query "[?format=='OpenAI' && contains(name,'mini')].{name:name, version:version}" -o table
az cognitiveservices account deployment create \
  -g $RG -n $AOAI \
  --deployment-name gpt-4.1-mini \
  --model-name gpt-4.1-mini --model-version 2025-04-14 --model-format OpenAI \
  --sku-name GlobalStandard --sku-capacity 10

Adım 1.2: Veri düzlemi erişimi verip çağırın. Anahtar yerine Entra ID ile kimlik doğrulama:

export AOAI_ID=$(az cognitiveservices account show -g $RG -n $AOAI --query id -o tsv)
az role assignment create \
  --assignee $(az ad signed-in-user show --query id -o tsv) \
  --role "Cognitive Services OpenAI User" \
  --scope "$AOAI_ID"
export OPENAI_BASE_URL="https://$AOAI.openai.azure.com/openai/v1/"
export OPENAI_API_KEY=entra
export OPENAI_MODEL=gpt-4.1-mini
python3 chat.py

Ne kazanıyorsunuz: GPU kotası, YAML ya da yamalanacak bir runtime olmadan bir dakikadan kısa sürede yanıt. Neyden vazgeçiyorsunuz: Yalnızca katalog modellerini kullanabiliyor, GPU’yu, motoru ve parametrelerini değiştiremiyorsunuz.

Seçenek 2: Azure Container Apps serverless GPU

Container’ı siz getiriyorsunuz, GPU’yu Azure veriyor ve yalnızca ihtiyaç olduğu sürece. Küme, node pool, sürücü ya da device plugin yok. Servis runtime’ı yine sizde; bu örnek 5. seçenekle aynı vLLM imajını ve parametrelerini aynı NVIDIA T4 sınıfı GPU’da çalıştırıyor. Diğer seçeneklerden farkı:

  • Sıfıra ölçekleme: minReplicas: 0 ile boştaki uygulama GPU’yu bırakıyor ve ödeme duruyor.
  • Saniye bazlı faturalandırma: Yalnızca bir replika çalışırken GPU, vCPU ve bellek saniyeleri için ödüyorsunuz.
  • Her türlü kendi modeliniz: Fine-tune’lar ve özel motorlar dahil, oluşturduğunuz her container’ı çalıştırabiliyorsunuz.

Kavramlar: Workload profiles environment, birden fazla hesaplama profili barındırabilen bir Container Apps ortamı; serverless GPU bunu gerektiriyor, yalnızca Consumption ortamı desteklemiyor. Consumption GPU profili Consumption-GPU-NC8as-T4 (1 × T4, 8 vCPU, 56 GiB) ya da Consumption-GPU-NC24-A100 (1 × A100, 24 vCPU, 220 GiB) olabiliyor; önce bölgesel erişilebilirliği kontrol edin. Revision, uygulama şablonunun değişmez bir anlık görüntüsü; ölçekleme ayarları da onun parçası.

Adım 2.1: GPU profilini kontrol edip ortamı oluşturun:

export ACA_ENV=aca-demo-gpu-env
export ACA_APP=phi-vllm-aca
# Which serverless GPU profiles does this region offer?
az containerapp env workload-profile list-supported -l $LOC \
  --query "[?contains(name,'GPU')].{name:name, cores:properties.cores, memGiB:properties.memoryGiB, gpus:properties.gpus}" \
  -o table
az containerapp env create -g $RG -n $ACA_ENV -l $LOC --enable-workload-profiles
az containerapp env workload-profile add -g $RG -n $ACA_ENV \
  --workload-profile-name gpu-t4 \
  --workload-profile-type Consumption-GPU-NC8as-T4

Adım 2.2: vLLM’i serverless GPU’ya dağıtın. Şablon 5. seçenekle aynı container ve parametreleri kullanıyor, dört Container Apps’e özgü farkla:

  • API anahtarı: Container Apps ingress’i, port-forward edilen AKS servislerinin aksine herkese açık bir HTTPS endpoint’i. Bu yüzden vLLM anahtarı bir secret’tan (VLLM_API_KEY) okuyor. /health probe’lar için açık kalıyor, /v1/* anahtar istiyor.
  • Startup probe: vLLM, ağırlıkları indirip yükledikten sonra 8000 portunu açıyor. Bu probe 11 dakikaya kadar izin veriyor (60 sn gecikme + 10 × 60 sn).
  • minReplicas: 0 sıfıra ölçeklemeyi açıyor.
  • cooldownPeriod: 900 boştaki replikayı küçültmeden önce 15 dakika tutuyor. Varsayılan 300 saniye, vLLM’in soğuk başlangıcından kısa.
export ACA_ENV_ID=$(az containerapp env show -g $RG -n $ACA_ENV --query id -o tsv)
export VLLM_KEY=$(openssl rand -hex 16)
cat <<EOF | az containerapp create -g $RG -n $ACA_APP --yaml /dev/stdin
location: $LOC
properties:
  environmentId: $ACA_ENV_ID
  workloadProfileName: gpu-t4
  configuration:
    secrets:
      - name: vllm-api-key
        value: $VLLM_KEY
  template:
    containers:
      - name: vllm
        image: docker.io/vllm/vllm-openai:v0.31.0
        args:
          - "--model=microsoft/Phi-3.5-mini-instruct"
          - "--served-model-name=phi-3.5-mini"
          - "--dtype=half"
          - "--max-model-len=4096"
          - "--gpu-memory-utilization=0.9"
          - "--trust-remote-code"
        env:
          - name: VLLM_API_KEY
            secretRef: vllm-api-key
        resources:
          cpu: 8
          memory: 56Gi
        probes:
          - type: Startup
            httpGet: { path: /health, port: 8000 }
            initialDelaySeconds: 60
            periodSeconds: 60
            failureThreshold: 10
          - type: Readiness
            httpGet: { path: /health, port: 8000 }
            periodSeconds: 10
    scale:
      minReplicas: 0
      maxReplicas: 1
      cooldownPeriod: 900
EOF
az containerapp ingress enable -g $RG -n $ACA_APP --type external --target-port 8000
export ACA_FQDN=$(az containerapp show -g $RG -n $ACA_APP --query properties.configuration.ingress.fqdn -o tsv)
echo "$ACA_FQDN"

Adım 2.3: Soğuk başlangıcı bekleyip çağırın. İlk replika yaklaşık 9 GB imaj ve 7,6 GB ağırlık indiriyor. /health 200 dönene kadar sorgulayın; her istek HTTP ölçekleyiciye talep olduğunu da bildiriyor:

until [ "$(curl -s -o /dev/null -w '%{http_code}' --max-time 60 https://$ACA_FQDN/health)" = "200" ]; do
  echo "$(date +%T) waiting for vLLM..."; sleep 15
done
export OPENAI_BASE_URL="https://$ACA_FQDN/v1"
export OPENAI_API_KEY=$VLLM_KEY
export OPENAI_MODEL=phi-3.5-mini
python3 chat.py

Motor loglarını az containerapp logs show -g $RG -n $ACA_APP --tail 100 --format text, platform olaylarını (probe’lar, ölçekleme) --type system ile okuyabilirsiniz.

5. seçeneğe göre maliyeti: Bir ortam, bir GPU profili ve bir uygulama tanımı. Küme, node pool, device plugin, Service ya da port-forward yok ve GPU boştayken gidiyor. Hâlâ sizde olanlar: İmaj, motor sürümü ve parametreleri, model dosyası ve endpoint güvenliği. 3. seçeneğe göre Microsoft’un yönettiği runtime’lardan vazgeçip her model ve her motoru çalıştırabilme ve sıfıra ölçekleme kazanıyorsunuz.

Seçenek 3: Foundry managed compute (önizleme)

Önizleme: SLA yok, üretim için önerilmiyor. Yerleşik içerik filtreleme henüz managed compute veri yolunda değil; gerekiyorsa Azure AI Content Safety’yi doğrudan çağırın.

Managed compute, açık modeller için yönetilen bir GPU platformu. Foundry kataloğunun Hugging Face koleksiyonundan bir model seçiyorsunuz; Foundry ayrılmış hızlandırıcıları hazırlıyor, Microsoft’un oluşturduğu bir servis runtime’ı çalıştırıyor ve modeli 1. seçenekle aynı Foundry endpoint’inde sunuyor. Sizin işleteceğiniz VM, küme, container imajı ya da runtime yok.

  • Model instance: Dağıtım birimi. VM boyutlandırmıyorsunuz; instance sayısını (dağıtım SKU’sundaki kapasite) belirliyorsunuz, her instance şablonunun belirttiği GPU’ları kullanıyor.
  • Deployment template: Runtime’ı (örneğin vLLM), instance başına hızlandırıcı ailesi ve sayısını, bağlam uzunluğunu, quantization’ı ve tool-call ile reasoning parser’ları, health probe’ları, eşzamanlılık gibi ayarları sabitleyen sürümlü bir varlık. Modelin nasıl çalışacağını belirleyen tek ayar, şablon seçimi.
  • Hızlandırıcı ailesi: Dokümantasyonda A100_80GB, H100_80GB ya da MI300_192GB. Yazarın kota API’si H200_141GB’ı da listelemiş.
  • GlobalManagedCompute: Dağıtım SKU’su. Managed compute şimdilik yalnızca Global dağıtımı destekliyor.

Adım 3.1: Hesabı seçip kotayı kontrol edin. Örnek, managed compute rehberindeki Python yönetim SDK’sını ve duyuru yazısında anlatılan Qwen3-32B modelini 40K bağlamlı, tek A100 yapılandırmasıyla kullanıyor. Mevcut bir Foundry hesabı (AIServices) ve projesi, dağıtım için Cognitive Services Contributor, çağırmak için Foundry User rolü ve managed compute kotanızda en az bir boş A100 gerekiyor; Azure VM kotası sayılmıyor.

export MC_RG="rg-inferencing-demo"
export MC_ACCOUNT="<your-foundry-resource-name>"
export MC_DEPLOYMENT=qwen3-32b-demo
export SUB=$(az account show --query id -o tsv)
export MC_LOC=$(az cognitiveservices account show -g "$MC_RG" -n "$MC_ACCOUNT" --query location -o tsv)
az rest --method get \
  --url "https://management.azure.com/subscriptions/$SUB/providers/Microsoft.CognitiveServices/locations/$MC_LOC/managedComputeUsages?api-version=2026-09-01" \
  --query "value[].{family:name.value, used:currentValue, limit:limit}" -o table

Yeni bir dağıtım için A100 satırında limit - used >= 1 olmalı. Değilse daha pahalı bir hızlandırıcıya geçmek yerine Foundry’den managed compute kotası isteyin. Hesapta proje yoksa oluşturun:

export MC_PROJECT=inference-demo
az cognitiveservices account project create \
  --name "$MC_ACCOUNT" --resource-group "$MC_RG" \
  --project-name "$MC_PROJECT" --location "$MC_LOC"
az cognitiveservices account project show \
  --name "$MC_ACCOUNT" --resource-group "$MC_RG" \
  --project-name "$MC_PROJECT" --query properties.provisioningState -o tsv

Sonuç Succeeded olmalı. Mevcut bir projeniz varsa onu kullanabilirsiniz; proje oluşturmak modeli yeniden dağıtmıyor ya da ölçeklemiyor.

Adım 3.2: Python SDK ile dağıtın. requirements.txt, rehberin belirttiği önizleme sürümü azure-mgmt-cognitiveservices==15.0.0b2‘yi sabitliyor:

python3 -m pip install -r requirements.txt
cat <<'EOF' > deploy-managed-compute.py
import os
from azure.identity import DefaultAzureCredential
from azure.mgmt.cognitiveservices import CognitiveServicesManagementClient
client = CognitiveServicesManagementClient(
    DefaultAzureCredential(), os.environ["SUB"]
)
print("Deploying one Qwen3-32B instance on one A100; typically 10-15 minutes.", flush=True)
deployment = client.managed_compute_deployments.begin_create_or_update(
    resource_group_name=os.environ["MC_RG"],
    account_name=os.environ["MC_ACCOUNT"],
    deployment_name=os.environ["MC_DEPLOYMENT"],
    resource={
        "sku": {"name": "GlobalManagedCompute", "capacity": 1},
        "properties": {
            "model": "azureml://registries/azure-huggingface/models/qwen--qwen3-32b/versions/1",
            "deploymentTemplate": "azureml://registries/azure-huggingface/deploymenttemplates/qwen--qwen3-32b--nvidia/labels/latest",
            "acceleratorType": "A100_80GB",
        },
    },
).result()
print(f"State: {deployment.properties.provisioning_state}")
print(f"ID: {deployment.id}")
if deployment.properties.provisioning_state != "Succeeded":
    raise RuntimeError("Deployment is not ready. Inspect its status before sending requests.")
EOF
python3 deploy-managed-compute.py

Adım 3.3: Aynı chat.py ile çağırın. Managed compute dağıtımları birleşik Foundry endpoint’ini kullanıyor. Runtime OpenAI uyumluysa (vLLM öyle) dağıtıma /openai/v1/ üzerinden ulaşılıyor ve model alanı dağıtım adı oluyor. Entra ID ile çağırmak için hesapta Foundry User rolü gerekiyor:

az role assignment create \
  --assignee $(az ad signed-in-user show --query id -o tsv) \
  --role "Foundry User" \
  --scope $(az cognitiveservices account show -g $MC_RG -n $MC_ACCOUNT --query id -o tsv)
export OPENAI_BASE_URL="https://$MC_ACCOUNT.services.ai.azure.com/openai/v1/"
export OPENAI_API_KEY=entra
export OPENAI_MODEL="$MC_DEPLOYMENT"   # deployment name, not the catalog model ID
python3 chat.py

Her managed compute dağıtımına ayrıca https://<account>.services.ai.azure.com/managed-deployments/<deployment-name>/ üzerinden de ulaşılabiliyor; OpenAI dışı API’si olan modeller için bu yol kullanılıyor. Yazar 3. seçeneğin tam olarak test edilmediğini, talimatların karşılaştırma amacıyla belgelendiğini not ediyor.

Managed compute birçok runtime’ı neden kolaylaştırıyor?

Managed compute yalnızca “hizmet olarak vLLM” değil. Model mimarisine göre seçilen bir runtime portföyü çalıştırıyor:

RuntimeKullanım alanı
vLLMYüksek throughput’lu LLM servisi (çoğu LLM için varsayılan)
SGLangYapılandırılmış çıktı: JSON, regex ve gramerle sınırlandırılmış üretim
TensorRT-LLMNVIDIA için optimize edilmiş, düşük gecikmeli LLM servisi
NVIDIA NIMNVIDIA’nın yayımladığı modeller, NIM API ile
Text Embeddings Inference (TEI)Embedding’ler, reranker’lar, sınıflandırıcılar
llama.cppCPU ve küçük GPU’larda GGUF formatında quantize edilmiş modeller
hf-serveGörüntü, ses, segmentasyon ve diğer Transformers pipeline’ları

AKS’te her runtime ayrı bir proje. 5. seçenek tek bir runtime ve tek bir model için gereken işi gösteriyor: GPU node pool, device plugin, motor parametreli bir Deployment, probe’lar, bir Service ve erişim yolu. Bir embedding modeli eklediğinizde farklı imaj, API, health endpoint ve bellek profiliyle baştan başlıyorsunuz. Yapılandırılmış çıktı üreten bir ajan modeli eklerseniz SGLang öğreniyorsunuz; konuşma ya da görüntü modeli eklerseniz Python servis kodu yazıyorsunuz. Her birinin kendi imaj hattı, CVE yamaları, sürüm sabitlemesi ve kullandığınız her GPU tipinde testi gerekiyor.

Managed compute’ta ise runtime, dağıtım şablonundaki bir alandan ibaret. Microsoft’un kürasyon süreci bu işi model, runtime ve hızlandırıcı kombinasyonu başına, model kataloğa girmeden önce bir kez yapıyor. Runtime güncellemeleri ve CVE yamaları çalışan dağıtımlara otomatik uygulanıyor.

Efor karşılaştırması: AKS’te vLLM ve managed compute

KonuAKS’te vLLM (Seçenek 5)Managed compute (Seçenek 3)
GPU kapasitesiSKU erişilebilirliği, VM kotası ve kurum politikasını önceden kontrol et; taint’li GPU node pool oluşturHızlandırıcı ailesini seç; managed compute kotası
GPU altyapısıNVIDIA device plugin DaemonSet’ini kur ve bakımını yapYok
RuntimeMotoru seç, imaj sürümünü sabitleŞablon model için doğru runtime’ı seçer
AğırlıklarEsnek: dışarı çıkışa izin varsa özel ya da herhangi bir açık depoÖnceden hazırlanmış, taranmış SafeTensors; özel ağ dostu
Güvenlik yamalarıİmajları ve sürücüleri yeniden derle, tara, dağıtMicrosoft çalışan dağıtımları yamalar
Endpoint ve kimlik doğrulamaService, ingress, TLS ve kimlik doğrulamayı sen kurarsınBirleşik Foundry endpoint’i, Entra ID ya da anahtar, özel ağ
GözlemlenebilirlikPrometheus, log ve dashboard’ları bağlaAzure Monitor: duruma göre istekler, p50/p90/p99 gecikme, token, TTFT
ÖlçeklemeHPA ya da KEDA ve node autoscalerModel instance sayısını değiştir
Elde kalanTam kontrol: her model, SKU, motor, parametre ya da dosya; KEDA ile sıfıra ölçekleme. Tam kontrol daha fazla sorumluluk demek.Katalogdaki modeller
İlk token’a kadar4 adım, ~15-20 dk, birkaç YAML dosyası, platform kurulumuHesap ve kota, SDK ile dağıtım, istemciyi çağırma; ~10-15+ dk hazırlık

Seçenek 4: AKS üzerinde KAITO

Sonuç 5. seçenekle aynı: AKS GPU’larınızda açık ağırlıklı bir model. Ama yığın tek bir Workspace CRD’sine iniyor. KAITO (AKS AI toolchain operator eklentisi) GPU düğümünü hazırlıyor, device plugin’i kuruyor, vLLM’i ayarlıyor ve Deployment ile Service’i oluşturuyor.

Adım 4.1: AI toolchain operator eklentisiyle küme oluşturun:

export CLUSTER_K=aks-demo-kaito
az aks create \
  -g $RG -n $CLUSTER_K --location $LOC \
  --node-count 1 --node-vm-size Standard_D4s_v6 \
  --enable-ai-toolchain-operator --enable-oidc-issuer \
  --generate-ssh-keys
az aks get-credentials -g $RG -n $CLUSTER_K --overwrite-existing
kubectl config use-context $CLUSTER_K

Adım 4.2: Tek bir Workspace uygulayın:

cat <<EOF | kubectl apply -f -
apiVersion: kaito.sh/v1beta1
kind: Workspace
metadata:
  name: workspace-phi
resource:
  instanceType: "$GPU_VM"
  labelSelector:
    matchLabels: { apps: phi }
inference:
  preset:
    name: phi-3.5-mini-instruct
EOF
kubectl get workspace workspace-phi -w

Adım 4.3: Çağırın. Başka bir terminalde port-forward başlatın: kubectl port-forward svc/workspace-phi 8000:80

export OPENAI_BASE_URL="http://localhost:8000/v1"
export OPENAI_API_KEY=not-needed
export OPENAI_MODEL=phi-3.5-mini-instruct
python3 chat.py

5. seçeneğe göre maliyeti: Node pool, device plugin, Deployment, Service ve probe’lar yerine tek bir CRD; kelimenin tam anlamıyla 5-7 satırlık bir Workspace tanımı. Elinizde kalanlar: Kümeniz, GPU’larınız, ağınız ve kimlik yapınız; gerekirse ham YAML’e inme seçeneği. Ayrıntılar için KAITO GitHub deposu.

Seçenek 5: AKS üzerinde elle kurulan vLLM

Tam kontrolün olduğu uç: GPU node pool ve device plugin’den model servis runtime’ına kadar her katmanı siz işletiyorsunuz. Yazara göre bu seçeneğin amacı yalnızca esneklik değil; üst seviye hizmetlerin üzerine kurulduğu yapı taşını görmek, sahiplenmek ve bu sahipliğin maliyetini hissetmek.

Modellerin çoğu yönetilen bir hizmette çalışacak. Ama katmanları bir kez elle kurmak şunları sağlıyor:

  • Üst seviye soyutlamaların nasıl kurulduğunu anlarsınız; yönetilen endpoint kara kutu olmaktan çıkar.
  • Bir özelliği nasıl kurulduğuyla ilişkilendirirsiniz. “Önbellekleme”, “otomatik ölçekleme” ve “bağlam uzunluğu” somut karşılıklara dönüşür: GPU belleğindeki KV cache, replika sayısı ya da bir bellek ayarı.
  • Bir iddianın hangi katmanla ilgili olduğunu bildiğiniz için doğru soruları sorarsınız.
  • Soyut kalmadan bilgiye dayalı bir konuşma yapabilirsiniz.

Yazar bunu, hypervisor’ı, CPU ve belleğin nasıl bölündüğünü, disklerin nasıl paylaşıldığını ve yazılım tanımlı ağı anlamadan sanal makinelerden bahsetmeye benzetiyor: VM kullanabilirsiniz ama neden yavaş olduğunu yargılayamazsınız. GPU’da vLLM servisi üç şeyi gösteriyor: Tek bir LLM çağrısının nasıl servis edildiği (prompt önce prefill adımında işleniyor, sonra yanıt token token üretiliyor; ağırlıklar ve KV cache GPU belleğini paylaşıyor), servis tarafında önbelleğin nasıl çalıştığı ve yönetilen bir hizmetin neyi üstlendiği.

Adım 5.1: Küme ve GPU node pool oluşturun:

export CLUSTER=aks-demo-manual
az aks create \
  -g $RG -n $CLUSTER --location $LOC \
  --node-count 1 --node-vm-size Standard_D4s_v6 \
  --generate-ssh-keys
az aks nodepool add \
  -g $RG --cluster-name $CLUSTER -n gpu \
  --mode User \
  --node-count 1 --node-vm-size $GPU_VM \
  --node-taints sku=gpu:NoSchedule --labels sku=gpu
az aks get-credentials -g $RG -n $CLUSTER --overwrite-existing
kubectl config use-context $CLUSTER
kubectl get nodes -o wide

Adım 5.2: NVIDIA device plugin’i kurun. AKS bu GPU düğümlerine sürücüyü kuruyor, ama sürücü tek başına Kubernetes’e pod’lar için hangi GPU’ların kullanılabileceğini söylemiyor. Bu adım, Kubernetes’in device plugin çerçevesini uygulayan açık kaynak NVIDIA Kubernetes device plugin’ini dağıtıyor.

Kubernetes CPU ve bellek gibi standart kaynakları zaten tanıyor. NVIDIA GPU’lar ise nvidia.com/gpu adlı genişletilmiş bir kaynak olarak sunuluyor ve Kubernetes’in bunları keşfedip ayırması için plugin gerekiyor. sku=gpu etiketi düğümleri seçiyor, taint ise yerleşimi kısıtlıyor; ikisi de GPU kapasitesini kaydetmiyor. DaemonSet, sku=gpu etiketli her düğümde (sonradan eklenenler dahil) bir plugin pod’u çalıştırıyor. Plugin, /var/lib/kubelet/device-plugins dizini üzerinden kubelet’e kaydoluyor, GPU’ları keşfediyor ve durumlarını raporluyor. Kubelet de nvidia.com/gpu‘yu düğüm kaynağı olarak duyuruyor. Plugin olmasa vLLM pod’u GPU isteği karşılanamadığı için Pending’de kalırdı.

Bu laboratuvardaki NVIDIA T4’te nvidia.com/gpu: 1 container’a GPU’nun bir parçasını değil tamamını ayırıyor. Örnek bilerek MIG ya da DRA kullanmıyor (ayrıntı için AKS Engineering Blog’daki MIG ve DRA yazısı).

cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels: { name: nvidia-device-plugin-ds }
  updateStrategy: { type: RollingUpdate }
  template:
    metadata:
      labels: { name: nvidia-device-plugin-ds }
    spec:
      tolerations:
        - { key: sku, operator: Equal, value: gpu, effect: NoSchedule }
        - { key: nvidia.com/gpu, operator: Exists, effect: NoSchedule }
      nodeSelector: { sku: gpu }
      priorityClassName: system-node-critical
      containers:
        - name: nvidia-device-plugin-ctr
          image: nvcr.io/nvidia/k8s-device-plugin:v0.16.2
          securityContext:
            allowPrivilegeEscalation: false
            capabilities: { drop: ["ALL"] }
          volumeMounts:
            - { name: device-plugin, mountPath: /var/lib/kubelet/device-plugins }
      volumes:
        - name: device-plugin
          hostPath: { path: /var/lib/kubelet/device-plugins }
EOF
# Expect: 1
kubectl get node -l sku=gpu -o jsonpath='{.items[0].status.allocatable.nvidia\.com/gpu}{"\n"}'

Adım 5.3: vLLM’i Deployment ve Service ile dağıtın:

cat <<'EOF' | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: phi-vllm
spec:
  replicas: 1
  selector:
    matchLabels: { app: phi-vllm }
  template:
    metadata:
      labels: { app: phi-vllm }
    spec:
      nodeSelector: { sku: gpu }
      tolerations:
        - { key: sku, operator: Equal, value: gpu, effect: NoSchedule }
      containers:
        - name: vllm
          image: vllm/vllm-openai:latest
          args:
            - "--model=microsoft/Phi-3.5-mini-instruct"
            - "--served-model-name=phi-3.5-mini"
            - "--dtype=half"
            - "--max-model-len=4096"
            - "--gpu-memory-utilization=0.9"
            - "--trust-remote-code"
          ports:
            - { containerPort: 8000 }
          resources:
            limits: { nvidia.com/gpu: 1 }
          readinessProbe:
            httpGet: { path: /health, port: 8000 }
            initialDelaySeconds: 60
            periodSeconds: 10
            failureThreshold: 30
---
apiVersion: v1
kind: Service
metadata:
  name: phi-vllm
spec:
  selector: { app: phi-vllm }
  ports:
    - { port: 80, targetPort: 8000 }
EOF
kubectl rollout status deploy/phi-vllm --timeout=900s

Adım 5.4: Çağırın. Başka bir terminalde: kubectl port-forward svc/phi-vllm 8000:80

export OPENAI_BASE_URL="http://localhost:8000/v1"
export OPENAI_API_KEY=not-needed
export OPENAI_MODEL=phi-3.5-mini
python3 chat.py

Maliyeti: Bir küme, bir GPU node pool, bir device plugin ve elle yazılmış Deployment, Service ve probe; artı her birinin gelecekteki tüm güncellemeleri. Kazancı: Tam kontrol. GPU’yu değiştirebilir, sürümleri sabitleyebilir, motorun her parametresini değiştirebilir, ağırlıkları bir PVC’de önbelleğe alabilir ya da quantize veya fine-tune edilmiş bir dosyayı servis edebilirsiniz.

Birden fazla replika, tek Service: Sıradan yük dengeleme nerede yetersiz kalıyor?

Buraya kadar her şey tek bir endpoint’in modeli servis ettiğini varsayıyordu. Pratikte kapasite ve erişilebilirlik için genellikle birden fazla vLLM pod’u çalıştırırsınız.

Sorun: Her vLLM pod’u kendi KV cache’ini, yani daha önce işlediği prompt’lar için hesapladığı attention durumunu tutuyor. Otomatik prefix caching ile bir prompt’un önekini daha önce görmüş pod, prefill sırasında onu yeniden hesaplamayı atlayabiliyor. Ama bu önbellek tek bir pod’un GPU belleğinde yaşıyor ve paylaşılmıyor. Standart bir Kubernetes Service konuşmaları ya da önbellek içeriğini değil bağlantıları dengeliyor. Bu yüzden aynı uzun öneki paylaşan iki istek (örneğin bir sohbetin ardışık iki turu) farklı pod’lara düşebiliyor. Bir pod önbellekten yanıt veriyor, diğeri tüm prompt’u sıfırdan hesaplıyor. İki yanıt da doğru; fark, her pod’un ne kadar iş yaptığında.

Test: Yazar aynı modelin iki replikasını çalıştırdı (vLLM 0.31.0 üzerinde Phi-3.5-mini, her biri bir NVIDIA T4, prefix caching açık). Bir pod’u yaklaşık 2.770 token’lık bir prompt’la ısıttı, sonra aynı prompt’u hem bu “sıcak” pod’a hem de diğer “soğuk” pod’a gönderdi:

Sıcak podSoğuk pod
Önbellekten yeniden kullanılan token2.774 token’ın 2.768’i0 (2.774 token’ın tamamı hesaplandı)
TTFT (istemci tarafı)~320 ms~4,0 sn
TTFT (vLLM içinde)~73 ms~3,45 sn

Standart bir Kubernetes Service, bir prompt’un KV cache’ini hangi pod’un tuttuğunu bilmiyor. Ortak öneki olan istekler, öneki yeniden hesaplaması gereken pod’a düşebiliyor. Cache-aware routing bu yüzden önemli: Yükü dengelerken isteği öneki zaten tutan replikaya göndermek, bu uzunluktaki prompt’larda bu GPU’da saniyelerce tekrar eden işi önlüyor. Yazar bu konuyu ayrı bir yazıda daha ayrıntılı ele alacağını söylüyor.

Temizlik

Denemeleri bitirdiğinizde GPU maliyetinin sürmemesi için kaynakları silin:

# Option 2: Container Apps (environment, app, and its Log Analytics workspace live in $RG)
az containerapp delete -g $RG -n $ACA_APP --yes
az containerapp env delete -g $RG -n $ACA_ENV --yes
# Option 3: delete the exact managed compute deployment and wait for completion.
# Reuse SUB, MC_RG, MC_ACCOUNT, and MC_DEPLOYMENT from Step 3.1.
python3 - <<'PY'
import os
from azure.identity import DefaultAzureCredential
from azure.mgmt.cognitiveservices import CognitiveServicesManagementClient
client = CognitiveServicesManagementClient(DefaultAzureCredential(), os.environ["SUB"])
client.managed_compute_deployments.begin_delete(
    resource_group_name=os.environ["MC_RG"],
    account_name=os.environ["MC_ACCOUNT"],
    deployment_name=os.environ["MC_DEPLOYMENT"],
).result()
print("Managed compute deployment deleted.")
PY
# Options 4 and 5: free the GPU nodes first
kubectl --context $CLUSTER   delete deploy phi-vllm --ignore-not-found
kubectl --context $CLUSTER_K delete workspace workspace-phi --ignore-not-found
# Everything else in the demo resource group (clusters, Foundry resource, Container Apps)
az group delete -n $RG --yes --no-wait

Kaynaklar


Rehberin özeti şu: Kapalı bir model kullanacaksanız tek seçenek Foundry serverless API. Açık modellerde ise karar, ne kadarını işletmek istediğinize bağlı. Dalgalı trafikte sıfıra ölçeklenen Container Apps serverless GPU, AKS kullanan ekipler için KAITO, tam kontrol için elle kurulan vLLM öne çıkıyor. Managed compute ve Fireworks on Foundry’nin bir kısmının hâlâ önizlemede olduğunu, örneklerdeki model sürümlerinin de zamanla emekliye ayrılacağını unutmamak gerekiyor.

Kaynak: https://techcommunity.microsoft.com/blog/StartupsatMicrosoftBlog/inference-options-on-azure-an-architect’s-view/4563542

Yazar Hakkında

Kerem Şuğle

Solution Architect, VMware vExpert ve Microsoft sertifikalı altyapı uzmanı. VMware vSphere/vSAN/VCF, Azure, AWS, Google Cloud, enterprise sanallaştırma ve yapay zeka konularında 15+ yıl deneyim. AI/cloud dönüşümü, sovereign cloud, enterprise güvenlik ve modern altyapı mimarisi alanlarında yazıyor.

Leave a Comment