(高级) 在 Kubernetes 环境中理解 Ray Autoscaler#
我们描述 Ray autoscaler 与 Kubernetes 生态系统中其他 autoscaler 之间的关系。
Ray Autoscaler vs. Horizontal Pod Autoscaler (水平 Pod 自动伸缩器)#
Ray autoscaler 调整 Ray 集群中的 Ray 节点数量。在 Kubernetes 上,每个 Ray 节点都作为 Kubernetes Pod 运行。因此,在 Kubernetes 环境中,Ray autoscaler 负责伸缩 Ray Pod 的数量。从这个意义上说,Ray autoscaler 的作用类似于 Kubernetes 的 Horizontal Pod Autoscaler (HPA,水平 Pod 自动伸缩器)。然而,Ray Autoscaler 与 HPA 相比具有以下特点。
负载指标基于应用语义#
Horizontal Pod Autoscaler 根据 CPU 和内存等物理使用指标确定伸缩规模。相比之下,Ray autoscaler 使用任务和 actor 注解中表达的逻辑资源。例如,如果 RayCluster CR 中的每个 Ray 容器规范指示 CPU 限制为 10,并且您提交了二十个带有 @ray.remote(num_cpus=5)
注解的任务,则会创建 10 个 Ray Pod 来满足 100 CPU 的资源需求。在这方面,Ray autoscaler 类似于 Kubernetes Cluster Autoscaler (集群自动伸缩器),后者根据容器资源请求中表达的逻辑资源做出伸缩决策。
细粒度控制缩容#
为了适应 Ray 应用的有状态性,Ray autoscaler 对缩容的控制比 Horizontal Pod Autoscaler 更细粒度。除了确定所需的规模外,Ray Autoscaler 还能精确选择要缩容的 Pod。然后 KubeRay operator 删除该 Pod。相比之下,Horizontal Pod Autoscaler 只能减少副本数,而无法很好地控制删除哪些 Pod。对于 Ray 应用来说,缩减一个随机的 Pod 可能会很危险。
架构:每个 Ray 集群一个 Ray Autoscaler#
Horizontal Pod Autoscaling 由 Kubernetes 控制平面中的一个管理器集中控制;该管理器控制许多 Kubernetes 对象的伸缩。相比之下,每个 Ray 集群由其自身的 Ray autoscaler 进程管理,该进程作为 Ray head Pod 中的 sidecar 容器运行。这一设计选择是出于以下考虑:
可伸缩性。 自动伸缩每个 Ray 集群需要处理来自该 Ray 集群的大量资源数据。
简化的版本控制和兼容性。 autoscaler 和 Ray 都作为 Ray 仓库的一部分进行开发。autoscaler 和 Ray core 之间的接口很复杂。为了支持运行不同 Ray 版本的多个 Ray 集群,最好匹配 Ray 和 Autoscaler 的代码版本。每个 Ray 集群运行一个 autoscaler 并匹配代码版本可确保兼容性。
Ray Autoscaler 与 Kubernetes Cluster Autoscaler#
Ray Autoscaler 和 Kubernetes Cluster Autoscaler (集群自动伸缩器) 是相互补充的。在 Ray autoscaler 决定创建一个 Ray Pod 后,Kubernetes Cluster Autoscaler 可以提供一个 Kubernetes 节点,以便放置该 Pod。类似地,在 Ray autoscaler 决定删除一个空闲 Pod 后,Kubernetes Cluster Autoscaler 可以清理剩余的空闲 Kubernetes 节点。建议您配置 RayCluster,使每个 Kubernetes 节点上只容纳一个 Ray Pod。如果您遵循此模式,Ray Autoscaler Pod 伸缩事件与集群自动伸缩器节点伸缩事件大致呈一对一关系。(我们说“大致”是因为 Ray Pod 有可能在底层的 Kubernetes 节点缩减之前被删除并替换为新的 Ray Pod。)
Vertical Pod Autoscaler (垂直 Pod 自动伸缩器)#
Ray Autoscaler 与 Kubernetes Vertical Pod Autoscaler (VPA,垂直 Pod 自动伸缩器) 之间没有关系,VPA 的目的是根据当前和过去的使用情况将单个 Pod 调整到合适的大小。如果您发现单个 Ray Pod 的负载过高,有许多手动技术可以降低负载。一种方法是通过增加 ray.remote
注解中指定的资源需求,从而减少每个节点调度的任务/actor 数量。例如,将 @ray.remote(num_cpus=2)
改为 @ray.remote(num_cpus=4)
将使给定 Ray Pod 中可容纳的该任务或 actor 的数量减半。