Infrastruktura do serwowania modeli

Dowiedz się, jak wdrażać i konfigurować punkty końcowe modeli, gdy Twoje środowisko nie zapewnia jeszcze rozwiązania do serwowania modeli.

Przed podłączeniem IBM Bob do dużego modelu językowego (LLM) musisz mieć dostęp do wdrożonego punktu końcowego modelu. Bob nie aprowizuje, nie hostuje ani nie zarządza infrastrukturą do serwowania modeli. Jeśli Twoja organizacja już zapewnia punkty końcowe modeli przez OpenShift AI, serwery wnioskowania z GPU, usługi AI w chmurze lub inne platformy wnioskowania, przejdź bezpośrednio do artykułu Konfiguracja bramy modelu.

Opcje wdrożenia

Wybierz opcję najlepiej pasującą do Twojego środowiska i wymagań operacyjnych.

OpcjaKiedy używać
OpenShift AI (on-cluster, OCI/ModelCar)Modele air-gapped lub samodzielnie hostowane; RHOAI już dostępne w klastrze
Chmura publicznaModele frontier przez AWS Bedrock, Azure OpenAI lub Google Vertex AI
Prywatna infrastrukturaModel serwowany na dedykowanych serwerach GPU lub dedykowanym klastrze wnioskowania

OpenShift AI (on-cluster, OCI/ModelCar)

Red Hat OpenShift AI (RHOAI) to zalecana platforma do serwowania modeli w klastrze, w tym wdrożeń air-gapped. Preferowanym podejściem do ładowania wag modelu jest wzorzec OCI/ModelCar: pliki modelu są wbudowane w obraz OCI w katalogu /models/ i przesyłane do prywatnego rejestru. Gdy InferenceService jest wdrażany, KServe wstrzykuje kontener init modelcar-init, który pobiera obraz i kopiuje wagi do współdzielonego woluminu w /mnt/models/, skąd następnie ładuje je środowisko uruchomieniowe (np. vLLM). Obraz modelu jest buforowany na węźle po pierwszym pobraniu — kolejne uruchomienia na tym samym węźle pomijają pobieranie.

Wymagania wstępne:

  • Operator Red Hat OpenShift AI zainstalowany w klastrze
  • KServe włączony i skonfigurowany
  • Węzły robocze z obsługą GPU z skonfigurowanym operatorem NVIDIA GPU (lub równoważnym)
  • CLI oc uwierzytelnione w docelowym klastrze z uprawnieniami do tworzenia zasobów w docelowej przestrzeni nazw
  • Prywatny rejestr kontenerów dostępny z klastra, z danymi uwierzytelniającymi do przesyłania do niego obrazów

Konfiguracja Red Hat OpenShift AI

Skonfiguruj zasoby DataScienceClusterInitialization i DataScienceCluster w następujący sposób:

  • Wyłącz serviceMesh.
  • Włącz KServe, ustawiając managementState: Managed.
  • Skonfiguruj KServe do używania trybu RawDeployment.
  • Usuń wszystkie nieużywane komponenty Red Hat OpenShift AI.

Przykładowa konfiguracja KServe:

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

Włączanie obsługi ModelCar

Obsługa ModelCar jest kontrolowana przez ConfigMap inferenceservice-config w przestrzeni nazw redhat-ods-applications. Klucz storageInitializer musi zawierać "enableModelcar": true.

Sprawdź bieżącą konfigurację:

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

Dane wyjściowe muszą zawierać:

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

Jeśli enableModelcar jest nieobecny lub false, zaktualizuj ConfigMap:

# Pobierz bieżącą wartość, scal flagę i zastosuj 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()))')}}"

Uruchom ponownie kontroler KServe, aby zastosować zmianę:

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

Pakowanie plików modelu w obraz OCI

