使用Rivermax和DeepStream在加速K8s集群上部署媒体流应用的参考部署指南

创建于2022年6月15日。范围:以下参考部署指南(RDG)展示了在加速Kubernetes集群上部署Rivermax和DeepStream流媒体应用。

文档目录

创建于2022年6月15日。

范围

以下参考部署指南(RDG)展示了在加速Kubernetes集群上部署Rivermax和DeepStream流媒体应用。

缩写和首字母缩略词

术语 定义 术语 定义
CDN 内容分发网络 LLDP 链路层发现协议
CNI 容器网络接口 NFD 节点特性发现
CR 自定义资源 NCCL NVIDIA 集合通信库
CRD 自定义资源定义 OCI 开放容器倡议
CRI 容器运行时接口 PF 物理功能
DHCP 动态主机配置协议 QSG 快速入门指南
DNS 域名系统 RDG 参考部署指南
DP 设备插件 RDMA 远程直接内存访问
DS DeepStream RoCE 融合以太网上的RDMA
IPAM IP地址管理 SR-IOV 单根输入输出虚拟化
K8s Kubernetes VF 虚拟功能

引言

本指南提供了K8s集群部署的完整解决方案周期,包括技术概述、设计、组件选择、部署步骤和应用工作负载示例。该解决方案将在标准服务器上交付。NVIDIA端到端以太网基础设施用于监督工作负载。

在本指南中,我们使用NVIDIA GPU Operator和NVIDIA Network Operator来管理K8s集群中GPU和网络组件的部署和配置。这些组件允许您使用CUDA、RDMA和GPUDirect技术加速工作负载。

本指南展示了具有两个K8s工作节点的K8s集群设计,并提供了部署K8s集群的详细说明。本指南假设为全新部署。

本文档面向需要为客户部署Rivermax流媒体应用的资深媒体和娱乐广播系统管理员、系统工程师和解决方案架构师。

参考文献

解决方案架构

关键组件和技术

  • NVIDIA DGX A100

    NVIDIA DGX™ A100是所有AI工作负载的通用系统,提供前所未有的计算密度、性能和灵活性,是世界上第一个5 petaFLOPS AI系统。NVIDIA DGX A100采用世界上最先进的加速器NVIDIA A100 Tensor Core GPU,使企业能够将训练、推理和分析整合到一个统一、易于部署的AI基础设施中,并可直接访问NVIDIA AI专家。

  • NVIDIA ConnectX SmartNICs

    10/25/40/50/100/200和400G以太网网卡

    业界领先的NVIDIA® ConnectX®系列智能网卡提供先进的硬件卸载和加速。NVIDIA以太网网卡为超大规模、公有云和私有云、存储、机器学习、AI、大数据和电信平台提供最高的ROI和最低的总拥有成本。

  • NVIDIA LinkX Cables

    NVIDIA® LinkX®线缆和收发器产品系列提供业界最完整的10、25、40、50、100、200和400GbE以太网以及100、200和400Gb/s InfiniBand产品,适用于云、HPC、超大规模、企业、电信、存储和人工智能数据中心应用。

  • NVIDIA Spectrum 以太网交换机

    灵活的外形,16到128个物理端口,支持1GbE到400GbE速度。

    基于针对性能和可扩展性优化的突破性硅技术,NVIDIA Spectrum交换机非常适合构建高性能、高性价比、高效的云数据中心网络、以太网存储结构和深度学习互连。NVIDIA将基于业界领先的专用集成电路(ASIC)技术的NVIDIA Spectrum™交换机与多种现代网络操作系统选择相结合,包括NVIDIA Cumulus® LinuxSONiCNVIDIA Onyx®

  • Kubernetes

    Kubernetes是一个开源容器编排平台,用于容器化应用的部署自动化、扩展和管理。

  • Kubespray

    Kubespray由Ansible剧本、清单、配置工具和通用OS/Kubernetes集群配置管理任务的领域知识组成,并提供:

    • 高可用集群
    • 可组合属性
    • 支持大多数流行的Linux发行版
  • NVIDIA GPU Operator

    NVIDIA GPU Operator使用Kubernetes中的operator框架来自动化管理配置GPU所需的所有NVIDIA软件组件。这些组件包括NVIDIA驱动程序(以启用CUDA)、GPU的Kubernetes设备插件、NVIDIA容器运行时、自动节点标记、基于DCGM的监控等。

  • NVIDIA Network Operator

    NVIDIA Network Operator使用Kubernetes中的operator框架来自动化管理配置网络所需的所有NVIDIA软件组件。这些组件包括NVIDIA网卡驱动程序、容器网络接口(CNI)插件、RDMA、SR-IOV等。

NVIDIA Network Operator简化了Kubernetes集群中NVIDIA网络资源的配置和管理。该操作符自动安装所需的主机网络软件,汇集所有必要组件以提供高速网络连接。这些组件包括NVIDIA网络驱动、Kubernetes设备插件、CNI插件、IP地址管理(IPAM)插件等。NVIDIA Network Operator与NVIDIA GPU Operator协同工作,为可扩展的GPU计算集群提供高吞吐量、低延迟的网络。

  • NVIDIA CUDA CUDA®是NVIDIA开发的并行计算平台和编程模型,用于在图形处理单元(GPU)上进行通用计算。借助CUDA,开发人员可以通过利用GPU的强大功能显著加速计算应用。在GPU加速的应用中,工作负载的顺序部分在CPU上运行(针对单线程性能优化),而计算密集型部分则在数千个GPU核心上并行运行。

  • NVIDIA Rivermax SDK NVIDIA Rivermax为任何媒体和数据流用例提供独特的基于IP的解决方案。Rivermax与NVIDIA GPU加速计算技术相结合,为媒体与娱乐(M&E)、广播、医疗、智慧城市等领域的广泛应用解锁创新。Rivermax利用NVIDIA ConnectX和BlueField DPU硬件流加速技术,实现直接数据传输到GPU和从GPU传输,为流工作负载提供最佳的吞吐量和延迟,同时最小化CPU利用率。

  • NVIDIA DeepStream SDK NVIDIA DeepStream允许快速开发和部署视觉AI应用和服务。DeepStream提供多平台、可扩展、TLS加密的安全性,可部署在本地、边缘和云端。它为基于AI的多传感器处理、视频、音频和图像理解提供了完整的流分析工具包。DeepStream主要面向视觉AI开发者、软件合作伙伴、初创公司和OEM厂商,用于构建IVA应用和服务。

  • 网络化媒体开放规范(NMOS) NMOS规范是一系列开放、免费的规范,使IP基础设施上的媒体设备之间能够实现互操作性。核心规范IS-04注册与发现IS-05设备连接管理提供了统一的机制,使媒体设备和服务能够向网络通告其能力,并让控制系统配置设备发送器和接收器之间的视频、音频和数据流。NMOS是可扩展的,例如包括音频通道映射、事件和提词信息交换以及API安全规范,利用IT最佳实践。有可用的开源NMOS实现,NVIDIA在DeepStream SDK中提供了免费的NMOS节点库

