SuperAPI AI Directory

vss-deploy-helm

Deployment & operations

View repository

Updated 10-16 02:39

About this skill

VSS Helm deploy

Use this workflow for the VSS sample app Helm chart at sample-applications/video-search-and-summarization/chart. The chart’s real dependencies are ovms, minioserver, audioanalyzer, postgresql, rabbitmq, videoingestion, videosearch, vdmsvectordb, multimodaldataprep, multimodalembeddingms, vectorretriever, vllm (alias of vllm-server), summaryui, and searchui (aliases of vssui).

If the user asks to map Compose or setup.sh settings to Helm values, read references/helm-values-map.md.

Environment setup (run first)

This skill drives the Video Search & Summarization app through its real source files, so the VSS application must be present and you must run commands from its app root. Do this before anything else, and it works whether or not the VSS source is already in your workspace.

Run the bundled bootstrap. It first tries to find an existing VSS checkout - walking up from the current directory and inspecting the enclosing git repo - and reuses it without ever re-cloning. Only when no checkout is found does it do a shallow, single-branch, sparse checkout of just sample-applications/video-search-and-summarization from main. It prints the resolved app root on stdout:

# SKILL_DIR is THIS skill's own directory (shown to you when the skill loads);
# in-repo it is .github/skills/vss-deploy-helm. Works the same if the skill is installed standalone.
SKILL_DIR=".github/skills/vss-deploy-helm"
APP_ROOT="$(bash "$SKILL_DIR/scripts/vss-bootstrap.sh")"
cd "$APP_ROOT"

Every command below assumes the working directory is this APP_ROOT. To pull from a fork/branch or reuse a specific checkout dir, override VSS_REPO_URL, VSS_REPO_BRANCH, or VSS_CLONE_DIR before running it.

Prerequisites

  1. Confirm a reachable Kubernetes cluster, kubectl, and Helm 3:
    kubectl cluster-info
    kubectl get nodes
    helm version
    
  2. Confirm dynamic PV provisioning if using PVCs:
    kubectl get storageclass
    
  3. For GPU/NPU, discover resource keys before writing values:
    kubectl get nodes -o json | jq -r '.items[] | "\(.metadata.name):\n" + (.status.allocatable | to_entries | map(select(.key | test("gpu|npu|vpu|accel";"i"))) | map("  \(.key): \(.value)") | join("\n"))'
    
    Common Intel keys are gpu.intel.com/i915, gpu.intel.com/xe, and npu.intel.com/accel.

1. Start from the real chart values

Work from the chart directory:

cd sample-applications/video-search-and-summarization/chart
helm dependency update
helm dependency list

Create/edit user_values_override.yaml for user-specific values. Do not commit filled secrets.

Minimum required values for most modes:

global:
  usePvc: true
  keepPvc: true
  huggingfaceToken: "hf_..."   # needed for gated/private Hugging Face models
  vlmName: "Qwen/Qwen3-VL-4B-Instruct"
  llmName: ""                  # optional OVMS split-model summarization model
  embeddingModelName: ""       # set per mode below
  modelDownload:
    image:
      repository: intel/model-download
      tag: "2026.2.0-ww30"
      pullPolicy: IfNotPresent
    ovmsReleaseTag: "v2026.1"
  proxy:
    http_proxy: ""
    https_proxy: ""
  env:
    POSTGRES_USER: "vsadmin"
    POSTGRES_PASSWORD: "change-me"
    MINIO_ROOT_USER: "minioadmin"
    MINIO_ROOT_PASSWORD: "change-me-8chars"
    RABBITMQ_DEFAULT_USER: "guest"
    RABBITMQ_DEFAULT_PASS: "change-me"

# Summary/OVMS model workspace:
ovms:
  claimSize: "20Gi"

# Search model caches (needed only when search is enabled):
multimodaldataprep:
  modelPvc:
    enabled: true
    size: "10Gi"
multimodalembeddingms:
  modelPvc:
    enabled: true
    size: "10Gi"

Why these matter:

  • global.usePvc enables the service-specific claims; OVMS, video-ingestion, Multimodal DataPrep, and the embedding service no longer share one PVC.
  • global.keepPvc: true avoids re-downloading/re-converting models after uninstall, but stale PVCs can also preserve incompatible old state. The vLLM subchart's vllm-model-cache PVC does not currently honor global.keepPvc and is deleted with the release.
  • ovms.claimSize sizes the summary-mode OVMS model workspace.
  • multimodaldataprep.modelPvc and multimodalembeddingms.modelPvc independently configure search model caches.
  • global.vlmName is required for summary/unified modes and is used by OVMS or by vLLM.
  • global.embeddingModelName is required when search components are enabled.
  • global.modelDownload controls the image used by the OVMS and video-ingestion init containers. Each init container starts its local REST service, submits a download job, waits for completion, and exits before the application container starts.

