Теперь запускаем модель при помощи KServe на GPU
Совсем недавно мы писали статью про то, как запустить в кластере k8s сервис Kserve и продемонстрировали запуск в нём инференса модели Qwen3. Но запуск мы осуществляли на CPU и ждать ответа нам приходилось больше минуты.
Теперь давайте немного дополним прошлую статью и покажем, как запускать инференс в Kserve при помощи GPU (в данном случае Nvidia). И сравнив производительность с запуском на CPU.
В этот раз для тестирования нам достался сервер Huawei 2288H V5, имеющий следующие характеристики:
- 2 CPU Intel(R) Xeon(R) Gold 5118 CPU @ 2.30GHz
- 256 Гб ОП
- 2 SAS диска ST600MM0009
- видеокарта NVIDIA Corporation GV100GL [Tesla V100 PCIe 16GB] (rev a1)
- ОС: openScaler 24.03 LTS SP2
- ядро: 6.6.0-108.0.0.114.os2403sp2.x86_64
У нас уже развёрнут на этом сервере k8s (один узел — он же мастер, он же рабочий), поэтому мы не будем в 2025 году утомлять вас рассказом «как ставить k8s».
Для начала, мы установим в k8s GPU-оператор https://github.com/NVIDIA/gpu-operator , который позволит использовать внутри кластера k8s драйвера nvidia.
Установку будем производить при помощи helm:
helm repo add NVIDIA https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install --wait --generate-name -n gpu-operator --create-namespace NVIDIA/gpu-operator
Проверяем что драйвер установлен корректно:
kubectl -n gpu-operator exec -it gpu-feature-discovery-tckgl -- nvidia-smi
Defaulted container “gpu-feature-discovery” out of: gpu-feature-discovery, toolkit-validation (init)
Wed Oct 15 10:41:16 2025
+-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.82.07 Driver Version: 580.82.07 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 Tesla V100-PCIE-16GB Off | 00000000:3B:00.0 Off | 0 | | N/A 42C P0 29W / 250W | 0MiB / 16384MiB | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ | 1 Tesla V100-PCIE-16GB Off | 00000000:86:00.0 Off | 0 | | N/A 40C P0 27W / 250W | 0MiB / 16384MiB | 0% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | No running processes found | +-----------------------------------------------------------------------------------------+
Теперь подготовим 2 yaml манифеста для запуска инференсов.
Один для CPU:
apiVersion: serving.kserve.io/v1beta1 kind: InferenceService metadata: name: huggingface-qwen3-cpu spec: predictor: model: modelFormat: name: huggingface args: - --model_name=qwen3 - --model_id=Qwen/Qwen3-1.7B - --max-model-len=16384 resources: limits: cpu: "6" memory: 24Gi requests: cpu: "6" memory: 24Gi
И манифест для запуска на nvidia:
apiVersion: serving.kserve.io/v1beta1 kind: InferenceService metadata: name: huggingface-qwen3-nvidia spec: predictor: model: modelFormat: name: huggingface args: - --model_name=qwen3 - --model_id=Qwen/Qwen3-1.7B - --max-model-len=16384 - --dtype=half resources: limits: cpu: "6" memory: 24Gi nvidia.com/gpu: "1" requests: cpu: "6" memory: 24Gi nvidia.com/gpu: "1"
Как вы видите, мы выделили 1 ядро nvidia для работы нашего инференса.
Для внешнего доступа (мы же ленивые) просто сделаем 2 службы типа NodePort и будем получать доступ к инференсам просто меняя в команде curl номер порта.
Служба для доступа к инференсу на CPU:
apiVersion: v1 kind: Service metadata: name: huggingface-qwen3-predictor-np-cpu namespace: default spec: ports: - name: http port: 80 protocol: TCP nodePort: 30123 targetPort: 8012 selector: serving.kserve.io/inferenceservice: huggingface-qwen3-cpu sessionAffinity: None type: NodePort
Служба для доступа к инференсу на Nvidia:
apiVersion: v1 kind: Service metadata: name: huggingface-qwen3-predictor-np-nvidia namespace: default spec: ports: - name: http port: 80 protocol: TCP nodePort: 30124 targetPort: 8012 selector: serving.kserve.io/inferenceservice: huggingface-qwen3-nvidia sessionAffinity: None type: NodePort
Собственно, всё! Запускаем наши инференсы (привычно применяем указанные выше файлы при помощи утилиты kubectl), ждём когда контейнеры запустятся и скачают модель из репозитория. Дождавшись приступаем к проверке.
Сначала зададим (уже набивший оскомину) вопрос про Марка Твена модели запущенной на CPU:
time curl -v http://172.17.3.6:30123/openai/v1/completions -H "content-type: application/json" -H "Host: huggingface-qwen3-qwen-test.example.com" -d '{"model": "qwen3", "prompt": "who is Mark Twen?", "stream":false, "max_tokens": 40}' * Trying 172.17.3.6:30123... * Connected to 172.17.3.6 (172.17.3.6) port 30123 * using HTTP/1.x > POST /openai/v1/completions HTTP/1.1 > Host: huggingface-qwen3-qwen-test.example.com > User-Agent: curl/8.14.1 > Accept: */* > content-type: application/json > Content-Length: 83 > * upload completely sent off: 83 bytes < HTTP/1.1 200 OK < Content-Length: 466 < Content-Type: application/json < Date: Wed, 15 Oct 2025 11:21:39 GMT < Server: uvicorn < * Connection #0 to host 172.17.3.6 left intact {"id":"cmpl-5f1d21458f374c90bc456be7dbf9ba22","object":"text_completion","created":1760527300, "model":"qwen3","choices":[{"index":0,"text":" Mark Twain, also known as Samuel Clemens (1835–1910), was an American author, humorist, and social critic. He is best known for his novels", "logprobs":null,"finish_reason":"length","stop_reason":null,"prompt_logprobs":null}], "usage":{"prompt_tokens":6,"total_tokens":46,"completion_tokens":40,"prompt_tokens_details":null}} real 0m23,462s user 0m0,014s sys 0m0,013s
Как вы видите, ответ занял целых 23 секунды.
Что же, теперь спросим у модели на GPU:
time curl -v http://172.17.3.6:30124/openai/v1/completions -H "content-type: application/json" -H "Host: huggingface-qwen3-qwen-test.example.com" -d '{"model": "qwen3", "prompt": "who is Mark Twen?", "stream":false, "max_tokens": 40}' * Trying 172.17.3.6:30124... * Connected to 172.17.3.6 (172.17.3.6) port 30124 * using HTTP/1.x > POST /openai/v1/completions HTTP/1.1 > Host: huggingface-qwen3-qwen-test.example.com > User-Agent: curl/8.14.1 > Accept: */* > content-type: application/json > Content-Length: 83 > * upload completely sent off: 83 bytes < HTTP/1.1 200 OK < Content-Length: 472 < Content-Type: application/json < Date: Wed, 15 Oct 2025 11:22:10 GMT < Server: uvicorn < * Connection #0 to host 172.17.3.6 left intact {"id":"cmpl-e8f14ea6af1d4e32afe9fc6e7ed894f8","object":"text_completion", "created":1760527331,"model":"qwen3","choices":[{"index":0,"text":" Mark Twain, often referred to as the "Scribe of the South," was an American author, humorist, and social critic. He was born in 1835 and died in", "logprobs":null,"finish_reason":"length","stop_reason":null,"prompt_logprobs":null}], "usage":{"prompt_tokens":6,"total_tokens":46,"completion_tokens":40,"prompt_tokens_details":null}} real 0m0,571s user 0m0,006s sys 0m0,004s
Как говорится, прибавить к этому ответу нечего, всё наглядно и так 🙂