逻辑设计

逻辑设计包括以下部分:

  • 运行Kubespray的部署节点,用于部署Kubernetes集群
  • K8s主节点,运行所有Kubernetes管理组件
  • 带有NVIDIA GPU和NVIDIA ConnectX-6Dx网卡的K8s工作节点
  • 高速以太网结构(辅助K8s网络)
  • 部署和K8s管理网络

sol.png

应用逻辑设计

在本指南中,我们部署了以下应用:

  1. Rivermax媒体节点
  2. NMOS注册控制器
  3. DeepStream网关
  4. 时间同步服务
  5. 用于内部GUI访问的VNC应用

apps.png

软件栈组件

soft.png

物料清单

本指南中使用以下硬件设置来构建包含两个K8s工作节点的K8s集群。

注意: 您可以根据网络拓扑和软件栈使用任何合适的硬件。

bom.png

部署与配置

网络/结构

本RDG描述了具有多个K8s工作节点的K8s集群部署。高性能网络是Kubernetes集群的辅助网络,需要L2网络拓扑。部署/管理网络拓扑和DNS/DHCP网络服务是IT基础设施的一部分。本指南不涵盖组件安装过程和配置。

网络IP配置

以下是服务器名称及其相关网络配置。

服务器/交换机类型 服务器/交换机名称 高速网络 管理网络
部署节点 depserver N/A eth0: DHCP 192.168.100.202
K8s主节点 node1 N/A eth0: DHCP
节点 主机名 高速网络接口 管理网络接口
K8s部署节点 depserver - eth0: DHCP 192.168.100.29
K8s工作节点1 node2 enp57s0f0: 无IP设置 eth0: DHCP 192.168.100.34
K8s工作节点2 node3 enp57s0f0: 无IP设置 eth0: DHCP 192.168.100.39
高速交换机 switch - mgmt0: DHCP 192.168.100.49
  • enpXXs0f0 高速网络接口无需额外配置。

布线

每个K8s工作节点上,仅将NVIDIA网卡的第一个端口通过NVIDIA LinkX DAC线缆连接到NVIDIA交换机,构成高性能网络。

下图展示了构建K8s集群所需的布线。

network.png

网络配置

交换机配置如下:

##
## Running database "initial"
## Generated at 2022/05/10 15:49:25 +0200
## Hostname: switch
## Product release: 3.9.3202
##

##
## Running-config temporary prefix mode setting
##
no cli default prefix-modes enable

##
## Interface Ethernet configuration
##
   interface ethernet 1/1-1/32 speed 100GxAuto force
   interface ethernet 1/1-1/32 switchport mode hybrid

##
## VLAN configuration
##
   vlan 2
   vlan 1001
   vlan 2 name "RiverData"
   vlan 1001 name "PTP"
   interface ethernet 1/1-1/32 switchport hybrid allowed-vlan all
   interface ethernet 1/5 switchport access vlan 1001
   interface ethernet 1/7 switchport access vlan 1001
   interface ethernet 1/5 switchport hybrid allowed-vlan add 2
   interface ethernet 1/7 switchport hybrid allowed-vlan add 2

##
## STP configuration
##
no spanning-tree

##
## L3 configuration
##
   interface vlan 1001
   interface vlan 1001 ip address 172.20.0.1/24 primary

##
## IGMP Snooping configuration
##
   ip igmp snooping unregistered multicast forward-to-mrouter-ports
   ip igmp snooping
   vlan 1001 ip igmp snooping
   vlan 1001 ip igmp snooping querier
   interface ethernet 1/5 ip igmp snooping fast-leave
   interface ethernet 1/7 ip igmp snooping fast-leave

##
## Local user account configuration
##
   username admin password 7 $6$mSW1WwYI$M5xfvsphrTRht6J2ByfF.J475tq8YuGKR6K1FwSgvkdb1QQFZbx/PtqK.GVJEBoMcmXsnB57QycP7jSp.Hy/Q.
   username monitor password 7 $6$V/Og9kzY$qc.oU2Ma9MPJClZlbvymOrb1wtE0N5yfQYPamhzRYeN2npVY/lOE5iisHUpxNqm3Ku8lIWDTPiO/bklyCMi2o.

##
## AAA remote server configuration
##
# ldap bind-password ********
   ldap vrf default enable
   radius-server vrf default enable
# radius-server key ********
   tacacs-server vrf default enable
# tacacs-server key ********

##
## Password restriction configuration
##
no password hardening enable

##
## SNMP configuration
##
   snmp-server vrf default enable

##
## Network management configuration
##
# web proxy auth basic password ********
   clock timezone Asia Middle_East Jerusalem
   ntp vrf default disable
   terminal sysrq enable
   web vrf default enable

##
## PTP protocol
##
   protocol ptp
   ptp priority1 1
   ptp vrf default enable
   interface ethernet 1/5 ptp enable
   interface ethernet 1/7 ptp enable
   interface vlan 1001 ptp enable

##
## X.509 certificates configuration
##
#
# Certificate name system-self-signed, ID ca9888a2ed650c5c4bd372c055bdc6b4da65eb1e
# (public-cert config omitted since private-key config is hidden)

##
## Persistent prefix mode setting
##
cli default prefix-modes enable

主机

通用配置