2. Choose the mode using the real override files

Use exactly these chart override files:

Docker/setup concept Helm command files What the chart enables
source setup.sh --summary -f summary_override.yaml -f user_values_override.yaml rabbitmq, ovms, videoingestion, audioanalyzer, summaryui; pipelinemanager.env.SUMMARY_FEATURE=FEATURE_ON
--summary with ENABLE_VLLM=true -f summary_override.yaml -f xeon_vllm_values.yaml -f user_values_override.yaml summary mode plus vllm.enabled=true, ovms.enabled=false, pipelinemanager.env.USE_VLLM=CONFIG_ON
source setup.sh --search -f search_override.yaml -f user_values_override.yaml multimodalembeddingms, multimodaldataprep, vdmsvectordb, vectorretriever, videosearch, searchui; global.vdmsIndexName=video_frame_embeddings
VECTORDB_BACKEND=milvus + source setup.sh --search -f search_override.yaml -f search_milvus_override.yaml -f user_values_override.yaml switches search backend to Milvus (global.vectordbBackend=milvus), enables milvusstandalone, disables vdmsvectordb, keeps multimodaldataprep + vectorretriever + videosearch
--summary-and-search / --all / --unified -f unified_summary_search.yaml -f user_values_override.yaml combined search+summary in one summaryui named unified-ui; global.vdmsIndexName=video_summary_embeddings
unified with vLLM -f unified_summary_search.yaml -f xeon_vllm_values.yaml -f user_values_override.yaml unified mode plus vLLM backend
dual separate UIs -f summary_override.yaml -f search_override.yaml -f user_values_override.yaml both summaryui and searchui; nginx routes /summary/ and /search/

Embedding model rule:

  • Search-only and dual UI use a multimodal embedding model, for example global.embeddingModelName: "CLIP/clip-vit-b-32".
  • Unified summary+search uses a text embedding model, for example global.embeddingModelName: "QwenText/qwen3-embedding-0.6b".

3. Install

Create a namespace once:

export NAMESPACE=vss-deployment
kubectl create namespace "$NAMESPACE"

Summary with OVMS CPU:

helm install vss . \
  -f summary_override.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

Summary with vLLM on Xeon CPU:

helm install vss . \
  -f summary_override.yaml \
  -f xeon_vllm_values.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

Search only:

helm install vss . \
  -f search_override.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

Unified summary+search:

helm install vss . \
  -f unified_summary_search.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

Dual separate UIs:

helm install vss . \
  -f summary_override.yaml \
  -f search_override.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

Before switching modes, uninstall the release first because the enabled subcharts and UI routing change:

helm uninstall vss -n "$NAMESPACE"

4. GPU/NPU and vLLM values

OVMS GPU VLM example:

global:
  vlmName: "OpenVINO/Phi-3.5-vision-instruct-int8-ov"
  devices:
    ovms:
      vlm:
        device: GPU
        key: "gpu.intel.com/i915"
      llm:
        device: CPU
        key: ""

OVMS split model, e.g. GPU VLM + NPU LLM:

global:
  vlmName: "OpenVINO/Phi-3.5-vision-instruct-int8-ov"
  llmName: "OpenVINO/Qwen3-8B-int4-cw-ov"
  devices:
    ovms:
      vlm:
        device: GPU
        key: "gpu.intel.com/i915"
      llm:
        device: NPU
        key: "npu.intel.com/accel"
ovms:
  env:
    VLM_WEIGHT_FORMAT: ""   # auto: CPU int8, GPU/NPU int4
    LLM_WEIGHT_FORMAT: ""

Search GPU for embedding/dataprep:

global:
  devices:
    multimodalEmbedding:
      device: GPU
      key: "gpu.intel.com/i915"
    multimodalDataprep:
      embedding:
        device: GPU
        key: "gpu.intel.com/i915"
      detection:
        device: CPU
        key: ""

Use global.devices.multimodalDataprep.embedding for in-process DataPrep embedding, global.devices.multimodalEmbedding for the query-side embedding service, and global.devices.multimodalDataprep.detection for DataPrep object detection. These settings are independent; every GPU/NPU setting requires its own resource key.

vLLM tuning keys from the actual vllm subchart:

