亚马逊AWS官方博客

使用 CodeBuild 在 EC2 VT1 建构 EKS 影音多媒体解决方案

由于现在拥有互联网和移动网络流量的主要受众对视频内容的需求一直在快速增长。诸如 Twitch 等顶级流媒体服务的内容创建者继续呈爆炸式的增长,他们正在寻求具有高质量的影像实时交付的系统,而现场活动推播公司越来越希望采用敏捷的云基础架构,以在不牺牲可靠性的情况下降低成本,并有效地扩展需求。

AWS 云服务很高兴地宣布 Amazon EC2 VT1 实例已经在美国东部(弗吉尼亚北部)、美国西部(俄勒冈)、欧洲(爱尔兰)和亚太地区(东京)区域全面推出。这些实例旨在为分辨率高达 4K UHD 的多流视频转码提供最佳性价比。 VT1 实例采用带有加速 H.264/AVC 和 H.265/HEVC 编解码器的 Xilinx® Alveo™ U30 媒体加速器转码卡,比起先前搭载 GPU 系列的 EC2 实例,每个串流可以提升30%的性价比。与 GPU 系列的 EC2 实例相比,每个串流更可以节省高达 60% 的优惠价格。

对于拥有自己的直播和流媒体视频管道的用户可以使用 VT1 实例对分辨率高达 4K UHD 的视频流进行转码。 VT1 实例具有高达 25 Gbps 的网络接口,可以在低延迟和低抖动的情況下撷取多个视频串流 (Video streaming over IP) 。此功能使用户能够达到可扩展、经济高效且具有弹性的基础架构的目的。

1. 关于 Amazon EC2 VT1 实例机型 實例機型

此实例在 Amazon EC2 VT1 系列中提供专用的加速视频转码硬件。这些实例由 Xilinx® Alveo™ U30 媒体加速器支持,每个实例最多可搭载 8 个 U30 媒体加速卡。每个 U30 加速卡都搭配 2 个 XCU30 Zynq UltraScale+ SoC,在具有 H.264/H.265 视频编解码器单元 (VCU) 内核的 vt1.24xlarge 实例中总共可以拥有 16 个可寻址 XCU30 SoC 设备。 VT1 系列目前包含三种尺寸,参考如下:

实例大小 vCPUs Xilinx U30      加速卡 记忆体 网路带宽 EBS 优化带宽 1080p60 串流/實例 可寻址 XCU30 SoC
1 vt1.3xlarge 12 1 24GB Up to 3.12 Gbps Up to 4.75 Gbps 8 2
2 vt1.6xlarge 24 2 48GB 6.25 Gbps 4.75 Gbps 16 8
3 vt1.24xlarge 96 8 192GB 25 Gbps 19 Gbps 64 16

VT1 实例适用于在每个实例上為多个串流进行转码。串流可以并行或混合(画中画、并排、过渡)独立处理。 vCPU 内核有助于实现图像、音频处理和多路复用。 而 Xilinx® Alveo™ U30 卡可以同时以不同的分辨率(1080p、720p、480p 和 360p)以及 H.264 和 H.265 输出多个串流。

每个 VT1 实例都可以配置为生成具有不同设置、分辨率和传输比特率的并行编码(“ABR 阶梯”)。例如,可以使用 H.265 以每秒 60 帧的速度对 4K UHD 流进行编码,以实现高分辨率显示。可以使用 H.264 对多个较低分辨率进行编码,以传送到标准显示器。

每个可寻址 XCU30 SoC 設備都支持以下規格:

编解码器:MPEG4 Part 10 H.264、MPEG-H Part 2 HEVC H.265

分辨率:128×128 至 3840×2160

灵活的码率控制:等速比特率(CBR)、可变比特率(VBR)和 等量化参数(QP)

帧扫描类型:渐进式 H.264/H.265

输入色彩深度:YCbCr 4:2:2,每个色彩通道 10 bit 位元。

下表概述了每个可寻址设备和实例类型的转码流数量:

转码分辨率 XCU 30 SoC vt1.3xlarge vt1.12xlarge vt1.24xlarge
1 3840x2160p60 1 2 8 16
2 3840x2160p30 2 4 16 32
3 1920x1080p60 4 8 32 64
4 1920x1080p30 8 16 64 1238
5 1280x720p30 16 32 128 256
6 960x540p30 24 48 192 384

VT1 实例可以与 Amazon Elastic Container Service (Amazon ECS) 和 Amazon Elastic Kubernetes Service (Amazon EKS) 结合使用,以有效扩展转码的工作负载,并与 Amazon CloudFront 结合使用做到全球范围的内容交付。 VT1 实例也可以使用 AWS Marketplace 合作伙伴事先开发并包装好 VT1 相关插件的 Amazon 系统映像 (AMI) 和容器启动。您也可以使用 AWS Media Sercices 来补助 VT1 实例,以实现可靠的视频打包和生成转码内容的解决方案。