通用前提条件:

  • 硬件 确保所有K8s工作节点具有完全相同的硬件规格(详见BoM)。

  • 主机BIOS 确认使用支持SR-IOV的服务器平台,并查阅服务器平台供应商文档中的BIOS设置以启用SR-IOV

  • 主机操作系统 所有服务器应安装Ubuntu Server 20.04操作系统,并包含OpenSSH服务器软件包。

  • Kubernetes经验 必须熟悉Kubernetes集群架构。

注意: 确保K8s工作节点的BIOS设置为最大性能。 所有K8s工作节点必须具有完全相同的NIC PCIe位置,并暴露相同的接口名称。

主机操作系统前提条件

确保在部署Ubuntu Server 20.04操作系统期间创建了非root用户depuser

运行以下命令更新Ubuntu软件包:

服务器控制台
$ sudo apt-get update
$ sudo apt-get install linux-image-lowlatency -y
$ sudo apt-get upgrade -y
$ sudo reboot

为非root用户depuser添加无密码sudo权限。

在本解决方案中,在**/etc/sudoers**文件末尾添加了以下行:

服务器控制台
$ sudo vim /etc/sudoers

#includedir /etc/sudoers.d

#K8s cluster deployment user with sudo privileges without password
depuser ALL=(ALL) NOPASSWD:ALL

OFED安装与配置

仅需在K8s工作节点上安装OFED。下载最新OFED版本请访问Linux Drivers (nvidia.com)

下载和安装步骤如下,所有步骤需要root权限。

OFED安装后,请重启节点。

服务器控制台
wget https://content.mellanox.com/ofed/MLNX_OFED-5.5-1.0.3.2/MLNX_OFED_LINUX-5.5-1.0.3.2-ubuntu20.04-x86_64.iso
mount -o loop ./MLNX_OFED_LINUX-5.5-1.0.3.2-ubuntu20.04-x86_64.iso /mnt/
/mnt/mlnxofedinstall --vma --without-fw-update
reboot

K8s集群部署

本解决方案中的Kubernetes集群使用Kubespray从部署节点以非root用户depuser身份安装。

SSH私钥与无密码登录

以部署用户(本例中为depuser)登录到部署节点,运行以下命令创建SSH私钥以配置无密码认证:

部署节点控制台
$ ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/home/depuser/.ssh/id_rsa):
Created directory '/home/depuser/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/depuser/.ssh/id_rsa
Your public key has been saved in /home/depuser/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:IfcjdT/spXVHVd3n6wm1OmaWUXGuHnPmvqoXZ6WZYl0 depuser@depserver
The key's randomart image is:
+---[RSA 3072]----+
|                *|
|               .*|
|      . o . .  o=|
|       o + . o +E|
|        S o  .**O|
|         . .o=OX=|
|           . o%*.|
|             O.o.|
|           .*.ooo|
+----[SHA256]-----+

复制您的SSH私钥

key,例如~/.ssh/id_rsa,复制到部署中的所有节点,运行以下命令(示例):

部署节点控制台

$ ssh-copy-id depuser@192.168.100.29

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/depuser/.ssh/id_rsa.pub"
The authenticity of host '192.168.100.29 (192.168.100.29)' can't be established.
ECDSA key fingerprint is SHA256:6nhUgRlt9gY2Y2ofukUqE0ltH+derQuLsI39dFHe0Ag.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
depuser@192.168.100.29's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'depuser@192.168.100.29'"
and check to make sure that only the key(s) you wanted were added.

验证您可以通过无密码SSH连接到部署中的所有节点,运行以下命令(示例):

部署节点控制台

$ ssh depuser@192.168.100.29

Kubespray部署与配置

通用设置

要在部署节点上安装运行Kubespray与Ansible所需的依赖,请运行以下命令:

部署节点控制台

$ cd ~
$ sudo apt -y install python3-pip jq
$ wget https://github.com/kubernetes-sigs/kubespray/archive/v2.18.1.tar.gz
$ tar -zxf v2.18.1.tar.gz
$ cd kubespray-2.18.1
$ sudo pip3 install -r requirements.txt

警告:后续命令的默认文件夹为~/kubespray-2.18.1。 要下载最新Kubespray版本,请访问 Releases · kubernetes-sigs/kubespray · GitHub

部署定制

创建新的集群配置和主机配置文件。 将下面的IP地址替换为您的节点IP地址:

部署节点控制台

$ cp -rfp inventory/sample inventory/mycluster
$ declare -a IPS=(192.168.100.29 192.168.100.34 192.168.100.39)
$ CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

结果将创建inventory/mycluster/hosts.yaml文件。 检查并更改文件中的主机配置。以下是此部署的示例:

inventory/mycluster/hosts.yaml

all:
  hosts:
    node1:
      ansible_host: 192.168.100.29
      ip: 192.168.100.29
      access_ip: 192.168.100.29
    node2:
      ansible_host: 192.168.100.34
      ip: 192.168.100.34
      access_ip: 192.168.100.34
    node3:
      ansible_host: 192.168.100.39
      ip: 192.168.100.39
      access_ip: 192.168.100.39

  children:
    kube_control_plane:
      hosts:
        node1:
    kube_node:
      hosts:
        node2:
        node3:
    etcd:
      hosts:
        node1:
    k8s_cluster:
      children:
        kube_control_plane:
        kube_node:
    calico_rr:
      hosts: {}

使用KubeSpray Ansible Playbook部署集群

运行以下命令启动部署过程:

部署节点控制台

$ ansible-playbook -i inventory/mycluster/hosts.yaml --become --become-user=root cluster.yml

K8s集群部署需要一些时间才能完成,请确保playbook日志中没有错误。

以下是成功结果的示例:

...
PLAY RECAP ***************************************************************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
node1                      : ok=501  changed=111  unreachable=0    failed=0    skipped=1131 rescued=0    ignored=2
node2                      : ok=360  changed=40   unreachable=0    failed=0    skipped=661  rescued=0    ignored=1
node3                      : ok=360  changed=40   unreachable=0    failed=0    skipped=660  rescued=0    ignored=1

