Infrastruktur model serving

Pelajari cara men-deploy dan mengonfigurasi endpoint model saat lingkunganmu belum menyediakan solusi model serving.

Sebelum kamu dapat menghubungkan IBM Bob ke large language model (LLM), kamu harus memiliki akses ke endpoint model yang telah di-deploy. Bob tidak menyediakan, meng-host, atau mengelola infrastruktur model serving. Jika organisasimu telah menyediakan endpoint model melalui OpenShift AI, GPU-based inference server, layanan AI cloud, atau platform inferensi lainnya, lanjutkan langsung ke Mengonfigurasi Model Gateway.

Opsi deployment

Pilih opsi yang paling sesuai dengan lingkungan dan persyaratan operasionalmu.

OpsiKapan digunakan
OpenShift AI (on-cluster, OCI/ModelCar)Model air-gapped atau self-hosted; RHOAI sudah tersedia di cluster
Public cloudModel frontier melalui AWS Bedrock, Azure OpenAI, atau Google Vertex AI
Infrastruktur privatModel dilayani pada server GPU terpisah atau cluster inferensi khusus

OpenShift AI (on-cluster, OCI/ModelCar)

Red Hat OpenShift AI (RHOAI) adalah platform yang direkomendasikan untuk melayani model di dalam cluster (on-cluster), termasuk deployment air-gapped. Pendekatan yang lebih disukai untuk memuat bobot (weight) model adalah pola OCI/ModelCar: file model dikemas ke dalam OCI image di bawah /models/ dan di-push ke registry privat. Saat InferenceService di-deploy, KServe menyuntikkan init container modelcar-init yang menarik image dan menyalin bobot ke dalam volume bersama di /mnt/models/, yang kemudian dimuat oleh runtime serving (misalnya vLLM). Image model di-cache pada node setelah penarikan pertama — restart berikutnya pada node yang sama melewati proses pengunduhan sepenuhnya.

Prasyarat:

  • Operator Red Hat OpenShift AI terinstal di cluster
  • KServe diaktifkan dan dikonfigurasi
  • Worker node berkemampuan GPU dengan NVIDIA GPU Operator (atau setara) terkonfigurasi
  • CLI oc terautentikasi ke cluster target dengan izin untuk membuat resource di namespace target
  • Container registry privat yang dapat diakses dari cluster, dengan kredensial untuk melakukan push image ke sana

Konfigurasi Red Hat OpenShift AI

Konfigurasikan resource DataScienceClusterInitialization dan DataScienceCluster sebagai berikut:

  • Nonaktifkan serviceMesh.
  • Aktifkan KServe dengan mengatur managementState: Managed.
  • Konfigurasikan KServe untuk menggunakan mode RawDeployment.
  • Hapus semua komponen Red Hat OpenShift AI yang tidak digunakan.

Contoh konfigurasi KServe:

kserve:
  defaultDeploymentMode: RawDeployment
  nim:
    managementState: Managed
  rawDeploymentServiceConfig: Headed
  serving:
    ingressGateway:
      certificate:
        type: OpenshiftDefaultIngress
    managementState: Removed
    name: knative-serving
  managementState: Managed

Aktifkan dukungan ModelCar

Dukungan ModelCar dikontrol oleh ConfigMap inferenceservice-config di namespace redhat-ods-applications. Kunci storageInitializer harus berisi "enableModelcar": true.

Verifikasi konfigurasi saat ini:

oc get configmap inferenceservice-config \
  -n redhat-ods-applications \
  -o jsonpath='{.data.storageInitializer}'

Output harus berisi:

{
  "enableModelcar": true,
  "cpuModelcar": "10m",
  "memoryModelcar": "15Mi"
}

Jika enableModelcar tidak ada atau false, perbarui ConfigMap:

# Ambil nilai saat ini, gabungkan flag, dan lakukan patch
CURRENT=$(oc get configmap inferenceservice-config \
  -n redhat-ods-applications \
  -o jsonpath='{.data.storageInitializer}')
