Deploy with the Operator#
The Holoscan for Media operator for VSR NIM manages the VSR NIM media function through a Kubernetes custom resource.
Use the operator when you want a CR-driven deployment model that reconciles the VSR NIM deployment, ConfigMaps, SDP data, Rivermax configuration, Multus networking, and NMOS settings.
What the Operator Creates#
When you apply a NvidiaVsrNimMediaFunction custom resource, the operator creates and manages the following components:
Component |
Description |
|---|---|
Deployment |
Runs the VSR NIM media function container with GPU, Multus networking, Rivermax, NMOS, and ST 2110 configuration. |
|
Contains |
|
Exposes generated SDP payloads by endpoint name for inspection and downstream tooling. |
Status updates |
Tracks provisioning, configuration, NMOS registration, NMOS connection state, and managed resources. |
The operator manages only the VSR NIM media function. Source and receiver endpoints must be provided by existing ST 2110 equipment, platform services, or the sample Helm chart with its VSR service disabled.
Provide Source and Receiver Endpoints#
The operator does not create a test-pattern source or output-file receiver. Use existing ST 2110/NMOS equipment, platform services, or the packaged sample chart for the endpoints around the operator-managed VSR NIM pod.
For local validation with the sample chart, complete the operator installation workflow to create the operator-managed VSR NIM deployment. After the NvidiaVsrNimMediaFunction CR creates the VSR NIM pod, deploy the sample receiver from the sample chart archive in the same namespace as the custom resource. The following sample chart command intentionally disables its own VSR service and sample sender. Set NAMESPACE, SECRET_NAME, and NODE_HOSTNAME for your cluster before running the command:
helm upgrade --install vsr-nim-io \
nvidia-vsr-nim-h4m-sample-1.0.10.tgz \
-n "${NAMESPACE}" \
--create-namespace \
--set nvidia-vsr-nim-h4m-service.enabled=false \
--set receiver.enabled=true \
--set sender.enabled=false \
--set receiver.image.secret="${SECRET_NAME}" \
--set receiver.nodeSelector.hostname="${NODE_HOSTNAME}"
Wait for the sample receiver and the CR-created VSR NIM pod to be ready, and then enable the sample sender:
helm upgrade --install vsr-nim-io \
nvidia-vsr-nim-h4m-sample-1.0.10.tgz \
-n "${NAMESPACE}" \
--reuse-values \
--set sender.enabled=true \
--set nvidia-vsr-nim-h4m-service.enabled=false \
--set sender.image.secret="${SECRET_NAME}" \
--set receiver.image.secret="${SECRET_NAME}" \
--set sender.nodeSelector.hostname="${NODE_HOSTNAME}" \
--set receiver.nodeSelector.hostname="${NODE_HOSTNAME}"
If the cluster does not run topo-aware-scheduler, add --set h4m.schedulerName="" to both sample chart commands. For static ST 2110 validation, pass the sample chart values-st2110.yaml overlay and keep the sample chart transport values aligned with the operator CR.
In NMOS mode, enabling the sample sender does not start media flow by itself. Use the NMOS controller to connect the sample sender to the operator-managed VSR input, and then connect the VSR output to the sample receiver.
Pull the Operator Chart#
ngc config set
ngc registry chart pull nim/nvidia/nvidia-vsr-nim-h4m-operator:1.0.10
Install the Operator#
helm upgrade --install vsr-nim-operator \
nvidia-vsr-nim-h4m-operator-1.0.10.tgz \
-n <operator-namespace> \
--create-namespace
If the operator image requires a pull secret, set it in the operator chart values:
helm upgrade --install vsr-nim-operator \
nvidia-vsr-nim-h4m-operator-1.0.10.tgz \
-n <operator-namespace> \
--create-namespace \
--set imagePullSecrets[0].name=<secret-name>
If generated media function pods should use a default pull secret when the CR omits spec.parameters.imagePullSecrets, set it in the operator chart values:
helm upgrade --install vsr-nim-operator \
nvidia-vsr-nim-h4m-operator-1.0.10.tgz \
-n <operator-namespace> \
--create-namespace \
--set mediaFunction.imagePullSecrets[0].name=<secret-name>
The pull secret for the operator image and the pull secret for generated VSR NIM media function pods are separate settings. A CR-level spec.parameters.imagePullSecrets value overrides the chart-level media function default for that CR.
Wait for the operator:
kubectl rollout status deployment \
-n <operator-namespace> \
-l app.kubernetes.io/instance=vsr-nim-operator \
--timeout=180s
Create a Media Function#
Create a NvidiaVsrNimMediaFunction custom resource. The CR defines:
One ST 2110-20 video input.
One ST 2110-20 video output.
NMOS or inline SDP control.
VSR processing parameters.
GPU, network, Rivermax, logging, security, resources, and scheduler settings.
Example CR for NMOS mode:
apiVersion: nvidia.com/v1alpha1
kind: NvidiaVsrNimMediaFunction
metadata:
name: vsr-nim-nmos
namespace: <namespace>
labels:
nvidia.com/holoscan-for-media.production: <production-name>
nvidia.com/holoscan-for-media.pipeline: 720-to-4K
spec:
schedulerName: topo-aware-scheduler
nodeSelector:
kubernetes.io/hostname: <gpu-node-name>
inputs:
video_input:
control:
nmos: {}
transport:
rtp: {}
format:
video:
media_type: video/raw
frame_width: 1280
frame_height: 720
frame_rate: "30"
interlace_mode: progressive
color_sampling: "YCbCr-4:2:2"
component_depth: 10
colorspace: BT709
transfer_characteristic: SDR
parameters:
localInterfaceName: net1
udp:
headerSize: 20
payloadSize: 800
useRtpTimestamp: true
ptpSrc: set
outputs:
video_output:
control:
nmos: {}
transport:
rtp: {}
format:
video:
media_type: video/raw
frame_width: 3840
frame_height: 2160
frame_rate: "30"
interlace_mode: progressive
color_sampling: "YCbCr-4:2:2"
component_depth: 10
colorspace: BT709
transfer_characteristic: SDR
parameters:
localInterfaceName: net2
udp:
payloadSize: 1220
packetsPerLine: 8
outputQueueMaxBuffers: 0
sync: false
async: false
passRtpTimestamp: true
rtpTimestampOffset: 2000000
ptpSrc: set
parameters:
nmosHttpPort: 8980
nmosLabel: "VSR NIM"
nmosDescription: "ST2110-20 video sender and receiver with 720p-to-4K upscaling"
nmosDomain: local
nmosSystemUrl: ""
nmosSeed: vsr-nim-sample
gstDebug: "2,nvdsnmosbin:8,nvnmos:2,nvdssdp*:8"
gpuId: "0"
glogVerbosity: "1"
rivermaxTxAdaptiveSchedulingFactor: "1.005"
rivermaxBurst: 4
imagePullSecrets:
- name: <secret-name>
rivermaxLicenseSecret: rivermax-license
highSpeedNetwork:
- name: media-a-rx-net
- name: media-a-tx-net
vsr:
srEnable: true
hqsr: true
srLevel: ultra
denoiseEnable: false
denoiseLevel: ultra
deblurEnable: false
deblurLevel: ultra
noiseInjectEnable: false
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
privileged: false
allowPrivilegeEscalation: true
capabilities:
add:
- IPC_LOCK
- NET_RAW
- SYS_NICE
- DAC_READ_SEARCH
drop:
- ALL
resources:
limits:
cpu: "4"
memory: 8Gi
hugepages-2Mi: 4Gi
nvidia.com/gpu: "1"
requests:
cpu: "4"
memory: 8Gi
hugepages-2Mi: 4Gi
nvidia.com/gpu: "1"
VSR NIM ST 2110 SDP generation supports SDR transfer characteristics in this release. Use transfer_characteristic: SDR.
The operator chart uses global.h4m.pipeline: "720-to-4K" as the default nvidia.com/holoscan-for-media.pipeline label for generated VSR NIM pods. To override labels for a specific media function, set these labels on the NvidiaVsrNimMediaFunction metadata:
metadata:
labels:
nvidia.com/holoscan-for-media.production: <production-name>
nvidia.com/holoscan-for-media.pipeline: <pipeline-name>
Apply the CR:
kubectl apply -f vsr-nim-media-function.yaml
On Red Hat OpenShift, replace kubectl with oc.
High-Speed Network Resource Pools#
The operator configures Multus network attachments for ST 2110 media transport through spec.parameters.highSpeedNetwork.
If highSpeedNetwork is omitted, the operator uses the following values:
parameters:
highSpeedNetwork:
- name: media-a-rx-net
- name: media-a-tx-net
The first attachment becomes the first secondary interface in the pod, typically net1, and the second attachment becomes net2. Keep spec.inputs.<name>.parameters.localInterfaceName and spec.outputs.<name>.parameters.localInterfaceName aligned with that order.
Set resourceName when the cluster exposes named SR-IOV device-plugin resources. If an attachment needs more than one virtual function, set resourceCount; it defaults to 1 when resourceName is present.
On clusters with single-numa-node topology requirements, configure highSpeedNetwork[].resourceName and resourceCount so the VSR pod can allocate the GPU, hugepages, and SR-IOV virtual functions from a compatible NUMA zone.
On clusters in which both VSR interfaces must use the same NUMA-local SR-IOV pool, list the same NetworkAttachmentDefinition twice and set the same device-plugin resource on each attachment:
spec:
inputs:
video_input:
parameters:
localInterfaceName: net1
outputs:
video_output:
parameters:
localInterfaceName: net2
parameters:
highSpeedNetwork:
- name: media-b-rx-net
resourceName: openshift.io/media_b_rx_pool
- name: media-b-rx-net
resourceName: openshift.io/media_b_rx_pool
The generated VSR pod still receives two in-pod interfaces. Use the repeated-entry form when you need two distinct interfaces. Use a single entry with resourceCount: 2 only when your media function and CNI setup intentionally use one in-pod interface:
spec:
parameters:
highSpeedNetwork:
- name: media-b-rx-net
resourceName: openshift.io/media_b_rx_pool
resourceCount: 2
Do not collapse separate RX and TX pools into one logical resource unless the cluster exposes one shared pool. On single-numa-node clusters, hiding the resource split can cause scheduler or kubelet topology placement failures.
Verify#
Check the custom resource:
kubectl get nvidiavsrnimmediafunction -n <namespace>
kubectl describe nvidiavsrnimmediafunction <cr-name> -n <namespace>
Check the generated deployment:
kubectl rollout status deployment/<cr-name> -n <namespace> --timeout=180s
kubectl logs -n <namespace> -l app.kubernetes.io/instance=<cr-name> -f
Check operator logs:
kubectl logs -n <operator-namespace> \
-l control-plane=controller-manager
Useful status fields include the following:
status.conditionsstatus.inputs.video_input.controlstatus.outputs.video_output.controlstatus.managed_resources
If the generated VSR NIM pod stays Pending, inspect pod events:
oc describe pod -n <namespace> -l app.kubernetes.io/instance=<cr-name>
Common causes include a missing NetworkAttachmentDefinition, an unavailable spec.schedulerName, insufficient GPU or hugepage capacity, unavailable SR-IOV device resources, or GPU and SR-IOV pool resources that cannot be placed on the same NUMA node.
Metrics and Health#
The operator chart can expose controller-runtime metrics and health endpoints for the operator controller. Media function metrics are separate. The VSR NIM media function image in this release does not currently expose /metrics; the media function metricsEnabled setting only adds Prometheus scrape annotations.
Operator Chart Settings#
The following are common operator chart settings:
Setting |
Description |
|---|---|
|
Operator controller image. |
|
Pull secrets for the operator controller image. |
|
Default VSR NIM image for generated media function pods. |
|
Default pull secrets for generated media function pods when the CR omits |
|
Default scheduler for generated media function pods when the CR omits |
|
Backward-compatible alias for |
|
Default Holoscan for Media labels for generated media function pods. |
Per-CR fields such as spec.parameters.imagePullSecrets, spec.schedulerName, and Holoscan for Media metadata labels override the corresponding chart-level media function defaults.
Uninstall#
Delete the media function CR:
kubectl delete -f vsr-nim-media-function.yaml
Uninstall the operator:
helm uninstall vsr-nim-operator -n <operator-namespace>