Sunday 9 May 2021  19:39:17 +0000 (0:00:00.064)       0:06:54.711 ********
===============================================================================
kubernetes/control-plane : kubeadm | Initialize first master ----------------------------------------------------------------------------------------- 28.13s
kubernetes/control-plane : Master | wait for kube-scheduler ------------------------------------------------------------------------------------------ 12.78s
download : download_container | Download image if required ------------------------------------------------------------------------------------------- 10.56s
container-engine/containerd : ensure containerd packages are installed -------------------------------------------------------------------------------- 9.48s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 9.36s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 9.08s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 9.05s
download : download_file | Download item -------------------------------------------------------------------------------------------------------------- 8.91s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 8.47s
kubernetes/preinstall : Install packages requirements ------------------------------------------------------------------------------------------------- 8.30s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 7.49s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 7.39s
kubernetes-apps/ansible : Kubernetes Apps | Start Resources ------------------------------------------------------------------------------------------- 7.07s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 5.99s
container-engine/containerd : ensure containerd repository is enabled --------------------------------------------------------------------------------- 5.59s
container-engine/crictl : download_file | Download item ----------------------------------------------------------------------------------------------- 5.45s
download : download_file | Download item -------------------------------------------------------------------------------------------------------------- 5.34s
kubernetes-apps/ansible : Kubernetes Apps | Lay Down CoreDNS templates -------------------------------------------------------------------------------- 5.00s
download : download_container | Download image if required -------------------------------------------------------------------------------------------- 4.95s
download : download_file | Download item -------------------------------------------------------------------------------------------------------------- 4.50s

K8s集群定制与验证

现在K8s集群已部署,可以从任何K8s主节点使用root用户连接到K8s集群。

账户或从安装了KUBECTL命令并配置了KUBECONFIG=的其他服务器进行自定义部署。

在我们的指南中,我们从K8s主节点使用root用户账户继续部署:

标记工作节点:

主节点控制台

$ kubectl label nodes node2 node-role.kubernetes.io/worker=
$ kubectl label nodes node3 node-role.kubernetes.io/worker=

注意: K8s工作节点标记是正确安装NVIDIA网络操作符所必需的。

以下是使用Calico CNI插件的K8s集群部署信息输出示例。

要确保Kubernetes集群正确安装,请运行以下命令:

主节点控制台

## 获取集群节点状态

kubectl get node -o wide

NAME    STATUS   ROLES                  AGE   VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION         CONTAINER-RUNTIME
node1   Ready    control-plane,master    9d   v1.22.8   192.168.100.29   <none>        Ubuntu 20.04.4 LTS   5.4.0-109-generic      containerd://1.5.8
node2   Ready    worker                  9d   v1.22.8   192.168.100.34   <none>        Ubuntu 20.04.4 LTS   5.4.0-109-lowlatency   containerd://1.5.8
node3   Ready    worker                  9d   v1.22.8   192.168.100.39   <none>        Ubuntu 20.04.4 LTS   5.4.0-109-lowlatency   containerd://1.5.8

## 获取系统Pod状态

kubectl -n kube-system get pods -o wide

NAME                                      READY   STATUS    RESTARTS       AGE   IP               NODE    NOMINATED NODE   READINESS GATES
calico-kube-controllers-5788f6558-bm5h9   1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>
calico-node-4f748                         1/1     Running   0               9d   192.168.100.34   node2   <none>           <none>
calico-node-jhbjh                         1/1     Running   0               9d   192.168.100.39   node3   <none>           <none>
calico-node-m78p6                         1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>
coredns-8474476ff8-dczww                  1/1     Running   0               9d   10.233.90.23     node1   <none>           <none>
coredns-8474476ff8-ksvkd                  1/1     Running   0               9d   10.233.96.234    node2   <none>           <none>
dns-autoscaler-5ffdc7f89d-h6nc8           1/1     Running   0               9d   10.233.90.20     node1   <none>           <none>
kube-apiserver-node1                      1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>
kube-controller-manager-node1             1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>
kube-proxy-2bq45                          1/1     Running   0               9d   192.168.100.34   node2   <none>           <none>
kube-proxy-4c8p7                          1/1     Running   0               9d   192.168.100.39   node3   <none>           <none>
kube-proxy-j226w                          1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>
kube-scheduler-node1                      1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>
nginx-proxy-node2                         1/1     Running   0               9d   192.168.100.34   node2   <none>           <none>
nginx-proxy-node3                         1/1     Running   0               9d   192.168.100.39   node3   <none>           <none>
nodelocaldns-9rffq                        1/1     Running   0               9d   192.168.100.39   node3   <none>           <none>
nodelocaldns-fdnr7                        1/1     Running   0               9d   192.168.100.34   node2   <none>           <none>
nodelocaldns-qhpxk                        1/1     Running   0               9d   192.168.100.29   node1   <none>           <none>

为K8s集群安装NVIDIA GPU操作符

部署GPU操作符的首选方法是使用helm从K8s主节点进行。要安装helm,只需使用以下命令:

$ snap install helm --classic

添加NVIDIA GPU操作符Helm仓库。

$ helm repo add nvidia https://nvidia.github.io/gpu-operator
$ helm repo update

部署NVIDIA GPU操作符。 GPU操作符应启用GPUDirect内核模块进行部署 - driver.rdma.enabled=true

$ helm install --wait --generate-name -n gpu-operator --create-namespace nvidia/gpu-operator --set driver.rdma.enabled=true --set driver.rdma.useHostMofed=true

$ helm ls -n gpu-operator
NAME                   	NAMESPACE   	REVISION	UPDATED                                	STATUS  	CHART               	APP VERSION
gpu-operator-1652190420	gpu-operator	1       	2022-05-10 13:47:01.106147933 +0000 UTC	deployed	gpu-operator-v1.10.0	v1.10.0  NAME

安装Helm chart后,检查Pod状态以确保所有容器正在运行且验证完成:

$ kubectl get pod -n gpu-operator -o wide

