基于Ack集群调度的方案设计

名词说明:本文提到的
k8s集群特指阿里云ack(Alibaba Cloud Container Service for Kubernetes)集群
概述
Kubernetes解决了应用的编排、生命周期、自我健康检查和恢复等问题,随着应用容器化(云原生化)的不断完善和落地,方方面面需要考虑的问题也就随之而来
其中应用的调度不乏重要,其关乎着应用的稳定性、资源利用率的完整性与合理性
原生调度原则
Kubernetes API Server接受客户端提交Pod对象创建请求后的操作过程中,一个重要的步骤是由调度器程序kube-scheduler从当前集群中选择一个可用的最佳节点来接收井运行它,通常是默认的调度器default-scheduler负责执行此类任务
KIND: Deployment
VERSION: apps/v1
FIELD: schedulerName <string>
DESCRIPTION:
If specified, the pod will be dispatched by specified scheduler. If not
specified, the pod will be dispatched by default scheduler.
设计调度需要考虑的因素:单独和整体的资源请求、硬件/软件/策略限制、亲和以及反亲和要求、数据局域性、负载间的干扰等等
k8s调度机制是k8s原生提供的一种高效优雅的资源分配机制,它的核心功能是为每个Pod找到最适合它的节点,通过合理利用k8s原生提供的调度能力,根据业务特性配置合理的调度策略,能有效提高集群中的资源利用率
调度流程
原生的调度流程整体上分为以下三步
-
预选(过滤)——选出可以调度的节点
-
优选(打分)——对选出的节点进行排序
-
选定——按照
pod优先级选定调度的节点
调度策略
常见的原生调度策略整体上也分为以下几种类型
-
Topology——拓扑域调度:例如域(
Region)、可用区(Zone)进行拓扑划分 -
nodeName——选定节点调度:直接指定
Node主机名进行调度(点对点) -
NodeSelector——节点选择器调度:节点标签选择器调度
-
NodeAffinity——节点亲和性调度:针对
pod和node之间的调度关系,分为硬亲和和软亲和 -
podAffinity——Pod亲和性调度:针对
pod和pod之间的调度关系,也分为硬亲和、软亲和和反亲和 -
Taint、Toleration——污点和容忍调度:节点拒绝
Pod调度(污点)和Pod能接纳节点污点(容忍)两个维度
应用和服务概况
应用按照服务用途维度划分主要分为两类:普通service类型和worker类型,其中分别包含
普通service类型
- 有状态服务:少数服务,如
mysql、redis - 无状态服务:多数服务
worker类型
- 普通
worker服务 gpu型worker服务
按照应用使用的资源类别划分,可对应用大致分为以下几类
- 通用计算
CPU计算密集型:大量计算,消耗CPU资源IO密集型:网络、磁盘IO要求高- 通用型:对
CPU和IO要求相对适中
- 异构计算
GPU计算型:深度学习训练GPU虚拟化型:图形和图像处理
- 某些特殊领域和用途的服务:例如高主频、高内存等等
阿里云集群概况
集群概况
本文的kubernetes集群都是由阿里云ack托管的,其中包含了ACK Pro版和边缘 Pro 版两种类型的集群
边缘 Pro 版主要是涉及云上云下的GPU节点混合部署的集群
本文仅讨论ACK Pro集群(其中Master节点由阿里云容器服务创建并托管)
node节点的规划
1.1 阿里云ecs介绍
选择服务器的硬件资源配置就和我们购买办公或个人PC、笔记本一样,主要需要考虑主板、CPU、内存、硬盘等硬件配置
CPU与内存通信,主要通过地址、数据、控制三大总线
先简单了解一下CPU核数与内存的配比主要要遵守的基本原则
- 频率要同步:内存的核心频率要等于或稍大于
CPU的外频 - 带宽要匹配:内存的数据带宽跟
CPU前端总线的带宽尽量相等 - 主板要调控:当以上两个条件有时是不可能同时能满足时就要靠主板通过异步设置来调控
通常CPU和内存的配比是1:2、1:4、1:8,至于为什么,这也是一个值得讨论的话题
阿里云ack将集群的master节点托管了,因此只需要考虑如何规划node节点。由于是“花钱”买服务,当然要本着较高“性价比”的原则去合理搭配node节点的选型和配比
节点即虚拟机,在阿里云也叫做ECS,先来看下目前阿里云通用的x86节点有哪些种类,在阿里云官网将ECS实例分为很多种:通用型、计算型、内存型、大数据型、本地SSD型、高主频型、安全增强型、GPU型、异构服务型、突发型、共享型等等(简直太多了)
为了合理选型,一个重要的途径是理解ECS的实例规格族的命名方式和其信息布局,常见的如下
-
通用型,适用于大多数场景,代称是
g系列,其vCPU和内存的配比是1:4 -
计算型,某些场景下对
CPU算力要求会更高一点,代称是c系列,其vCPU和内存的配比是1:2 -
内存型,提供更多的内存能力,代称是
r系列,其vCPU和内存的配比是1:8 -
大数据型和本地
SSD型,这两种的CPU和内存的配比都是1:4,区别在于本地盘的类型不一样,导致适合的场景也是不一样的,大数据型的简称是d,本地SSD型简称是i -
高主频型,通常的
CPU的主频应该是2.5G赫兹,有一些可以是达到3.2G赫兹甚至更高,这种就是高主频型,代号会在前面加上hf标识
阿里云实例规格的命名方式和规律如下