PATCHED=$(echo "$CURRENT" | python3 -c "
import json, sys
d = json.load(sys.stdin)
d['enableModelcar'] = True
print(json.dumps(d))
")
oc patch configmap inferenceservice-config \
  -n redhat-ods-applications \
  --type merge \
  -p "{\"data\":{\"storageInitializer\":$(echo $PATCHED | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}}"

Restart controller KServe untuk menerapkan perubahan:

oc rollout restart deployment kserve-controller-manager -n redhat-ods-applications
oc rollout status deployment kserve-controller-manager -n redhat-ods-applications

Kemas file model ke dalam OCI image

Unduh bobot model dari Hugging Face dan kemas ke dalam OCI image. Image harus memiliki semua file model di bawah direktori /models. Untuk informasi lebih lanjut, lihat dokumentasi KServe. Untuk deployment vLLM, sertakan pecahan (shard) model safetensors dan kecualikan file checkpoint lama seperti .bin, .pt, dan original/*.

Contoh Dockerfile:

FROM busybox:latest

# Bobot model — safetensors shards dan index
COPY <model-name>/model-*.safetensors         /models/
COPY <model-name>/model.safetensors.index.json /models/

# Konfigurasi model
COPY <model-name>/config.json             /models/
COPY <model-name>/generation_config.json  /models/

# Tokenizer
COPY <model-name>/tokenizer.json           /models/
COPY <model-name>/tokenizer_config.json    /models/
COPY <model-name>/special_tokens_map.json  /models/

Jika model menyertakan chat template (misalnya chat_template.jinja), tambahkan file tersebut. Atau, salin seluruh direktori dalam satu instruksi — lebih sederhana, tetapi mencakup file yang tidak dibutuhkan oleh vLLM:

FROM busybox:latest
COPY <model-name>/ /models/

Push image ke registry privat

Push OCI image ke container registry privat yang dapat dijangkau dari cluster:

<registry>/<project>/<model-name>:latest

Kamu dapat menggunakan alat manajemen image apa pun yang didukung, termasuk:

  • Podman
  • Skopeo
  • Pipeline CI/CD
  • Alat khusus registry

Buat namespace target dan image pull secret

Buat namespace project dan konfigurasikan kredensial untuk menarik image model:

oc new-project <namespace>

Buat pull secret registry:

# Pull secret agar KServe dapat menarik image model dari registry privatmu
oc create secret docker-registry model-registry-secret \
  --docker-server=<registry> \
  --docker-username=<username> \
  --docker-password=<password-or-token> \
  -n <namespace>

Buat service account:

# Service account yang digunakan oleh predictor KServe
oc create sa model-puller-sa -n <namespace>

Asosiasikan pull secret dengan service account:

# Lampirkan pull secret — kedua perintah diperlukan:
# oc secrets link mencakup penggunaan secret secara umum;
# imagePullSecrets diperlukan khusus oleh init container ModelCar KServe
oc secrets link model-puller-sa model-registry-secret --for=pull -n <namespace>
oc patch serviceaccount model-puller-sa -n <namespace> \
  -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}'
Catatan:

Kedua perintah diperlukan. Entri imagePullSecrets digunakan oleh init container ModelCar selama pengambilan image model.

Buat ServingRuntime

Deploy ServingRuntime berbasis vLLM di namespace target:

apiVersion: serving.kserve.io/v1alpha1
kind: ServingRuntime
metadata:
  name: vllm-runtime
  namespace: <namespace>
spec:
  multiModel: false
  supportedModelFormats:
    - name: pytorch
      autoSelect: true
  containers:
    - name: kserve-container
      image: vllm/vllm-openai:<version>
      ports:
        - containerPort: 3000
          protocol: TCP
      livenessProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 30
        timeoutSeconds: 5
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3
      startupProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 60

Terapkan konfigurasi runtime:

oc apply -n <namespace> -f serving-runtime-vllm.yaml

Deploy InferenceService

Buat InferenceService yang merujuk image model OCI menggunakan URI penyimpanan oci://.

Persyaratan konfigurasi utama:

  • Rujuk ServingRuntime yang telah dibuat sebelumnya.
  • Tentukan lokasi image OCI di storageUri.
  • Konfigurasikan batas sumber daya CPU, memori, dan GPU yang sesuai dengan persyaratan model.
  • Pasang memori bersama (/dev/shm) untuk vLLM.
  • Konfigurasikan argumen runtime vLLM dan environment variable.

Contoh:

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: <model-name>
  annotations:
    serving.kserve.io/autoscalerClass: external
    serving.kserve.io/deploymentMode: RawDeployment
spec:
  predictor:
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
            - matchExpressions:
                - key: kubernetes.io/arch
                  operator: In
                  values:
                    - amd64
    tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
    volumes:
      - name: shm
        emptyDir:
          medium: Memory
          sizeLimit: 64Gi
    model:
      modelFormat:
        name: pytorch
      runtime: vllm-runtime
      storageUri: "oci://<registry>/<namespace-or-project>/<model-name>:latest"
      resources:
        requests:
          cpu: "<cpu-request>"          # mis. "8"
        limits:
          cpu: "<cpu-limit>"            # mis. "16"
          memory: <memory-limit>        # mis. 96Gi — sesuaikan dengan kebutuhan VRAM model
          nvidia.com/gpu: "<gpu-count>" # mis. "1"
      volumeMounts:
        - name: shm
          mountPath: /dev/shm
      args:
        - /mnt/models/
        - --served-model-name=<model-name>
        - --port=3000
        - --enable-auto-tool-choice
        - --tool-call-parser=openai
      env:
        - name: HOME
          value: /tmp
        - name: MAX_LOG_LEN
          value: "100"        # pangkas baris log vLLM untuk menghindari banjir log
        - name: HF_HUB_CACHE
          value: /tmp
        - name: TRITON_CACHE_DIR
          value: /tmp
        - name: XDG_CACHE_HOME
          value: /tmp
        - name: HF_HOME
          value: /tmp/hf_home
        - name: NUM_GPUS
          value: "<gpu-count>" # harus sesuai dengan batas nvidia.com/gpu di atas
        - name: CUDA_VISIBLE_DEVICES
          value: "<gpu-indices>" # mis. "0" untuk satu GPU; "0,1" untuk dua GPU
        - name: VLLM_WORKER_MULTIPROC_METHOD
          value: spawn
        - name: LOGNAME
          value: vllm
        - name: USER
          value: vllm

Terapkan manifes InferenceService:

oc apply -n <namespace> -f isvc-<model-name>.yaml

Verifikasi deployment

Pantau status deployment, startup pod, dan log runtime:

# Pantau InferenceService mencapai status Ready
oc get inferenceservice <model-name> -n <namespace> -w

# Pantau pod predictor menyala
oc get pods -n <namespace> -w

# Pantau log predictor (pemuatan model dapat memakan waktu beberapa menit setelah Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>

Saat InferenceService melaporkan READY: True, validasi endpoint.

Verifikasi pendaftaran model dan kirim permintaan inferensi uji coba:

POD=$(oc get pods -n <namespace> \
  -l app=isvc.<model-name>-predictor \
  -o jsonpath='{.items[0].metadata.name}')

oc exec -n <namespace> "$POD" -c kserve-container -- \
  curl -fsS http://127.0.0.1:3000/v1/models

oc exec -n <namespace> "$POD" -c kserve-container -- \
  curl -fsS http://127.0.0.1:3000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "<model-name>",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 50
  }'

Pemecahan masalah

MasalahKemungkinan penyebabResolusi
ErrImagePullKredensial registry hilang atau tidak validKonfirmasikan bahwa model-registry-secret ada, memiliki kredensial yang valid, dan ditautkan ke model-puller-sa menggunakan oc secrets link dan patch imagePullSecrets.
ImagePullBackOffImage pull secret tidak dikonfigurasi untuk ModelCarPastikan service account menyertakan konfigurasi imagePullSecrets. Jalankan oc patch serviceaccount model-puller-sa -n <namespace> -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}'
Predictor tetap dalam Init:0/1Pengunduhan image model sedang berlangsungPeriksa event oc describe pod untuk progres Pulling/Pulled; waktu penarikan sebanding dengan ukuran image dan bandwidth registry.
Predictor tetap dalam Init:0/1 tanpa batas waktuFile model tidak ditemukanVerifikasi bahwa file model disimpan di bawah /models dalam OCI image.
Engine core initialization failedWaktu kompilasi awal CUDA habis (timeout)Startup pertama dapat memakan waktu lebih lama saat cache dibuat. Restart dan coba lagi.
Pemuatan model gagalFormat file model tidak didukungGunakan file safetensors Hugging Face dan kecualikan checkpoint lama.
Error OpenSSL FIPS self-testContainer image tidak kompatibel dengan FIPSGunakan image vLLM yang kompatibel dengan FIPS.
OutOfMemory / OOMKilledMemori GPU tidak mencukupiTingkatkan sumber daya GPU, kurangi panjang konteks, atau gunakan model terkuantisasi (quantized).
InferenceService tetap PendingSumber daya cluster tidak tersediaVerifikasi ketersediaan GPU dan lepaskan sumber daya dari workload yang tidak digunakan.

Untuk informasi lebih lanjut, lihat:

Endpoint model public cloud

Gunakan opsi ini saat model di-host oleh penyedia cloud, seperti IBM watsonx, AWS Bedrock, Azure OpenAI, atau Google Vertex AI.

Prasyarat:

  • Konektivitas outbound HTTPS (port 443) dari cluster OpenShift ke endpoint layanan cloud.
  • API key yang valid, kredensial IAM, atau kredensial autentikasi yang setara.

Sebelum mengonfigurasi IBM Bob

Pastikan bahwa:

  • Deployment model telah diprovisikan dan aktif.
  • Kredensial autentikasi dibuat dan disimpan dengan aman.
  • Setiap persyaratan jaringan atau akses khusus penyedia telah dipenuhi.

Setelah endpoint tersedia, lanjutkan ke Mengonfigurasi Model Gateway.

Endpoint model infrastruktur privat

Gunakan opsi ini saat model di-host pada infrastruktur yang dikelola pelanggan di luar cluster IBM Bob, seperti:

  • Server GPU khusus
  • Cluster OpenShift terpisah
  • Server inferensi bare-metal
  • Platform AI enterprise

Prasyarat:

  • Endpoint model mengekspos API yang kompatibel dengan OpenAI.
  • Konektivitas HTTPS ada antara cluster IBM Bob dan endpoint.
  • Kredensial autentikasi tersedia sebagai Kubernetes secret.

Sebelum mengonfigurasi IBM Bob

Validasi hal berikut:

  • Konektivitas jaringan dari cluster ke endpoint.
  • Konfigurasi TLS atau mutual TLS, jika diperlukan.
  • Network policy dan firewall mengizinkan akses.
  • Autentikasi endpoint berfungsi dengan benar.

Setelah konektivitas dan autentikasi diverifikasi, lanjutkan ke Mengonfigurasi Model Gateway.

Bagaimana topik ini?