NAME                                                              READY   STATUS      RESTARTS        AGE     IP              NODE    NOMINATED NODE   READINESS GATES
gpu-feature-discovery-bcc22                                       1/1     Running     1 (3d8h ago)    5d18h   10.233.96.3     node2   <none>           <none>
gpu-feature-discovery-vl68h                                       1/1     Running     0               5d18h   10.233.92.58    node3   <none>           <none>
gpu-operator-1652190420-node-feature-discovery-master-5b5fx8zlx   1/1     Running     1 (4m5s ago)    5d18h   10.233.90.17    node1   <none>           <none>
gpu-operator-1652190420-node-feature-discovery-worker-czsb4       1/1     Running     0               4s      10.233.92.75    node3   <none>           <none>
gpu-operator-1652190420-node-feature-discovery-worker-fnlj6       1/1     Running     0               4s      10.233.96.253   node2   <none>           <none>
gpu-operator-1652190420-node-feature-discovery-worker-r44r8       1/1     Running     1 (4m5s ago)    5d18h   10.233.90.22    node1   <none>           <none>
gpu-operator-6497cbf9cd-vcsrg                                     1/1     Running     1 (4m6s ago)    5d18h   10.233.90.19    node1   <none>           <none>
nvidia-container-toolkit-daemonset-4h9dr                          1/1     Running     0               5d18h   10.233.96.246   node2   <none>           <none>
nvidia-container-toolkit-daemonset-rv7sn                          1/1     Running     1 (5d18h ago)   5d18h   10.233.92.50    node3   <none>           <none>
nvidia-cuda-validator-kr6q9                                       0/1     Completed   0               5d18h   10.233.92.61    node3   <none>           <none>
nvidia-cuda-validator-zb4p8                                       0/1     Completed   0               5d18h   10.233.96.4     node2   <none>           <none>
nvidia-dcgm-exporter-5hdzh                                        1/1     Running     0               5d18h   10.233.96.198   node2   <none>           <none>
nvidia-dcgm-exporter-lnqzb                                        1/1     Running     0               5d18h   10.233.92.57    node3   <none>           <none>
nvidia-device-plugin-daemonset-dxgnz                              1/1     Running     0               5d18h   10.233.92.62    node3   <none>           <none>
nvidia-device-plugin-daemonset-w692b                              1/1     Running     0               5d18h   10.233.96.9     node2   <none>           <none>
nvidia-device-plugin-validator-pqns8                              0/1     Completed   0               5d18h   10.233.92.64    node3   <none>           <none>
nvidia-device-plugin-validator-sgtmt                              0/1     Completed   0               5d18h   10.233.96.10    node2   <none>           <none>
nvidia-driver-daemonset-l9x4n                                     2/2     Running     1 (2d19h ago)   5d18h   10.233.92.30    node3   <none>           <none>
nvidia-driver-daemonset-tf2tl                                     2/2     Running     5 (2d21h ago)   5d18h   10.233.96.244   node2   <none>           <none>
nvidia-operator-validator-p6794                                   1/1     Running     0               5d18h   10.233.96.6     node2   <none>           <none>
nvidia-operator-validator-xjrg9                                   1/1     Running     0               5d18h   10.233.92.54    node3   <none>           <none>

NVIDIA Network Operator Installation

The NVIDIA Network Operator leverages Kubernetes CRDs and Operator SDK to manage networking-related components in order to enable fast networking and RDMA for workloads in K8s cluster. The Fast Network is a secondary network of the K8s cluster for applications that require high bandwidth or low latency.

To make it work, several components need to be provisioned and configured. The Helm is required for the Network Operator deployment.

Add the NVIDIA Network Operator Helm repository:

## Add REPO
helm repo add mellanox https://mellanox.github.io/network-operator \
  && helm repo update

Create the values.yaml file to customize the Network Operator deployment (example):

nfd:
  enabled: true

sriovNetworkOperator:
  enabled: true

ofedDriver:
  deploy: false
nvPeerDriver:
  deploy: false
rdmaSharedDevicePlugin:
  deploy: false
sriovDevicePlugin:
  deploy: false

deployCR: true
secondaryNetwork:
  deploy: true
  cniPlugins:
    deploy: true
  multus:
    deploy: true
  ipamPlugin:
    deploy: true

Deploy the operator:

helm install -f ./values.yaml -n network-operator --create-namespace --wait mellanox/network-operator --generate-name

helm ls -n network-operator
NAME                       	NAMESPACE       	REVISION	UPDATED                                	STATUS  	CHART                 	APP VERSION
network-operator-1648457278	network-operator	1       	2022-03-28 08:47:59.548667592 +0000 UTC	deployed	network-operator-1.1.0	v1.1.0

Once the Helm chart is installed, check the status of the pods to ensure all the containers are running:

## PODs status in namespace - network-operator

kubectl -n network-operator get pods -o wide
NAME                                                              READY   STATUS    RESTARTS        AGE   IP               NODE    NOMINATED NODE   READINESS GATES
network-operator-1648457278-5885dbfff5-wjgsc                      1/1     Running   0                5m   10.233.90.15     node1   <none>           <none>
network-operator-1648457278-node-feature-discovery-master-zbcx8   1/1     Running   0                5m   10.233.90.16     node1   <none>           <none>
network-operator-1648457278-node-feature-discovery-worker-kk4qs   1/1     Running   0                5m   10.233.90.18     node1   <none>           <none>
network-operator-1648457278-node-feature-discovery-worker-n44b6   1/1     Running   0                5m   10.233.92.221    node3   <none>           <none>
network-operator-1648457278-node-feature-discovery-worker-xhzfw   1/1     Running   0                5m   10.233.96.233    node2   <none>           <none>
network-operator-1648457278-sriov-network-operator-5cd4bdb6mm9f   1/1     Running   0                5m   10.233.90.21     node1   <none>           <none>
sriov-device-plugin-cxnrl                                         1/1     Running   0                5m   192.168.100.34   node2   <none>           <none>
sriov-device-plugin-djlmn                                         1/1     Running   0                5m   192.168.100.39   node3   <none>           <none>
sriov-network-config-daemon-rgfvk                                 3/3     Running   0                5m   192.168.100.39   node3   <none>           <none>
sriov-network-config-daemon-zzchs                                 3/3     Running   0                5m   192.168.100.34   node2   <none>           <none>

## PODs status in namespace - nvidia-network-operator-resources