接下來的步驟將會帶大家一步一步創建打包一個環境,讓用戶能夠在 Amazon VT1 環境裡使用 Amazon EKS 來建構可客製化和可擴展的影音多媒體轉檔應用程序解決方案。

2. 如何快速透過 Codebuild 建立一个 Amazon EC2 VT1 实例机型

2.1 关于 AWS CodeBuild

AWS CodeBuild 是一项完全托管的构建(CI) 服务,使用户能够编译源代码、运行测试并生成可以部署的软件包(software packages)。它具有弹性、可扩展性(elastic, scalable,),并为 Java、Ruby、Python、Go 和 Node.js 等编程语言提供精心设计的构建环境。AWS CodeBuild 可按需扩展并且您只需为使用的构建时间付费,无需额外预置、管理和扩展您自己的构建服务器(build servers)。

2.2 自动化创建 Amazon 虚拟机映像 (AMI) 流程

以下流程会运用到不同工具的介接来实践來打包一個专门给 Amazon VT1 并内建 Amazon EKS 环境的虚拟机映像 (AMI) 档案,並將其加入到 EKS 集群中使用。如下图:

为了帮助构建适用于 Amazon Linux2、Ubuntu 18/20、Amazon ECS 和 Amazon Elastic Kubernetes Service (Amazon EKS) 的 AMI,以下参考 AWS Sample Github 项目提供了一个简化使用 HashiCorp Packer 的构建过程。

2.3 我们首先需要给予 AWS CodeBuild 相应的建立服务脚色(Build Service Role) IAM 权限,让AWS CodeBuild 可以透过 Packer 顺利执行并创建出一个符合 Amazon VT1 EC2 机型的 虚拟机映像 (AMI) 。可以参考以下所提供的内容:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:AttachVolume",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:CopyImage",
        "ec2:CreateImage",
        "ec2:CreateKeypair",
        "ec2:CreateSecurityGroup",
        "ec2:CreateSnapshot",
        "ec2:CreateTags",
        "ec2:CreateVolume",
        "ec2:DeleteKeyPair",
        "ec2:DeleteSecurityGroup",
        "ec2:DeleteSnapshot",
        "ec2:DeleteVolume",
        "ec2:DeregisterImage",
        "ec2:DescribeImageAttribute",
        "ec2:DescribeImages",
        "ec2:DescribeInstances",
        "ec2:DescribeInstanceStatus",
        "ec2:DescribeRegions",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeSnapshots",
        "ec2:DescribeSubnets",
        "ec2:DescribeTags",
        "ec2:DescribeVolumes",
        "ec2:DetachVolume",
        "ec2:GetPasswordData",
        "ec2:ModifyImageAttribute",
        "ec2:ModifyInstanceAttribute",
        "ec2:ModifySnapshotAttribute",
        "ec2:RegisterImage",
        "ec2:RunInstances",
        "ec2:StopInstances",
        "ec2:TerminateInstances"
      ],
      "Resource": "*"
    }
  ]
}

2.4 使用 AWS CodeBuild 創建虚拟机映像 (AMI) 會需要使用我們預先定義好的构建规范文件(buildspec)buildspec 是 AWS CodeBuild 用来运行构建任务的一组构建命令和相关设置,采用 YAML 格式。以下是我们是事先定义好的构建规范文件(buildspec):

version: 0.2

phases:
  pre_build:
    commands:
      - echo "Installing additional YUM & Python packages..."
      - yum -y update && yum -y install unzip curl python3-pip
      - pip3 install awscli
      - echo "Installing Packer..."
      - cd /usr/local/bin/ && curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.8.0/packer_1.8.0_linux_amd64.zip && unzip packer.zip
      - cd $CODEBUILD_SRC_DIR/xilinx-u30-ami_base && packer version
      - echo "Validating packer JSON"
      - packer validate xilinx-vt-al2-eks.yml
      - env
      - echo $HOME
  build:
    commands:
      - echo "Build Phase"
      - export AWS_MAX_ATTEMPTS=200
      - export PACKER_LOG=1 
      - export PACKER_LOG_PATH=packerlog.txt
      - cd $CODEBUILD_SRC_DIR/xilinx-u30-ami_base && packer build xilinx-vt-al2-eks.yml
      - AMINAME=`cat $CODEBUILD_SRC_DIR/xilinx-u30-ami_base/packerlog.txt | grep -A1 'AMIs were created:' | tail -1 | cut -d ':' -f 2 | cut -d ' ' -f 2`
      - echo $AMINAME

buildspec_ami-al2-eks.yml

2.4.1 在 buildspec 裡我們首先安裝了 awscli ,packer 到 建构环境 (build enviornment) 中。