vllm:
  enabled: true
  pvc:
    size: 80Gi
  env:
    vllmCpuKvCacheSpace: "48"
    vllmRpcTimeout: "100000"
    vllmAllowLongMaxModelLen: "1"
    vllmEngineIterationTimeoutS: "120"
    vllmCpuNumReservedCpu: "0"
    vllmLoggingLevel: "INFO"
  model:
    dtype: bfloat16
    maxModelLen: 32000
    maxNumBatchedTokens: 2048
    maxNumSeqs: 256
    tensorParallelSize: 1
  resources:
    requests:
      cpu: "16"
      memory: 128Gi
    limits:
      cpu: "16"
      memory: 128Gi

Prefer using xeon_vllm_values.yaml rather than hand-setting all of this; it also sets pipelinemanager.env.USE_VLLM=CONFIG_ON and resource requests for dependent services.

5. Upgrade safely

After editing values, keep the same override-file stack used at install:

helm upgrade vss . \
  -f summary_override.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

For vLLM summary:

helm upgrade vss . \
  -f summary_override.yaml \
  -f xeon_vllm_values.yaml \
  -f user_values_override.yaml \
  -n "$NAMESPACE"

If changing subchart code or dependencies:

helm dependency update

6. Verify

Watch pods; first startup may take 20–50 minutes because models are downloaded/converted:

kubectl get pods -n "$NAMESPACE" -w
kubectl get svc -n "$NAMESPACE"

Get the NodePort URL. The release name vss makes nginx service vss-nginx:

VSS_HOST=$(kubectl get pods -l app=vss-nginx -n "$NAMESPACE" -o jsonpath='{.items[0].status.hostIP}')
VSS_PORT=$(kubectl get service vss-nginx -n "$NAMESPACE" -o jsonpath='{.spec.ports[0].nodePort}')
echo "http://${VSS_HOST}:${VSS_PORT}"

UI paths:

  • Summary/search/unified singleton modes: /
  • Dual UI mode: /summary/ and /search/; root redirects to /summary/

Check logs for slow or failed startup:

kubectl logs -n "$NAMESPACE" deploy/vss-pipelinemanager
kubectl logs -n "$NAMESPACE" deploy/vss-nginx
kubectl get events -n "$NAMESPACE" --sort-by=.lastTimestamp

When OVMS or video ingestion is stuck in Init, inspect the pod's model-download init container:

kubectl describe pod -n "$NAMESPACE" <pod-name>
kubectl logs -n "$NAMESPACE" <ovms-pod> -c download-vlm
kubectl logs -n "$NAMESPACE" <ovms-pod> -c download-llm   # split-model mode only
kubectl logs -n "$NAMESPACE" <video-ingestion-pod> -c od-model-downloader

OVMS metrics, when ovms.enabled=true:

kubectl port-forward svc/vss-nginx 8081:80 -n "$NAMESPACE"
curl http://localhost:8081/ovms/metrics

7. Common fixes

  • Helm fails with missing credentials: fill global.env.POSTGRES_USER, global.env.POSTGRES_PASSWORD, global.env.MINIO_ROOT_USER, global.env.MINIO_ROOT_PASSWORD, global.env.RABBITMQ_DEFAULT_USER, global.env.RABBITMQ_DEFAULT_PASS.
  • Helm fails with GPU key errors: set global.devices.*.key for every non-CPU device.
  • Model download job/init container fails: inspect the specific model-download log, verify global.modelDownload.image, proxy/token values, model id, device support, and available model storage before debugging the main container.
  • Helm fails with a missing device key: set the matching key for any global.devices.* entry set to GPU or NPU.
  • Search returns bad/no results: confirm global.embeddingModelName matches the mode and global.vdmsIndexName came from the right override file.
  • Reinstall still broken with global.keepPvc: true: stale PVC contents may be incompatible. Identify the affected mode and delete only its PVCs after the user accepts losing cached models/data.:
    # Summary with OVMS:
    kubectl delete pvc vss-ovms-pvc -n "$NAMESPACE"
    
    # Search model caches:
    kubectl delete pvc vss-multimodaldataprep-models-pvc \
      vss-multimodalembeddingms-models-pvc -n "$NAMESPACE"
    
  • Need larger storage: set ovms.claimSize for converted VLM/LLM models, videoingestion.claimSize for OD models, multimodaldataprep.modelPvc.size/multimodalembeddingms.modelPvc.size for search model caches, or the relevant data setting such as minioserver.claimSize, postgresql.claimSize, vdmsvectordb.claimSize, or vllm.pvc.size.