kubectl -n nvidia-network-operator-resources get pods -o wide
NAME                   READY   STATUS    RESTARTS       AGE   IP               NODE    NOMINATED NODE   READINESS GATES
cni-plugins-ds-snf6x   1/1     Running   0               5m   192.168.100.39   node3   <none>           <none>
cni-plugins-ds-zjb27   1/1     Running   0               5m   192.168.100.34   node2   <none>           <none>
kube-multus-ds-mz7nd   1/1     Running   0               5m   192.168.100.39   node3   <none>           <none>
kube-multus-ds-xjxgd   1/1     Running   0               5m   192.168.100.34   node2   <none>           <none>
whereabouts-jgt24      1/1     Running   0               5m   192.168.100.34   node2   <none>           <none>
whereabouts-sphx4      1/1     Running   0               5m   192.168.100.39   node3   <none>           <none>

High-Speed Network Configuration

After installing the operator, please check the SriovNetworkNodeState CRs to see all SR-IOV-enabled devices in your node.

In this deployment, the network interface has been chosen with the following name: enp57s0f0.

To review the interface status please use the following command:

NICs status

## NIC status
kubectl -n network-operator get sriovnetworknodestates.sriovnetwork.openshift.io node2 -o yaml

...
status:
  interfaces:
    deviceID: 101d
    driver: mlx5_core
    eSwitchMode: legacy
    linkSpeed: 100000 Mb/s
    linkType: ETH
    mac: 0c:42:a1:2b:73:fa
    mtu: 9000
    name: enp57s0f0
    numVfs: 8
    pciAddress: "0000:39:00.0"
    totalvfs: 8
    vendor: 15b3
  - deviceID: 101d
    driver: mlx5_core
...

Create SriovNetworkNodePolicy CR for chosen network interface - policy.yaml file, by specifying the chosen interface in the 'nicSelector'.

According to application design VF0 allotted into a separate pool from the rest of VFn:

apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: mlnxnics-sw1
  namespace: network-operator
spec:
  nodeSelector:
    feature.node.kubernetes.io/custom-rdma.capable: "true"
  resourceName: timepool
  priority: 99
  mtu: 9000
  numVfs: 8
  nicSelector:
    pfNames: [ "enp57s0f0#0-0" ]
  deviceType: netdevice
  isRdma: true

---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetworkNodePolicy
metadata:
  name: mlnxnics-sw2
  namespace: network-operator
spec:
  nodeSelector:
    feature.node.kubernetes.io/custom-rdma.capable: "true"
  resourceName: rdmapool
  priority: 99
  mtu: 9000
  numVfs: 8
  nicSelector:
    pfNames: [ "enp57s0f0#1-7" ]
  deviceType: netdevice
  isRdma: true

Deploy policy.yaml:

kubectl apply -f policy.yaml
sriovnetworknodepolicy.sriovnetwork.openshift.io/mlnxnics-sw1 created
sriovnetworknodepolicy.sriovnetwork.openshift.io/mlnxnics-sw2 created

Note: This step takes a while. This depends on the amount of K8s Worker Nodes to apply the configuration, and the number of VFs for each selected network interface.

Create an SriovNetwork CR for chosen network interface - network.yaml file which refers to the 'resourceName' defined in SriovNetworkNodePolicy.

In this example below created:

  • timenet - K8s network name for PTP time sync
  • rdmanet - K8s network name with dynamic IPAM
  • rdma-static - K8s network name with static IPAM
apiVersion: "sriovnetwork.openshift.io/v1"
kind: SriovNetwork
metadata:
  name: timenet
  namespace: network-operator
spec:
  resourceName: timepool
  networkNamespace: default
  ipam: |
    {
      "type": "whereabouts",
      "datastore": "kubernetes",
      "range": "192.168.10.0/24",
      "exclude": [
        "192.168.10.0/30"
      ]
    }
---
apiVersion: "sriovnetwork.openshift.io/v1"
kind: SriovNetwork
metadata:
  name: rdmanet
  namespace: network-operator
spec:
  resourceName: rdmapool
  networkNamespace: default
  ipam: |
    {
      "type": "whereabouts",
      "datastore": "kubernetes",
      "range": "192.168.20.0/24",
      "exclude": [
        "192.168.20.0/30"
      ]
    }
---
apiVersion: "sriovnetwork.openshift.io/v1"
kind: SriovNetwork
metadata:
  name: rdma-static
  namespace: network-operator
spec:
  resourceName: rdmapool
  networkNamespace: default
  ipam: |
    {
      "type": "static"
    }
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: timenet
  namespace: network-operator
spec:
  ipam: |
    {
         "datastore": "kubernetes",
         "kubernetes": {"kubeconfig": "/etc/cni/net.d/whereabouts.d/whereabouts.kubeconfig"},
         "log_file": "/tmp/whereabouts.log",
         "log_level": "debug",
         "type": "whereabouts",
         "range": "172.20.0.0/24",
         "exclude": [ "172.20.0.1/32" ]
    }
  networkNamespace: default
  resourceName: timepool
  trust: "on"
  vlan: 0

---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: rdmanet
  namespace: network-operator
spec:
  ipam: |
    {
      "datastore": "kubernetes",
      "kubernetes": { "kubeconfig": "/etc/cni/net.d/whereabouts.d/whereabouts.kubeconfig" },
      "log_file": "/tmp/whereabouts.log",
      "log_level": "debug",
      "type": "whereabouts",
      "range": "192.168.102.0/24",
      "exclude": [ "192.168.102.254/32", "192.168.102.253/32" ]
    }
  networkNamespace: default
  resourceName: rdmapool
  vlan: 2

---
apiVersion: sriovnetwork.openshift.io/v1
kind: SriovNetwork
metadata:
  name: rdmanet-static
  namespace: network-operator
spec:
  ipam: |
    {
      "type": "static"
    }
  networkNamespace: default
  resourceName: rdmapool
  vlan: 2

部署 network.yaml

kubectl apply -f network.yaml
sriovnetwork.sriovnetwork.openshift.io/timenet created
sriovnetwork.sriovnetwork.openshift.io/rdmanet created
sriovnetwork.sriovnetwork.openshift.io/rdmanet-static created

管理HugePages