2.4.2  在预先建构的步骤我们可以先验证 packer .yaml 文件设定组态是否语法正确,成功可用。

在 xilinx-u30-ami_base 目录中,将可找到适用于 Amazon Linux 2 和 Ubuntu 18.04 的打包程序脚本。 一般只需要修改variables:{} 內的 json 并执行 packer build 即可。(以下案例套用的是xilinx video sdk version 1.5,  最新版本消息可以参考这边)

"variables": {
    "region": <你所使用的区域>,
    "flag": "eks-1.21",
    "subnet_id": <你建构 AMI 时的子网域-id >,
    "security_groupids": <你建构 AMI 时的安全组-id >,
    "build_ami": <EKS 优化 AMI-id (根据区域或有所不同) >,
    "xilinx-video-sdk_version": v1.5,
    "xilinx-video-releasedir": "U30_Amazon_2.0_v1.5_20210827"
  },

2.4.3 前面几段命令会印出建构环境的相关讯息以确保建构的过程是朝着预期的方向进行,最后就可以开始使用 packer 的命令 packer build 使用我们写好的 .yaml 文件 开始建构我们所需要的 AMI。

2.4.4 AMI 建构成功后我们会在 AWS CodeBuild 的构建日志列印出新建构好的AMI的名称以方便查找。

2.5 透過 AWS CodeBuild 控制台 > 构建项目 > 创建构建项目 > 源 > 源提供商 選擇 “GitHub” 和你預先設置好可與AWS 連線內含以下 buildspec 的 Github 存储库 (repository) :

创建完构建项目后,选择”开始构建” 即可开始建构我们所需要的 AMI,并可于构建日志查看构建的状态,作后完成可以看到所构建出来的VT1 AMI id。(请记下这个 AMI id 供后面 创建节点组 (nodegroup) 做使用)

3. 在 Amazon EKS 上运行容器化工作负载

启动具有 VT1 实例的 EKS 集群,请根据上方 步骤 2. 提供的流程创建 AMI。

一旦创建了 AMI。则需要启动一个 EKS 集群。

如果没有既有的 EKS 集群,可以用以下的命令建立一个没有节点组 (nodegroup) 的 EKS 集群。

eksctl create cluster —version=1.21 —without-nodegroup —region <your region> —name <your eks cluster name>

3.1 透过创建 EKS 工作节点来配置在步骤 2. 建立好的 Amazon VT1 AMI。可以参考以下的配置创建 nodegroup.yaml 档案。

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: <EKS 集群名称, eg: u30-eks >
  region: <EKS 集群区域, eg: us-east-1 >

vpc:  ##EKS nodegroup 的 vpc/subnet
  id: "vpc-0ad02b8f6add1de30"
  subnets:
    Public:
      us-east-1a:
        id: "subnet-025977455fd1bc1bb"
      us-east-1b:
        id: "subnet-0b220f74a50fe4d98"

managedNodeGroups:
  - name: vt1-ng-1d 
    instanceType: vt1.3xlarge
    volumeSize: 200
    instancePrefix: vt1-ng-1d-worker
    ami: <Amazon VT1 AMI id, eg: ami-09124d6a37695ffd8>
    iam:
      withAddonPolicies:
        imageBuilder: true
        autoScaler: true
        ebs: true
        fsx: true
        cloudWatch: true
    ssh:
      allow: true
      publicKeyName:<自己的私钥对名字>
    subnets:
    - subnet-025977455fd1bc1bb
    minSize: 1
    desiredCapacity: 1
    maxSize: 4
    overrideBootstrapCommand: |
      #!/bin/bash
      /etc/eks/bootstrap.sh <EKS 集群名称, eg: u30-eks>

档案建立完成后便可以在 EKS 集群环境执行以下命令创建 EKS 工作节点:

eksctl create nodegroup -f nodegoup.yaml
3.2 创建完节点组我们亦可在EKS 集群的环境下检视一下刚刚创建的EKS 工作节点是否创建成功。执行以下命令:
kubectl get node

亦可在 AWS 控制台上看到 vt1 的工作节点被创建出来。则我们算是初步的创建好 Amazon VT1 上的 EKS 容器环境了。

4. Xilinx  U30 在 EKS 容器内设备插件与设定

4.1 部署后,我们需要应用 FPGA U30 设备插件,相关的 Daemonset 部署文件可以在 Xilinx vidoe SDK 的官方网页上找到 xilinx-device-plugin.yml。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fpga-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: xilinx-fpga-device-plugin
  template:
    metadata:
      annotations:
        scheduler.alpha.kubernetes.io/critical-pod: ""
      labels:
        name: xilinx-fpga-device-plugin
    spec:
      tolerations:
      - key: CriticalAddonsOnly
        operator: Exists
      containers:
      - image: public.ecr.aws/xilinx_dcg/k8s-fpga-device-plugin:1.0.100
        name: xilinx-fpga-device-plugin
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        volumeMounts:
          - name: device-plugin
            mountPath: /var/lib/kubelet/device-plugins
      volumes:
        - name: device-plugin
          hostPath:
            path: /var/lib/kubelet/device-plugins

