亚马逊AWS官方博客

无人机自主飞行平台建设实践:借助 Karpenter 和 Spot 实例,将平台计算成本降低 90%

无人机自主飞行平台概要介绍

无人机自主飞行平台的建设与当下流行的汽车自动驾驶平台非常相似,平台需要提供的功能包括:数据收集、摄取;数据存储、处理和分析;标记和注释;算法和模型开发、训练;模拟仿真;验证和校验;以及 Pipeline 编排、管理和部署(包括 MLOps 和 DevOps)。构建这样一套平台,除了需要一个具有高度弹性、可扩展的计算、存储、网络以及分析和深度学习框架的开发平台外,还需考虑可提供开发安全、可靠和成本优化的无人机自动驾驶所需的架构和技术,以帮助企业降低开发和验证成本,并缩短无人机产品推向市场的时间。

我们先来看看无人机自动驾驶的主要工作内容和特点:

图 1:无人机自主飞行平台主要工作内容

无人机自主飞行平台的最大特点可以概括为:

  1. 任务动态触发:各个平台的任务在满足一定条件时,会自动触发执行,无需人工干预。比如 AI 平台,当采集的数据足够形成一个数据集时,即会自动触发预定义的训练任务,对某个模型进行迭代。这样做可以大幅度提高平台的效率和响应速度。
  2. 任务并行量大:每个平台都可能产生几十~几百个并发任务,需要在极短的时间内(通常是分钟级)提供极大的计算资源来处理这些并发任务;同时为了提高处理速度和效率,还得考虑分布式技术和任务调度框架,并保证系统的可扩展性和容错性。
  3. 任务运行时长不一:在无人机自主飞行平台中,数据平台、SLAM、AI 训练和仿真等任务通常具有不同的运行时间,从数十分钟到几天不等。因为它们涉及的数据量、算法复杂度和硬件资源需求不同。比如数据平台和 SLAM 主要是 CPU 和内存,而 AI 平台主要依赖 GPU 硬件。因此,无人机自主飞行平台需要能够动态地分配资源和调整任务优先级,以确保平台能够高效地完成任务。

另外还有一点也是需要重点考虑的,就是成本。几百上千个任务同时运行,对资源的消耗是巨大的,同样也会导致成本高企。但其实这些任务都是动态按需触发的,事前也无法预知需要多少;还有,任务结束后,这些资源也就闲置了,需要及时释放。所以就对资源的弹性调度和成本节约提出了很高的要求:在任务需要时,资源能在 1~2 分钟内就能投入使用;在任务结束后,随即销毁资源。比如数据平台的一个任务,一般只需要 20~30 分钟,如果预置资源就要耗费 6~10 分钟,那这个效率也不是我们想要的。

无人机自主飞行平台解决方案架构

考虑到无人机自主飞行平台的上述特点,我们构建的解决方案架构:

图 2:无人机自主飞行平台架构

整个方案基于 EKS,充分利用 Kubernetes 对于容器灵活调度的特性。在 Kubernetes 集群中,我们固定一个节点组,用于后台常驻服务与任务调度组件,部署包括 AWS Load Balancer Controller、Karpenter、Kong 网关、Argo Workflow 和配置管理等管理组件。这些管理组件所需要的资源都比较固定,为此,我们推荐采用 EC2 的预留实例。

数据平台、云测试平台(SLAM)和 AI 平台上承载的任务都是动态的任务,这些任务的资源,我们采用 Karpenter 来管理任务所需要的 EC2 实例。Karpenter 是一个为 Kubernetes 构建的开源项目,它特别适合无人机自主飞行平台的需求特点:在无需提前进行节点组的资源配置的情况下,快速的获得 EC2 资源进行任务运算:在创建资源时,Karpenter 会自动根据 Pod 的资源需求(如 Pod Resource Request 设置)、亲和性设置(如 Node Affinity 等)计算出符合要求的节点类型和数量;在任务结束后也可快速释放资源。而且所有这些工作都是由 Karpenter 根据预定义的 Provisioner 自动完成。所有的任务资源,都优先考虑 Spot 实例,然后才是按需实例。