Kubernetes支持Pod中的应用分配和消费预分配的HugePages。节点会自动发现并报告所有HugePages资源作为可调度资源。有关K8s HugePages管理的更多信息,请参考此处

为了分配HugePages,需要在/etc/default/grub中修改GRUB_CMDLINE_LINUX_DEFAULT参数。以下设置在启动时分配2MB * 8192页 = 16GB HugePages:

/etc/default/grub

...

GRUB_CMDLINE_LINUX_DEFAULT="default_hugepagesz=2M hugepagesz=2M hugepages=8192"

...

运行update-grub以应用配置到grub并重启服务器:

Worker Node console

# update-grub
# reboot

服务器重启后,从主节点通过命令检查hugepages分配:

Master Node console

# kubectl describe nodes node2
...
Capacity:
  cpu:                  48
  ephemeral-storage:    459923528Ki
  hugepages-1Gi:        0
  hugepages-2Mi:        16Gi
  memory:               264050900Ki
  nvidia.com/gpu:       2
  nvidia.com/rdmapool:  7
  nvidia.com/timepool:  1
  pods:                 110
Allocatable:
  cpu:                  46
  ephemeral-storage:    423865522704
  hugepages-1Gi:        0
  hugepages-2Mi:        16Gi
  memory:               246909140Ki
  nvidia.com/gpu:       2
  nvidia.com/rdmapool:  7
  nvidia.com/timepool:  1
  pods:                 110
...

启用CPU和拓扑管理

CPU Manager管理CPU组并将工作负载约束到特定CPU上。

CPU Manager对于具有以下某些属性的工作负载非常有用:

  • 需要尽可能多的CPU时间
  • 对处理器缓存未命中敏感
  • 是低延迟网络应用
  • 与其他进程协调并受益于共享单个处理器缓存

Topology Manager根据收集的拓扑信息提示,基于配置的Topology Manager策略和Pod请求的资源,决定Pod是否可以在节点上被接受或拒绝。为了获得最佳性能,需要与CPU隔离以及内存和设备局部性相关的优化。

Topology Manager对于使用硬件加速器支持延迟关键型执行和高吞吐量并行计算的工作负载非常有用。

注意: 要使用Topology Manager,必须使用具有static策略的CPU Manager。

有关更多信息,请参考控制节点上的CPU管理策略控制节点上的拓扑管理策略

为了启用CPU Manager和Topology Manager,请在kubelet配置文件/etc/kubernetes/kubelet-config.yaml中添加以下行:

/etc/kubernetes/kubelet-config.yaml

...
cpuManagerPolicy: static
cpuManagerReconcilePeriod: 10s
topologyManagerPolicy: single-numa-node
featureGates:
  CPUManager: true
  TopologyManager: true

由于cpuManagerPolicy的更改,请删除/var/lib/kubelet/cpu_manager_state并在每个受影响的K8s工作节点上重启kubelet服务。

Worker Node console

# rm -f /var/lib/kubelet/cpu_manager_state
# service kubelet restart

应用

以下提供了K8s特定组件和K8s YAML配置文件,用于在K8s集群中部署Rivermax应用。

注意: 为了正确执行应用,需要Rivermax许可证。要获取许可证,请查看Rivermax许可证生成指南

注意: 要从容器仓库下载Rivermax应用容器镜像和应用管道,您需要注册并登录Rivermax门户,点击“Get Started”。

Rivermax许可证

将Rivermax许可证作为configmap值上传到K8s集群。

kubectl create configmap rivermax-config --from-file=rivermax.lic=./rivermax.lic

媒体节点应用

此Pod定义包含AMWA网络化媒体开放规范(NMOS)的实现,使用NMOS Rivermax节点实现。有关AMWA、NMOS和网络化媒体孵化器的更多信息,请参考http://amwa.tv/。有关Rivermax SDK的更多信息,请参考https://developer.nvidia.com/networking/Rivermax

以下是用于媒体节点部署的YAML配置文件。请填写您的容器文件名和注册密钥。

apiVersion: v1
kind: ConfigMap
metadata:
  name: river-config
data:
  container-config: |-
    #media_node JSON file to run
    config_json=/var/home/config.json
    #Output registry stdout/stderr output to a log inside container
    log_output=FALSE
    #Update/insert label parameter with container hostname on entrypoint
script run
    update_label=TRUE
    #Allow these network interfaces in /etc/avahi/avahi-daemon.conf
    allow_interfaces=net1

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: "mnc"
  labels:
    apps: rivermax
spec:
  replicas: 3
  selector:
    matchLabels:
      app: rivermax
  template:
    metadata:
      labels:
        app: rivermax
      annotations:
        k8s.v1.cni.cncf.io/networks: rdmanet
    spec:
      containers:
      - command:
        image: < media node container image >
        name: "medianode"
        env:
          - name: DISPLAY
            value: "192.168.102.253:0.0"
        resources:
          requests:
            nvidia.com/rdmapool: 1
            hugepages-2Mi: 4Gi
            memory: 8Gi
            cpu: 4
          limits:
            nvidia.com/rdmapool: 1
            hugepages-2Mi: 4Gi
            memory: 8Gi
            cpu: 4
        securityContext:
          capabilities:
            add: [ "IPC_LOCK", "SYS_RESOURCE", "NET_RAW","NET_ADMIN" ]
        volumeMounts:
        - name: config
          mountPath: /var/home/ext/
        - name: licconfig
          mountPath: /opt/mellanox/rivermax/
        - mountPath: /hugepages
          name: hugepage
        - mountPath: /dev/shm
          name: dshm
      volumes:
      - name: config
        configMap:
          name: river-config
      - name: licconfig
        configMap:
          name: rivermax-config
      - name: hugepage
        emptyDir:
          medium: HugePages
      - name: dshm
        emptyDir: {
          medium: 'Memory',
          sizeLimit: '4Gi'
          }
      imagePullSecrets:
      - name: < Container registry secret >

NMOS控制器

AMWA NMOS控制器是一种能够与NMOS API交互的设备,NMOS API是一系列用于专业应用网络化媒体的开放规范。NMOS控制器可以使用通用方法和协议在IP基础设施上发现、注册、连接和管理媒体设备。NMOS控制器还可以处理事件和计数、音频通道映射、授权以及其他属于NMOS路线图的功能。更多信息,请参阅README.md

