如何在 AWS 上使用 EKS 大规模部署 Riva
目录

如何在 AWS 上使用 EKS 大规模部署 Riva#
这是一个在 Amazon Web Services (AWS) Elastic Kubernetes Service (EKS) 上使用基于 Traefik 的负载均衡部署和扩展 Riva Speech Skills 的示例。它包括以下步骤
创建 EKS 集群
部署 Riva API 服务
部署 Traefik 边缘路由器
创建 IngressRoute 以处理传入请求
部署示例客户端
扩展集群
先决条件#
在继续之前,请确保您拥有
此示例已在以下版本上测试过:eksctl
(v0.82.0)、helm
(v3.6.3)、kubectl
(v1.21.2) 和 traefik
(v2.5.3)。
创建 EKS 集群#
该集群包含三个独立的节点组
gpu-linux-workers
:配备 GPU 的节点,主 Riva 服务在此运行。g5.2xlarge
实例,每个使用 A10 GPU,提供良好的价值和足够的容量以满足许多应用程序的需求。此节点组允许从 1 个节点扩展到 8 个节点。cpu-linux-lb
:用于 Traefik 负载均衡器的通用计算节点,使用m6i.large
实例。cpu-linux-clients
:另一个通用节点,使用m6i.2xlarge
实例,用于访问 Riva 服务的客户端应用程序。此节点在本示例中用于基准测试,也可以用于其他服务,例如node.js
应用程序。
构建一个配置文件,定义这些节点组,并将其保存到名为
eks_launch_conf.yaml
的文件中。apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: name: riva-cluster region: us-west-2 version: "1.21" iam: withOIDC: true managedNodeGroups: - name: gpu-linux-workers labels: { role: workers } instanceType: g5.2xlarge minSize: 1 maxSize: 8 volumeSize: 100 privateNetworking: true ssh: allow: true - name: cpu-linux-lb labels: { role: loadbalancers } instanceType: m6i.large desiredCapacity: 1 volumeSize: 100 privateNetworking: true ssh: allow: true - name: cpu-linux-clients labels: { role: clients } instanceType: m6i.2xlarge desiredCapacity: 1 volumeSize: 100 privateNetworking: true ssh: allow: true
使用上述配置启动集群。
eksctl create cluster -f eks_launch_conf.yaml
AWS 可能需要 30 分钟或更长时间来配置所有必要的资源。完成后,您应该在默认 Kubernetes 配置文件中看到一些更改。
验证节点现在是否出现在 Kubernetes 中。如果是,则集群已成功创建。
cat .kube/config kubectl get pods -A kubectl get nodes --show-labels kubectl get nodes --selector role=workers kubectl get nodes --selector role=clients kubectl get nodes --selector role=loadbalancers
部署 Riva API#
Riva Speech Skills Helm chart 旨在自动化部署到 Kubernetes 集群。下载 Helm chart 后,进行少量调整将使 chart 适应 Riva 在本教程其余部分的使用方式。
下载并解压 Riva API Helm chart。将
VERSION_TAG
替换为所需的特定版本。export NGC_CLI_API_KEY=<your NGC API key> export VERSION_TAG="2.18.0" helm fetch https://helm.ngc.nvidia.com/nvidia/riva/charts/riva-api-${VERSION_TAG}.tgz --username='$oauthtoken' --password=$NGC_CLI_API_KEY tar -xvzf riva-api-${VERSION_TAG}.tgz
在
riva-api
文件夹中,修改以下文件values.yaml
在
modelRepoGenerator.ngcModelConfigs
中,根据需要注释或取消注释特定的模型或语言。将
service.type
从LoadBalancer
更改为ClusterIP
。这会将服务直接暴露给集群内的其他服务,例如下面要安装的代理服务。
templates/deployment.yaml
添加节点选择器约束,以确保 Riva 仅部署在正确的 GPU 资源上。在
spec.template.spec
中,添加nodeSelector: eks.amazonaws.com/nodegroup: gpu-linux-workers
启用集群以使用 nvidia 设备插件运行需要 NVIDIA GPU 的容器
helm repo add nvdp https://nvidia.github.io/k8s-device-plugin helm repo update helm install \ --generate-name \ --set failOnInitError=false \ nvdp/nvidia-device-plugin
确保您在工作目录中,其中
riva-api
作为子目录,然后安装 Riva Helm chart。您可以显式覆盖values.yaml
文件中的变量,例如modelRepoGenerator.modelDeployKey
设置。helm install riva-api riva-api/ \ --set ngcCredentials.password=`echo -n $NGC_CLI_API_KEY | base64 -w0` \ --set modelRepoGenerator.modelDeployKey=`echo -n tlt_encode | base64 -w0`
Helm chart 顺序运行两个容器:一个
riva-model-init
容器,用于下载和部署模型,然后是一个riva-speech-api
容器,用于启动语音服务 API。根据模型的数量,初始模型部署可能需要一个小时或更长时间。要监视部署,请使用kubectl
描述riva-api
pod 并观看容器日志。export pod=`kubectl get pods | cut -d " " -f 1 | grep riva-api` kubectl describe pod $pod kubectl logs -f $pod -c riva-model-init kubectl logs -f $pod -c riva-speech-api
部署 Traefik 边缘路由器#
现在 Riva 服务正在运行,集群需要一种机制将请求路由到 Riva。
如果在 riva-api
Helm chart 的 values.yaml
中将 service.type
设置为 LoadBalancer
,则这将自动创建一个 AWS Classic Load Balancer 以将流量定向到 Riva 服务。相反,开源 Traefik 边缘路由器将用于此目的。
下载并解压 Traefik Helm chart。
helm repo add traefik https://helm.traefik.io/traefik helm repo update helm fetch traefik/traefik tar -zxvf traefik-*.tgz
修改
traefik/values.yaml
文件。将
service.type
设置为LoadBalancer
以在可从集群外部访问的外部 IP 上暴露服务。如果service.type
设置为ClusterIP
,则服务将仅在集群内部 IP 上暴露。将
nodeSelector
设置为{ eks.amazonaws.com/nodegroup: cpu-linux-lb }
。与您对 Riva API 服务所做的类似,这告诉 Traefik 服务在cpu-linux-lb
节点组上运行。
部署修改后的
traefik
Helm chart。helm install traefik traefik/
创建 IngressRoute#
IngressRoute 使 Traefik 负载均衡器能够识别传入请求并将它们分发到多个 riva-api
服务。
如果您使用设置为 ClusterIP
的 service.type
部署了上述 traefik
Helm chart,则 Kubernetes 会自动为该服务创建一个本地 DNS 条目:traefik.default.svc.cluster.local
。如果您使用设置为 LoadBalancer
的 service.type
部署了上述 traefik
Helm chart,则 Kubernetes 会自动为该服务创建一个外部 DNS 条目,可以从 kubectl get svc
命令获取,例如 a7153b60c6e7a44dab6f681d15e111b5-2140342794.us-west-2.elb.amazonaws.com
。
以下 IngressRoute 定义匹配这些 DNS 条目,并将请求定向到 riva-api
服务。您可以修改这些条目以支持不同的 DNS 安排,具体取决于您的需求。
创建以下
riva-ingress.yaml
文件。您需要将<local_or_external_IP>
替换为上述说明中提到的本地或外部 DNS 条目。apiVersion: traefik.containo.us/v1alpha1 kind: IngressRoute metadata: name: riva-ingressroute spec: entryPoints: - web routes: - match: "Host(`<local_or_external_IP>`)" kind: Rule services: - name: riva-api port: 50051 scheme: h2c
部署 IngressRoute。
kubectl apply -f riva-ingress.yaml
Riva 服务现在能够从集群内部或外部提供 gRPC 请求,具体取决于 service.type
字段,地址如前所述为本地或外部地址。如果您计划在集群中部署自己的客户端应用程序以与 Riva 通信,则可以将请求发送到该地址。在下一节中,您将部署 Riva 示例客户端并使用它来测试部署。
部署示例客户端#
Riva 提供了一个包含一组预构建示例客户端的容器,用于测试 Riva 服务。Riva C++ 客户端 和 Riva Python 客户端 也可在 GitHub 上找到,供那些有兴趣修改它们的人使用。
创建
client-deployment.yaml
文件,该文件定义了部署并包含以下内容apiVersion: apps/v1 kind: Deployment metadata: name: riva-client labels: app: "rivaasrclient" spec: replicas: 1 selector: matchLabels: app: "rivaasrclient" template: metadata: labels: app: "rivaasrclient" spec: nodeSelector: eks.amazonaws.com/nodegroup: cpu-linux-clients imagePullSecrets: - name: imagepullsecret containers: - name: riva-client image: "nvcr.io/nvidia/riva/riva-speech:2.18.0" command: ["/bin/bash"] args: ["-c", "while true; do sleep 5; done"]
部署客户端服务。
kubectl apply -f client-deployment.yaml
连接到客户端 pod。
export cpod=`kubectl get pods | cut -d " " -f 1 | grep riva-client` kubectl exec --stdin --tty $cpod /bin/bash
从客户端 pod 的 shell 内部,在示例
.wav
文件上运行示例 ASR 客户端。指定如前所述的<local_or_external_IP>
端点,端口为 80,作为服务地址。riva_streaming_asr_client \ --audio_file=/opt/riva/wav/en-US_sample.wav \ --automatic_punctuation=true \ --riva_uri=<local_or_external_IP>:80
扩展集群#
如上所述部署,EKS 集群仅配置单个 GPU 节点,尽管给定配置允许最多 8 个节点。虽然单个 GPU 可以处理 大量请求,但集群可以轻松地使用更多节点进行扩展。
将 GPU 节点组扩展到所需数量的计算节点(在本例中为 4 个)。
eksctl scale nodegroup \ --name=gpu-linux-workers \ --cluster=riva-cluster \ --nodes=4 \ --region=us-west-2
扩展
riva-api
部署以使用额外的节点。kubectl scale deployments/riva-api --replicas=4
与原始 riva-api
部署一样,每个副本 pod 在启动 Riva 服务之前都会下载并初始化必要的模型。