Ringkasan Utama
OpenCost 1.121.0 menerbitkan llm_cost_per_million_tokens untuk model vLLM self-hosted dengan dua basis. Biaya allocation mencakup waktu GPU idle dan cocok dengan tagihan cloud; biaya usage hanya menghitung inference yang aktif. Usage dibagi allocation menghasilkan utilisasi. Bandingkan biaya allocation, bukan usage, dengan harga API: self-hosting menang hanya di atas biaya usage dibagi harga itu.
Pertanyaan awalnya sederhana: berapa biaya satu juta token di server vLLM yang kami jalankan, dan apakah lebih murah daripada API? Setiap jawaban yang bisa saya buat hanyalah tagihan GPU bulanan dibagi jumlah token dari dashboard, dengan asumsi utilisasi yang tersembunyi di tengahnya.
OpenCost 1.121.0 mengubah pembagian itu menjadi sebuah metric. Post ini adalah pembacaan dekat atas pengumuman CNCF, blog OpenCost sendiri, panduan inference-cost-tracking di repository, dan dua pull request di baliknya, lalu dicek dengan dokumentasi metrics vLLM. Saya belum menjalankan 1.121.0 di cluster, jadi semua angka di bawah berasal dari halaman-halaman itu atau hitungan saya sendiri yang diberi label.
Yang ditambahkan OpenCost 1.121.0: dua series per model
Pengumuman CNCF tanggal 5 Agustus 2026 menggambarkan 1.121.0 sebagai penghubung antara biaya infrastruktur GPU dan throughput token LLM, sehingga tim platform bisa melihat biaya tiap model dan tiap token. Fitur ini dibuat dengan llm-d dalam benak, tetapi post-nya menyebut metric inti juga jalan dengan vLLM biasa. Halaman release v1.121.0 mencatat fitur ini sebagai pull request 3845, AI Inference Costs v1, ditambah pull request 3901 yang memperbaiki cara usage basis dihitung.
Jumlah token berasal dari counter vLLM vllm:prompt_tokens_total dan vllm:generation_tokens_total; sisi dolarnya dari allocation engine OpenCost yang sudah ada. Setiap series membawa model_name, model_version, namespace, cost_basis, dan workload_type, dan workload_type saat ini selalu inference.
| Series | Apa itu | Catatan dari panduan |
|---|---|---|
| llm_total_hourly_cost | Tarif per jam dalam dolar per jam, bukan counter kumulatif | Kalikan 24 untuk proyeksi harian real-time, atau pakai avg_over_time selama 24h dikali 24 untuk data historis |
| llm_cost_per_million_tokens | Biaya blended per 1M token | Label phase bernilai prompt atau generation memisahkan biaya input dari output |
| llm_cache_savings_fraction | Porsi prompt token yang dilayani dari KV cache, 0 sampai 1 | Nol bila prefix caching mati atau tidak ada cache hit |
| allocation_method (label) | Cara pemisahan input dan output dihitung | compute_time, prefix_caching_off, multiplier, atau kosong bila join gagal atau biayanya nol |
Biaya allocation adalah tagihan; biaya usage adalah kerja nyata
Dua basis biaya ini menjawab pertanyaan yang berbeda, dan sisa post ini bergantung pada menjaganya tetap terpisah. Artikel CNCF membingkai allocation sebagai biaya menjaga model tetap tersedia, dan usage sebagai biaya inference aktifnya, dengan penghematan dari KV cache hit. Panduan di repository, yang saya baca di branch develop dan mungkin lebih baru daripada tag 1.121.0, lebih mekanis.
| Aspek | Allocation basis | Usage basis |
|---|---|---|
| Cocok dengan tagihan infrastruktur | Ya | Tidak |
| Waktu GPU idle | Dihitung | Dikecualikan |
| Infrastruktur llm-d bersama (scheduler, gateway) | Dihitung, disebar ke model sebanding dengan total allocation cost tiap model | Dikecualikan |
| Resource yang dihitung | Yang lebih besar antara requested atau used | GPU diskala dengan rata-rata GPU usage, CPU dengan core usage dibanding request, RAM dengan bytes used dibanding requested |
| Untuk apa | Chargeback, showback, dan build-vs-buy | Analisis efisiensi |
Utilisasi muncul dari rasionya: biaya usage per juta token dibagi biaya allocation per juta token. Contoh di artikel adalah 1,00 dolar lawan 4,00 dolar, yaitu 25 persen. Perhatikan apa yang sebenarnya diukur rasio ini. Karena usage basis membuang biaya idle dan biaya bersama, model yang sibuk setiap detik pun tetap di bawah 100 persen selama infrastruktur bersama diberi label. Ini rasio efisiensi biaya, bukan counter GPU.
Menyalakannya: satu flag dan satu label yang harus cocok
Setup-nya kecil. Set INFERENCE_COST_ENABLED ke true di deployment OpenCost; ia memakai ulang PROMETHEUS_SERVER_ENDPOINT untuk metric vLLM, jadi tidak ada Prometheus kedua yang perlu dikonfigurasi. Join antara biaya dan token memakai kunci nama model dan namespace, sehingga satu label pod menjadi seluruh integrasinya.
# 1. Turn it on. Names and defaults are from docs/inference-cost-tracking.md.
# OpenCost reuses PROMETHEUS_SERVER_ENDPOINT, so no second Prometheus.
env:
- name: INFERENCE_COST_ENABLED
value: "true" # default is false
- name: INFERENCE_MODEL_LABEL # default: llm-d.ai/model
value: "llm-d.ai/model"
- name: INFERENCE_SHARED_INFRA_LABEL # default: llm-d.ai/inference-shared
value: "llm-d.ai/inference-shared"
- name: INFERENCE_SHARED_INFRA_LABEL_VALUE # default: "true"
value: "true"
# 2. Label the vLLM pods. The value must equal vLLM's model_name, and the
# namespace must match exactly. Wrong: label says "acme-chat-8b" while vLLM
# reports the full path, so tokens show up and every cost field is zero.
# Right: pin the name on both sides.
# vllm serve /models/acme-chat-8b --served-model-name acme-chat-8b
metadata:
namespace: llm-serving
labels:
llm-d.ai/model: acme-chat-8b
# 3. Prove the join. These are the guide's own endpoints (examples use :9003).
# A non-zero totalCost for the model means the labels line up.
# curl "http://localhost:9003/inferenceCost/total?window=7d&aggregate=model_name"
# curl "http://localhost:9003/inferenceCost/timeseries?window=24h&accumulate=hour&costBasis=usage&filter=namespace:llm-serving"Nilai label harus sama dengan model_name milik vLLM, yaitu --served-model-name bila diset dan path --model lengkap bila tidak. Panduan menyebut OpenCost mencocokkan nama lengkap org/model dengan nama pendek, tetapi namespace harus persis sama. Pod scheduler dan gateway diberi label shared-infra agar biayanya disebar ke model, bukan muncul sebagai overhead tanpa pemilik.
Set --served-model-name secara eksplisit di setiap server vLLM. Nama pendek yang stabil menjaga label pod, series model_name, dan dashboard tetap sinkron saat checkpoint di baliknya berganti.
Utilisasi dan break-even sebagai PromQL yang bisa di-alert
Dari yang saya baca, OpenCost tidak menerbitkan series utilisasi, jadi saya akan menurunkannya sendiri. Pilih series blended, yang tanpa label phase, di tiap basis lalu bagi. Rekam sekali dan semua dashboard serta alert memakai definisi yang sama.
# prometheus-rules.yaml. The blended series has no phase label, hence phase="".
groups:
- name: inference-cost
rules:
# utilisation = usage cost per 1M tokens / allocation cost per 1M tokens
- record: model:llm_utilisation:ratio
expr: |
sum by (model_name, namespace) (
llm_cost_per_million_tokens{cost_basis="usage", phase=""}
)
/
sum by (model_name, namespace) (
llm_cost_per_million_tokens{cost_basis="allocation", phase=""}
)
# Compare ALLOCATION cost with the API price. 2.00 is the article's
# illustrative price; put your real one here.
- alert: SelfHostedCostAboveApiPrice
expr: |
sum by (model_name, namespace) (
llm_cost_per_million_tokens{cost_basis="allocation", phase=""}
) > 2.00
for: 6h # allocation cost swings with traffic; do not page on a quiet hour
labels:
severity: ticket
# Daily spend for one model, from the hourly-rate gauge (it is a rate, not a counter):
# avg_over_time(llm_total_hourly_cost{cost_basis="allocation"}[24h]) * 24Alert menembak pada biaya allocation, karena itulah angka yang menurut post CNCF harus dibandingkan dengan harga API. Nilai 2,00 dolar dipakai hanya karena contoh artikel memakainya; ganti dengan harga model hosted yang benar-benar akan Anda pilih. Durasi for yang panjang penting: biaya allocation model yang jarang dipakai naik turun mengikuti traffic.
Break-even: biaya usage dibagi harga API
Contoh CNCF adalah 1,00 dolar usage dan 4,00 dolar allocation per juta token, yaitu utilisasi 25 persen. Terhadap harga API 2,00 dolar, API lebih murah, dan artikel menyebut self-hosting baru kompetitif di atas sekitar 50 persen. Angka 50 itu bukan aturan praktis; itu 1,00 dibagi 2,00. Bila biaya usage per juta token kurang lebih tetap saat traffic berubah, yang merupakan asumsi saya di sini, biaya allocation adalah biaya usage dibagi utilisasi.
| Utilisasi | Biaya allocation per 1M token | Lawan harga API 2,00 dolar |
|---|---|---|
| 100 persen | 1,00 dolar | Self-hosting lebih murah |
| 80 persen | 1,25 dolar | Self-hosting lebih murah |
| 50 persen | 2,00 dolar | Break-even |
| 25 persen | 4,00 dolar | API lebih murah (contoh artikel) |
| 10 persen | 10,00 dolar | API lebih murah |
| 5 persen | 20,00 dolar | API lebih murah |
Setiap baris kecuali yang 25 persen adalah hitungan saya sendiri atas harga ilustrasi artikel, bukan hasil pengukuran. Baris terakhir ada karena artikel menyebut model dengan traffic rendah bisa menghabiskan 95 persen waktunya dalam keadaan warm tapi idle. Kalau biaya berskala satu banding satu dengan waktu sibuk, model itu ada di sekitar 5 persen. Pada praktiknya usage basis menskala biaya GPU dengan rata-rata GPU usage, bukan waktu sibuk, jadi anggap baris bawah sebagai arah, bukan prakiraan.
Ada dua pelajaran praktis. Ambang batasnya bergeser setiap kali salah satu harga berubah, jadi simpan harga API sebagai variabel, bukan konstanta. Dan tuas yang Anda pegang adalah utilisasi: menggabungkan traffic ke replica yang lebih sedikit menaikkan model di tabel, sedangkan GPU yang lebih murah mengubah pembilangnya.
Membaca empat kuadran sebelum memutuskan
Post CNCF memberi matriks dua kali dua untuk membaca allocation terhadap usage. Saya tampilkan ulang karena ia memisahkan kasus yang solusinya traffic dari kasus yang solusinya model.
| Biaya allocation | Biaya usage | Pembacaan |
|---|---|---|
| Tinggi | Rendah | Utilisasi adalah masalahnya: pertimbangkan model sharing atau konsolidasi traffic |
| Tinggi | Tinggi | Evaluasi apakah model cocok untuk workload-nya |
| Rendah | Rendah | Kemungkinan ukurannya sudah pas |
| Rendah | Tinggi | Inference-nya sendiri mahal: evaluasi ukuran model, quantisation, dan kecocokan hardware |
Baris atas adalah tempat perhitungan break-even terasa. Model allocation tinggi dan usage rendah bisa kalah dari API hari ini dan menang setelah konsolidasi, sedangkan model usage tinggi tidak akan terselamatkan oleh traffic. Post menyebut proof of concept-nya berjalan di cluster dengan 109 GPU dan 30 model; saya tidak menemukan angka per model darinya, jadi tidak ada yang bisa saya tunjukkan.
Saat angka berbohong: failure mode yang diuji lebih dulu
Yang paling diam-diam adalah biaya nol. Menurut panduan, bila label pod hilang atau tidak cocok, token tetap muncul tetapi semua field biaya nol dan allocation_method kosong. Tidak ada error; dashboard hanya menampilkan model yang memproses token secara gratis.
Model dengan jumlah token tetapi biaya nol hampir pasti label mismatch, bukan model gratis. Bandingkan nilai label pod dengan model_name vLLM di Prometheus, dan pastikan namespace persis sama, sebelum Anda percaya angka cost-per-million apa pun.
Pemisahan input dan output bisa jatuh kembali ke tebakan. OpenCost membagi biaya infrastruktur dengan waktu prefill terhadap total waktu, memakai vllm:request_prefill_time_seconds_sum dan vllm:request_time_per_output_token_seconds_sum. Bila keduanya hilang atau nol, allocation_method menunjukkan multiplier dan biaya output diperkirakan 2,5 kali biaya input. Angka blended tidak terpengaruh; pemisahannya iya.
Usage basis sempat dirilis dengan bug. Pull request 3901 menyebut biaya allocation sebelumnya dipakai untuk GPU, CPU, dan RAM meskipun costBasis adalah usage. Perbaikannya menskala GPU dengan rata-rata GPU usage, CPU dengan core usage dibanding request, dan RAM dengan bytes used dibanding requested, serta membiarkan biaya network, persistent volume, load balancer, dan external tanpa skala. Perbaikan ini ada di release notes v1.121.0 bersama fiturnya, tetapi artinya rasio utilisasi Anda bertumpu pada rata-rata GPU usage terukur, yang bukan besaran yang sama dengan token per detik.
Batasan lain dari halaman yang saya baca: fitur ini butuh Prometheus karena metric vLLM hanya tersedia di sana; pengukuran GPU terbuang, deteksi GPU idle, integrasi UI, dan atribusi tim tercatat sebagai pekerjaan berjalan; dan pull request menyebut label UID per pod dari llm-d akan memungkinkan biaya per token lebih akurat tetapi belum dikerjakan. Terakhir, post CNCF menunjukkan bahwa cost bukan price. Angka API Anda adalah harga, angka self-hosted Anda adalah biaya, dan keduanya tidak memasukkan waktu engineer untuk menjalankan stack, yang merupakan pengamatan saya, bukan artikel.
Yang dilakukan Senin: seminggu pengukuran
Jangan migrasi apa pun dulu. Habiskan seminggu membuktikan angkanya, lalu putuskan model demi model.
- Aktifkan INFERENCE_COST_ENABLED di OpenCost non-produksi, beri label satu deployment vLLM, lalu panggil /inferenceCost/total untuk memastikan biayanya tidak nol.
- Cek bahwa allocation_method melaporkan compute_time; bila tertulis multiplier, perbaiki metric timing vLLM sebelum memakai pemisahan input dan output.
- Catat angka allocation blended, angka usage, dan rasionya untuk tiap model selama seminggu penuh, agar akhir pekan yang sepi ikut tercatat.
- Hitung break-even tiap model sebagai biaya usage dibagi harga API yang akan Anda pilih, lalu bandingkan dengan rasio terukur.
- Bertindak sesuai kuadran: konsolidasikan atau bagi model allocation tinggi dan usage rendah, ubah ukuran model usage tinggi, dan biarkan sisanya.
# Port-forward OpenCost (the service name varies by install; the guide's
# examples use localhost:9003), then pull a week on both bases.
kubectl -n opencost port-forward svc/<opencost-service> 9003:9003 &
curl -s "http://localhost:9003/inferenceCost/total?window=7d&aggregate=model_name&costBasis=allocation" | jq '.data.inferenceCosts'
curl -s "http://localhost:9003/inferenceCost/total?window=7d&aggregate=model_name&costBasis=usage" | jq '.data.inferenceCosts'
# Break-even utilisation = usage cost per 1M tokens / API price per 1M tokens.
# Plug in YOUR measured usage cost; 1.00 and 2.00 are the article's example.
awk 'BEGIN { usage = 1.00; api = 2.00; printf "break-even: %.0f%%
", 100 * usage / api }'Saya belum menjalankan ini di cluster, jadi saya tidak bisa memberi break-even terukur. Yang bisa saya katakan, metodenya hanya dua panggilan API, satu recording rule, dan satu pembagian.
Hargai inference self-hosted dengan biaya allocation per juta token, baca utilisasi sebagai usage dibagi allocation, dan jangan percaya keduanya sebelum label join terbukti tidak nol. Break-even bukan persentase tetap, melainkan biaya usage dibagi harga API, dan ia bergeser setiap kali salah satunya berubah.
Sumber dan bacaan lanjutan
- Blog CNCF: OpenCost 1.121.0, pelacakan biaya inference Kubernetes pertama di kelasnya
- Blog OpenCost: biaya inference llm-d dan OpenCost
- Repository OpenCost: docs/inference-cost-tracking.md
- OpenCost pull request 3845: AI Inference Costs v1
- OpenCost pull request 3901: perbaikan usage cost basis untuk AI inference
- Release notes OpenCost: v1.121.0
- Dokumentasi vLLM: desain production metrics
- llm-d: distributed LLM inference berbasis Kubernetes