接下来你可以透过执行以下命令来部署 Xilinx 设备插件

kubectl apply -f xilinx-device-plugin.yml

4.2 您可以透过以下命令确认 Xilinx U30 设备被 K8s API 服务器看到并且可以在您的工作中分配。

kubectl describe node

我们可以看到有一张 Xilinx U30 的设备被分配到目前的 EKS 节点上。

4.3 接下来我们需要在这个EKS集群上建立一个容器来测试是否能够成功使用 Xilinx U30 的设备来进行转码。

根据 Xilinx vidoe SDK 的官方网页所以提供的 EC2 VT1 容器映像建立說明,我们可以自己建立一个容器映像放在 Amazon Elastic Container Registry (私有注册表) 上,以及建立一个 u30-pod.yml 来部署我们的测试容器。并执行以下命令:

kubectl apply -f u30-pod.yml
apiVersion: v1
kind: Pod
metadata:
# Choose a unique test pod name
  name: u30                                     
spec:
  containers:
# Choose a unique container name
  - name: u30               
# Path to the Docker image on ECR              
    image: public.ecr.aws/h3v8x5z1/x30:latest                      
    resources:
      limits:
# Number of Alveo U30 cards which should be mounted
        xilinx.com/fpga-xilinx_u30_gen3x4_base_1-0: 1  
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello; sleep 10;done"]

u30-pod.yml

4.4 当我们部署完这个测试的容器后,我们可以再次检验是否这个容器可以使用到 U30 的设备。

我们进入这个测试容器的环境内我们需要执行以下的 setup.sh 的档案来检验是否容器已经拿到U30的设备。

sh /opt/xilinx/xcdr/setup.sh

接下来我们在这个测试的容器中试着用 ffmepg 的指令对 1080p mp4 的视频进行转档测试。

ffmpeg -c:v mpsoc_vcu_h264 -i visitalps_1080p30.mp4 -vf xvbm_convert -pix_fmt yuv420p -y /tmp/out.mp4

Xilinx Video SDK 的官方文档提供了其他 ffmepg 测试的范本,可以参考这边来做进阶的测试。

5.  串流密度和编码性能

为了说明 VT1 实例系列的串流密度和编码性能,我们以最小的实例 vt1.3xlarge 为例,它可以将同时将 8个 1080p60 视频流编码到 H264 中。我们以接近的价格选择了类似的实例,并以它们可以同时编码多少个 1080p60 H264 流以达到同等质量来做比较:

实例机型 Codec 美东地区每小时价格* 1080p60 串流/实例 每小时花费 / 串流
1 c5.4xlarge x264 $0.68 2 $0.34
2 c6g.4xlarge x264 $0.54 2 $0.27
3 c5a.4xlarge x264 $0.62 3 $0.21
4 g4dn.xlarge nvenc $0.53 4 $0.13
5 vt1.3xlarge xma $0.65 8 $0.08

*价格截至本文发布日期为准。

如您所见,以 vt1.3xlarge 实例为例,其单位小时可以编码的串流是 c5.4xlarge 的 4倍 ,每个流的成本降低高达 76%。它还可以 g4dn.xlarge 实例编码串流的2倍,每个流的成本降低高达 39%。

总结

客户现在可以受益于专门用于视频编码和解码的专用实例系列,并以最低的每个流成本优化重新缩放。这是我们的第一个 EC2 实例,具有用于视频转码的专用硬件加速卡。借助多达 8 个 Xilinx® Alveo™ U30 媒体加速卡,您可以选择并行化多达 16 个 4K UHD 视频串流,用于批次处理、实时和低延迟的转码。 VT1 亦可支持 Amazon ECS 和 EKS 用于容器化转码应用程序并可搭配使用 Amazon CodeBuild 轻松构建测试容器化环境。比相同价位的基于 CPU/GPU的实例进行通用编码可以更加优化和更具成本效益。

如果您有任何问题,请联系您的客户团队。现在,使用 Amazon EC2 VT1 实例启动您的视频转码工作负载。

参考文档、资源

本篇作者

Jill Wang

AWS技术客户经理,负责企业级客户的架构和成本优化、技术支持等工作,致力于Media & Entertainement等行业,拥有13+年的軟體开发、技术支持和專案管理经验。

Donnie Li

AWS Devops 技术支持工程師, 对于操作系统,容器,CI/CD,都有深入的了解,專門處理客戶在使用 ECS, EKS 和 Code系列的使用問題。