Pobierz wagi modelu z Hugging Face i spakuj je w obraz OCI. Obraz musi mieć wszystkie pliki modelu w katalogu /models. Więcej informacji znajdziesz w dokumentacji KServe. W przypadku wdrożeń vLLM dołącz fragmenty modelu safetensors i wyklucz starsze pliki punktów kontrolnych, takie jak .bin, .pt i original/*.

Przykładowy Dockerfile:

FROM busybox:latest

# Wagi modelu — fragmenty safetensors i indeks
COPY <model-name>/model-*.safetensors         /models/
COPY <model-name>/model.safetensors.index.json /models/

# Konfiguracja modelu
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/

Jeśli model zawiera szablon czatu (na przykład chat_template.jinja), dodaj go. Alternatywnie skopiuj cały katalog jedną instrukcją — prościej, ale zawiera pliki niepotrzebne dla vLLM:

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

Przesyłanie obrazu do prywatnego rejestru

Prześlij obraz OCI do prywatnego rejestru kontenerów dostępnego z klastra:

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

Możesz użyć dowolnego obsługiwanego narzędzia do zarządzania obrazami, w tym:

  • Podman
  • Skopeo
  • Pipeline CI/CD
  • Narzędzia specyficzne dla rejestru

Tworzenie docelowej przestrzeni nazw i sekretu do pobierania obrazów

Utwórz przestrzeń nazw projektu i skonfiguruj dane uwierzytelniające do pobierania obrazu modelu:

oc new-project <namespace>

Utwórz sekret do pobierania z rejestru:

# Sekret do pobierania, aby KServe mógł pobrać obraz modelu z prywatnego rejestru
oc create secret docker-registry model-registry-secret \
  --docker-server=<registry> \
  --docker-username=<username> \
  --docker-password=<password-or-token> \
  -n <namespace>

Utwórz konto usługi:

# Konto usługi używane przez predyktor KServe
oc create sa model-puller-sa -n <namespace>

Powiąż sekret do pobierania z kontem usługi:

# Dołącz sekret do pobierania — oba polecenia są wymagane:
# oc secrets link obejmuje ogólne użycie sekretu;
# imagePullSecrets jest wymagane przez kontener init 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"}]}'
Uwaga:

Oba polecenia są wymagane. Wpis imagePullSecrets jest używany przez kontener inicjalizacyjny ModelCar podczas pobierania obrazu modelu.

Tworzenie ServingRuntime

Wdróż ServingRuntime oparty na vLLM w docelowej przestrzeni nazw:

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

Zastosuj konfigurację środowiska uruchomieniowego:

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

Wdrażanie InferenceService

Utwórz InferenceService, który odwołuje się do obrazu modelu OCI przy użyciu URI pamięci masowej oci://.

Kluczowe wymagania konfiguracyjne:

  • Odwołanie do wcześniej utworzonego ServingRuntime.
  • Określenie lokalizacji obrazu OCI w storageUri.
  • Konfiguracja limitów zasobów CPU, pamięci i GPU odpowiadających wymaganiom modelu.
  • Montowanie pamięci współdzielonej (/dev/shm) dla vLLM.
  • Konfiguracja argumentów środowiska uruchomieniowego vLLM i zmiennych środowiskowych.

Przykład:

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>"          # np. "8"
        limits:
          cpu: "<cpu-limit>"            # np. "16"
          memory: <memory-limit>        # np. 96Gi — dostosuj do wymagań VRAM modelu
          nvidia.com/gpu: "<gpu-count>" # np. "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"        # skraca wiersze dziennika vLLM, aby uniknąć zalewania logów
        - 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>" # musi odpowiadać limitowi nvidia.com/gpu powyżej
        - name: CUDA_VISIBLE_DEVICES
          value: "<gpu-indices>" # np. "0" dla pojedynczego GPU; "0,1" dla dwóch
        - name: VLLM_WORKER_MULTIPROC_METHOD
          value: spawn
        - name: LOGNAME
          value: vllm
        - name: USER
          value: vllm

Zastosuj manifest InferenceService:

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

Weryfikacja wdrożenia

Monitoruj stan wdrożenia, uruchamianie podów i dzienniki środowiska uruchomieniowego:

# Obserwuj, jak InferenceService osiąga stan Ready
oc get inferenceservice <model-name> -n <namespace> -w

# Obserwuj uruchamianie poda predyktora
oc get pods -n <namespace> -w

# Śledź dzienniki predyktora (ładowanie modelu może potrwać kilka minut po osiągnięciu stanu Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>

Gdy InferenceService zgłosi READY: True, sprawdź punkt końcowy.

Zweryfikuj rejestrację modelu i wyślij testowe żądanie wnioskowania:

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
  }'

Rozwiązywanie problemów

ProblemMożliwa przyczynaRozwiązanie
ErrImagePullBrakujące lub nieprawidłowe dane uwierzytelniające do rejestruSprawdź, czy model-registry-secret istnieje, ma prawidłowe dane uwierzytelniające i jest powiązany z model-puller-sa przy użyciu zarówno oc secrets link, jak i patcha imagePullSecrets.
ImagePullBackOffSekret do pobierania obrazów nie jest skonfigurowany dla ModelCarUpewnij się, że konto usługi zawiera konfigurację imagePullSecrets. Uruchom oc patch serviceaccount model-puller-sa -n <namespace> -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}'
Predyktor pozostaje w stanie Init:0/1Pobieranie obrazu modelu w tokuSprawdź zdarzenia oc describe pod dla postępu Pulling/Pulled; czas pobierania zależy od rozmiaru obrazu i przepustowości rejestru.
Predyktor pozostaje w stanie Init:0/1 przez dłuższy czasNie znaleziono plików modeluSprawdź, czy pliki modelu są przechowywane w katalogu /models w obrazie OCI.
Engine core initialization failedPrzekroczenie limitu czasu wstępnej kompilacji CUDAPierwsze uruchomienie może trwać dłużej podczas generowania pamięci podręcznych. Uruchom ponownie i spróbuj ponownie.
Ładowanie modelu nie powiedzie sięNieobsługiwany format pliku modeluUżyj plików safetensors z Hugging Face i wyklucz starsze punkty kontrolne.
Błędy autotestu FIPS OpenSSLObraz kontenera nie jest zgodny z FIPSUżyj obrazu vLLM zgodnego z FIPS.
OutOfMemory / OOMKilledNiewystarczająca pamięć GPUZwiększ zasoby GPU, zmniejsz długość kontekstu lub użyj modelu skwantyzowanego.
InferenceService pozostaje w stanie PendingZasoby klastra niedostępneSprawdź dostępność GPU i zwolnij zasoby z nieużywanych obciążeń.

Więcej informacji można znaleźć w:

Punkty końcowe modeli w chmurze publicznej

Użyj tej opcji, gdy modele są hostowane przez dostawcę chmurowego, takiego jak IBM watsonx, AWS Bedrock, Azure OpenAI lub Google Vertex AI.

Wymagania wstępne:

  • Wychodząca łączność HTTPS (port 443) z klastra OpenShift do punktu końcowego usługi chmurowej.
  • Prawidłowe klucze API, dane uwierzytelniające IAM lub równoważne dane uwierzytelniające.

Przed skonfigurowaniem IBM Bob

Upewnij się, że:

  • Wdrożenie modelu jest aprowizowane i aktywne.
  • Dane uwierzytelniające są wygenerowane i bezpiecznie przechowywane.
  • Wszelkie specyficzne dla dostawcy wymagania sieciowe lub dostępowe są spełnione.

Po udostępnieniu punktu końcowego przejdź do artykułu Konfiguracja bramy modelu.

Punkty końcowe modeli w prywatnej infrastrukturze

Użyj tej opcji, gdy modele są hostowane w infrastrukturze zarządzanej przez klienta poza klastrem IBM Bob, takiej jak:

  • Dedykowane serwery GPU
  • Oddzielne klastry OpenShift
  • Serwery wnioskowania na bare-metal
  • Korporacyjne platformy AI

Wymagania wstępne:

  • Punkt końcowy modelu udostępnia API zgodne z OpenAI.
  • Istnieje łączność HTTPS między klastrem IBM Bob a punktem końcowym.
  • Dane uwierzytelniające są dostępne jako sekrety Kubernetes.

Przed skonfigurowaniem IBM Bob

Sprawdź następujące elementy:

  • Łączność sieciowa z klastra do punktu końcowego.
  • Konfiguracja TLS lub wzajemnego TLS, jeśli jest wymagana.
  • Zasady sieciowe i zapory zezwalają na dostęp.
  • Uwierzytelnianie punktu końcowego działa poprawnie.

Po zweryfikowaniu łączności i uwierzytelniania przejdź do artykułu Konfiguracja bramy modelu.

Jak oceniasz ten temat?