apiVersion: v1
kind: Pod
metadata:
  name: nmos-cpp
  labels:
    app.kubernetes.io/name: nmos
  annotations:
    k8s.v1.cni.cncf.io/networks: |
          [
            { "name": "rdmanet-static",
              "ips": [ "192.168.102.254/24" ]
            }
          ]
spec:
  containers:
  - name: nmos-pod
    image: docker.io/rhastie/nmos-cpp:latest
    env:
    - name: RUN_NODE
      value: "true"
    resources:
      requests:
        cpu: 2
        memory: 1Gi
        nvidia.com/rdmapool: 1
      limits:
        cpu: 2
        memory: 1Gi
        nvidia.com/rdmapool: 1
    ports:
      - containerPort: 8010
        name: port-8010
      - containerPort: 8011
        name: port-8011
      - containerPort: 11000
        name: port-11000
      - containerPort: 11001
        name: port-11001
      - containerPort: 1883
        name: port-1883
      - containerPort: 5353
        name: port-5353
        protocol: UDP

DeepStream媒体网关

DeepStream SDK的应用之一是将原始数据编码为SRT流。该应用程序可以从摄像头或文件捕获视频帧,使用H.264或H.265编解码器进行编码,并通过SRT协议通过网络发送。SRT代表安全可靠传输(Secure Reliable Transport),是一种低延迟、安全的流媒体技术。该应用程序可用于远程监控、直播或视频会议等场景。

以下是媒体网关部署的YAML配置文件。请填写您的容器文件名和注册表密钥。

apiVersion: v1
kind: Pod
metadata:
  name: ds-rmax
  labels:
    name: dsrmax-app
  annotations:
    k8s.v1.cni.cncf.io/networks: rdmanet
spec:
  containers:
  - name: dsrmax
    image: < DeepStream media gateway container image >
    command:
      - sh
      - -c
      - sleep inf
    env:
      - name: DISPLAY
        value: "192.168.102.253:0.0"
    ports:
      - containerPort: 7001
        name: udp-port
    securityContext:
      capabilities:
        add: [ "IPC_LOCK", "SYS_RESOURCE", "NET_RAW","NET_ADMIN"]
    resources:
      requests:
        nvidia.com/rdmapool: 1
        nvidia.com/gpu: 1
        hugepages-2Mi: 2Gi
        memory: 8Gi
        cpu: 8
      limits:
        nvidia.com/rdmapool: 1
        nvidia.com/gpu: 1
        hugepages-2Mi: 2Gi
        memory: 8Gi
        cpu: 8
    volumeMounts:
    - name: config
      mountPath: /var/home/ext/
    - name: licconfig
      mountPath: /opt/mellanox/rivermax/
    - mountPath: /hugepages
      name: hugepage
    - mountPath: /dev/shm
      name: dshm
  volumes:
  - name: config
    configMap:
      name: river-config
  - name: licconfig
    configMap:
      name: rivermax-config
  - name: hugepage
    emptyDir:
      medium: HugePages
  - name: dshm
    emptyDir: {
      medium: 'Memory',
      sizeLimit: '4Gi'
      }
  imagePullSecrets:
  - name: < Container registry secret >
---
apiVersion: v1
kind: Service
metadata:
  name: rmax-service
spec:
  type: NodePort
  selector:
    name: dsrmax-app
  ports:
      # By default and for convenience, the `targetPort` is set to the same value as the `port` field.
    - port: 7001
      name: udp-port
      protocol: UDP
      targetPort: 7001

带GUI的VNC容器

此Pod定义允许您通过Kubernetes集群内的Web VNC界面访问Ubuntu LXDE/LXQT桌面环境。它使用K8s辅助网络的接口,通过GUI管理集群节点上的应用程序。

以下是VNC部署的YAML配置文件。请填写您的容器文件名。

此应用程序的示例可在GitHub - theasp/docker-novnc找到,但您可以创建自己的容器镜像。

apiVersion: v1
kind: Pod
metadata:
  name: ub-vnc
  labels:
    name: ubuntu-vnc
  annotations:
    k8s.v1.cni.cncf.io/networks: |
       [
         { "name": "rdmanet-static",
           "ips": [ "192.168.102.253/24" ]
         }
       ]
spec:
  volumes:
    - name: dshm
      emptyDir:
        medium: Memory
  containers:
    - image: < NOVNC container image >
      name: vnc-container
      resources:
        limits:
          cpu: 4
          memory: 8Gi
          nvidia.com/rdmapool: 1
      env:
        - name: DISPLAY_WIDTH
          value: "1920"
        - name: DISPLAY_HEIGHT
          value: "1080"
        - name: RUN_XTERM
          value: "yes"
        - name: RUN_FLUXBOX
          value: "yes"
      ports:
        - containerPort: 8080
          name: http-port
      volumeMounts:
        - mountPath: /dev/shm
          name: dshm

---
apiVersion: v1
kind: Service
metadata:
  name: vnc-service
spec:
  type: NodePort
  selector:
    name: ubuntu-vnc
  ports:
    - port: 8080
      name: http-port
      targetPort: 8080

作者

VR.jpg Vitaliy Razinkov Vitaliy Razinkov是NVIDIA网络团队的解决方案架构师,专注于复杂的Kubernetes、OpenShift和Microsoft解决方案。凭借超过25年的高级技术职位经验,他在设计和实施先进基础设施方面拥有深厚的专业知识。Vitaliy撰写了多份关于Microsoft技术、RoCE/RDMA加速的Kubernetes/OpenShift机器学习以及容器化解决方案的参考设计指南——所有这些都可在NVIDIA网络文档网站上找到。

garethsb-badge-photo.jpg Gareth Sylvester-Bradley Gareth Sylvester-Bradley是NVIDIA的首席工程师,目前担任高级媒体工作流协会(AMWA)网络化媒体开放规范(NMOS)架构审查组主席。他专注于构建软件工具包和敏捷、协作的行业规范,为广播、直播制作提供开放、软件定义、硬件加速的媒体工作流。

医学影像、工业视频等。