实例选型原则通常遵循下面三点
- 相同大小的企业级实例比入门级实例性能更稳定,但入门级实例性价比更高,因为企业级实例独占
vCPU,不存在资源争抢 - 相同实例规格,新一代比老一代性价比更高,新一代实例规格释放更多技术红利
- 合适的实例规格搭配合适的块存储类型才能达到预期性能(高效云盘/
SSD/ESSD/本地盘)
1.2 k8s集群节点选型原则
k8s集群节点如何选型?
从CPU为出发点,CPU选定的同时,按照一定配比的内存大小也相应确定
节点区分标准线的划定。vCPU的个数是决定实例价格的关键,vCPU个数实例的一个xlarge单位代表4个vCPU,以8xlarge即32个vCPU为分界线,小于32个vCPU的实例划分为较小CPU核数即small节点,把大于或等于32个vCPU的实例划分为较大CPU核数即large节点
但是,需要购买分别高、低至多少个vCPU的节点作为k8s集群的node呢?换句话说,是使用更少的大节点还是使用更多的小节点来组建k8s集群呢?
可以把整个k8s集群中所有node组成的节点理解成为一个大型的单个节点,换句话说,这就和一台价格昂贵全部满配的物理机一样,其node节点就是这台物理机虚拟出来的VM
举个栗子,需要一个节点池总量为64C/256GB的集群,考虑k8s需要多节点,因此两个比较极端的配比是2台32C/128GB的较大节点和8台8C/32GB的较小节点
这里对大节点和小节点的优缺点分析和列举了以下几点
- 大节点个数总量较少,带来的管理成本会更少
- 大节点支持资源使用较高的“饥饿”型应用,即资源消耗较高的应用
- 发生
node节点级别的扩缩容时,大节点成本更高,因为一次就需要扩容配置较高的节点 - 大节点每个节点运行的
pod数较多,相应的k8s组件压力更大,当出现大批量pod频繁创建销毁时, 组件性能、时效性和可靠性都会下降,因此k8s官方推荐的节点pod最大数默认为110 - 大节点
pod副本分布更集中,由于节点数量减少,在同一个节点出现相关pod副本的可能性增大,当出现故障时,对pod影响较大。如果pod副本数更少,那么对整个应用来说,故障率和中断率也更高 - 按照阿里云资源预留公式推算的预留资源更多,大节点相对可分配给
pod的资源总量就会变少

说到这里,到底是该使用少量大节点还是大量小节点呢?按照上面的分析,各有利弊,因此并没有一定之规
退而求其次,可以均衡搭配,使用不同大小的节点来混合构建集群,对于某些特殊的服务,还可以单独做节点池
另外,对于worker任务型服务,充分利用云平台弹性伸缩能力,选用抢占式实例,更节省成本
k8s集群初始化创建时,会创建一个默认的节点池default-nodepool,一般会选择3台中等配置的ECS实例
往往为了应用在不同环境的隔离,在资源足够的情况下,会将dev、staging、prod等不同环境放在各自不同的集群中,当然也可以将prod生产环境单独做集群,dev和staging环境放在一套集群,这样成本更低
剩下就是根据应用的特点、成本设计与规划节点池
1.3 k8s集群 节点池设计
根据服务特性规划出不同的节点池,混合组建成集群,有助于集群资源利用率的提高
使用抢占式策略,并结合利用了公有云的弹性伸缩能力,用于自动扩缩集群节点数量,以真正实现资源利用率的提升,可以在较大程度上优化用户账单
根据业务现有相关服务的类型特点,加上合理考虑成本与收费类型的前提,加上默认的节点池,将节点池分为以下几类
| 节点池类型 | 适用环境 | 付费策略 | 节点池/节点命名 | 资源配额 | 服务特点 |
|---|---|---|---|---|---|
| 系统节点池 | prod nonprod | 包年包月 | default-nodepool | 适用于部署k8s集群系统组件 | |
| 稳定型节点池 | prod nonprod | 包年包月 | ${env}-packets | 32C/128GB/500GB | 适用于副本数相对稳定,资源要求相对适中,稳定性要求相对较高,版本迭代速率相对较小的核心服务 |
| 大磁盘型节点 | prod | 包年包月 | ${env}-disk-large | 32C/256GB/5TB | 适用于对磁盘读写空间较大的服务 |
| nonprod | 包年包月 | ${env}-disk-large | 16C/128GB/2TB | 适用于对磁盘读写空间较大的服务 | |
| 大配置节点 | prod nonprod | 抢占式 | ${env}-large | 32C/128GB/500GB 32C/256GB/500GB | 适用于CPU/Mem资源要求较大的worker类型服务 |
| 小配置节点 | prod nonprod |