在数据平台中,需要用 Apache Spark 对多个数据集里的数据进行筛选,所以我们采用 Amazon EMR on EKS 来完成。将大数据工作负载与其它平台基于容器的任务整合到 EKS 里,既帮助简化了基础设施的管理,还可以通过自动化 Kubernetes 集群管理来减少运营的开销。

Karpenter 的 Provisioner 配置说明

无人机自主飞行平台动态任务所需的计算节点的创建和销毁,是由 Karpenter 的 Provisioner 组件来负责的。当 Kubernetes 集群中出现 Unscheduleable Pod 的时候,Karpenter 通过 Provisioner 来确定所需要创建的 EC2 实例的规格和大小。

在节点创建方面,Karpenter 的 Provisioner 提供了多种灵活的选项,可以根据需求配置自动缩放规则和节点属性。例如,可以设置最小和最大节点数、CPU 和内存限制、节点标签等。为此,针对数据平台、SLAM 平台和 AI 平台的要求,我们分别创建了不同的 Provisioner,以满足不同场景下的任务需求。

在 Provisioner 的“karpenter.sh/capacity-type”中,我们设定“values: [“spot”, “on-demand”],这样 Karpenter 在新建节点时,会优先考虑 Spot 实例,从而达到成本节省的目的。

  • 数据平台和云测试平台 Provisioner 样例

Provisioner.yaml

---
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: data-process-provisioner
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot","on-demand"]
  limits:
    resources:
      cpu: 2000
  providerRef:
    name: data-process-provider
  ttlSecondsAfterEmpty: 60

Nodetmplate.yaml

---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: data-process-provider
spec:
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 400Gi
        volumeType: gp3
  subnetSelector:
    Name: node-private*
  securityGroupSelector:
    kubernetes.io/cluster/xxxxx: owned
  • AI 平台 Provisioner 样例

ai-training-provisoner.yaml

---
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: ai-training-provisioner
spec:
  requirements:
- key: "karpenter.k8s.aws/instance-category"
      operator: In
      values: ["p"]
- key: karpenter.sh/capacity-type
      operator: In
      values: ["spot","on-demand"]
    - key: "topology.kubernetes.io/zone"
      operator: In
      values: ["xx-xxxx-1a"]
  limits:
    resources:
      cpu: 2000
  providerRef:
    name: ai-training-provider
  ttlSecondsAfterEmpty: 60

ai-training-nodetemplate.yaml

---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: ai-training-provider
spec:
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 300Gi
        volumeType: gp3
  subnetSelector:
    Name: node-private*
  securityGroupSelector:
    kubernetes.io/cluster/xxxx: owned

配置了 Provisioner 之后,在部署的 pod 或者 job 模板里添加 nodeSelector,例如 AI 训练任务,根据任务需求,我们希望指定特定的实例类型:

 nodeSelector:
    karpenter.sh/provisioner-name: ai-training-provisioner
    node.kubernetes.io/instance-type: p3.8xlarge

总结和收益

在本博客中,我们介绍了通过使用 EKS、Karpenter 和 Spot 实例建立无人机自主飞行平台。借助 Karpenter 和 Spot 实例的结合,我们将平台的计算成本节省达 90%以上。同时,相比在 EKS 中使用托管节点组和 Cluster AutoScaler 的方式,Karpenter 在处理节点扩缩时会更加灵活高效。在本项目中,通常在 2 分钟内即可拉起任务进行执行。

接下来,我们将在后续的博客中探讨无人机自主飞行平台上关于存储的选择和成本优化,敬请关注!

本篇作者

张文博

数据与基础服务总监,关注云原生、容器、大数据相关技术,目前致力于将云原生的技术引入传统科技公司,加速数字化转型。

何康明

AWS 解决方案架构师,负责基于 AWS 的云计算方案架构的咨询和设计,致力于 AWS 云服务在国内和全球的应用和推广。在加入 AWS 之前,曾就职于 IBM 和 VMware,对公有云、私有云架构设计和交付方面有着丰富的经验。