生产环境中的kubernetes 优先级与抢占
kubernetes 中的抢占功能是调度器比较重要的feature,但是真正使用起来还是比较危险,否则很容易把低优先级的pod给无辜kill。为了提高GPU集群的资源利用率,决定勇于尝试一番该featrue。当然使用之前还是得阅读一下相关的代码做到心里有数,出了问题也方便定位修复。
基本原理
优先级与抢占是为了确保一个高优先级的pod在调度失败后,可以通过"挤走" 低优先级的pod,腾出空间后保证它可以调度成功。 我们首先需要在集群中声明PriorityClass来定义优先等级数值和抢占策略,
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high
value: 10000
preemptionPolicy: Never
globalDefault: false
description: "This priority class should be used for high priority service pods."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: low
value: -999
globalDefault: false
description: "This priority class should be used for log priority service pods."
如上所示定义了两个PriorityClass对象。然后就可以在pod中声明使用它了:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: nginx
name: high-nginx
spec:
replicas: 1
selector:
matchLabels:
run: nginx
template:
metadata:
labels:
run: nginx
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: nginx
resources:
limits:
cpu: "500m"
priorityClassName: high
这个 Pod 通过 priorityClassName 字段。声明了要使用名叫 high-priority 的 PriorityClass。当这个 Pod 被提交给 Kubernetes 之后,Kubernetes 的 Priority AdmissionController 就会自动将这个 Pod 的spec.priority 字段设置为10000。
如下:
preemptionPolicy: Never
priority: 10000
priorityClassName: high
Pod创建好之后,调度器就会根据创建的priority进行调度的决策,首先会在等待队列中优先调度,如果调度失败就会进行抢占: 依次遍历所有的node找出最适合的node,将该nodename填充在spec.nominatedNodeName字段上,然后等待被抢占的pod全都退出后再次尝试调度到该node之上。具体的逻辑请自行阅读相关代码,此处不在赘述。
生产环境使用方式
- v1.14版本的kubernetes该feature已经GA,默认开启,但此时我们往往没有做好准备,如果直接给pod设置优先级会导致很多意料之外的抢占,造成故障。 (参见How a Production Outage Was Caused Using Kubernetes Pod Priorities)。所以建议在初次使用的时候还是先显式关闭抢占,只设置优先级,等集群中所有的pod都有了各自的优先级之后再开启,此时所有的抢占都是可预期的。可以通过kube-scheduler 配置文件中的
disablePreemption: true进行关闭 - 调度器是根据优先级pod.spec.priority数值来决定优先级的,而用户是通过指定pod.sepc.priorityclass的名字来为pod选择优先级的,此时就需要Priority AdmissionController根据priorityclass name为pod自动转换并设置对应的priority数值。我们需要确保该admissionController开启,如果你的kube-apiserver中还是通过
--admission-controlflag来指定admissionoController的话需要手动添加PriorityadmissonController,如果是通过--enable-admission-plugins来指定的话,无需操作,该admissionController默认开启。 - 按照集群规划创建对应的
PriorityClass及其对应的抢占策略,目前支持两种策略: Never, PreemptLowerPriority。 Never可以指定不抢占其他pod, 即使该pod优先级特别高,这对于一些离线任务较为友好。 非抢占调度在v1.15中为alpha, 需要通过--feature-gates=NonPreemptingPriority=true进行开启。 - 在创建好了PriorityClass之后,需要防止高优先级的pod过分占用太多资源,使用resourceQuota机制来限制其使用量,避免低优先级的pod总是被高优先级的pod压制,造成资源饥饿。resoueceQuote可以通过指定scope为
PriorityClass来限定某个优先级能使用的资源量:
apiVersion: v1
kind: ResourceQuota
metadata:
name: high-priority
spec:
hard:
pods: "10"
scopeSelector:
matchExpressions:
- operator : In
scopeName: PriorityClass
values: ["high"]
如上即为限制高优先级的pod最多能创建10个。operator指定了作用的对象,operator: In可以显式指定作用于的哪些priorityClass,operator: Exists则指定作用于该namespace下的所有priorityClass。
- 有时候我们想要只有priorityClass对应的resourceQuota存在之后才能创建pod,确保所有的priorityClass的pod资源都是受控的。 如果那个namespacew没有该resourceQuota则拒绝该pod的创建,该操作可以通过指定
--admission-control-config-file文件来设置,内容如下:
apiVersion: apiserver.k8s.io/v1alpha1
kind: AdmissionConfiguration
plugins:
- name: "ResourceQuota"
configuration:
apiVersion: resourcequota.admission.k8s.io/v1beta1
kind: Configuration
limitedResources:
- resource: pods
matchScopes:
- scopeName: PriorityClass
operator: In
values: ["high"]
该配置定义了: "high"优先级的pod只能在指定的namespaces下创建,该namespaces有作用于"high"优先级的resouceQuota,上面第四步中的resouceQuota即可满足要求。
scopeName定义了作用的对象为priorityClass, operator指定了作用的范围,可以是In操作符,指定某几个value, 也可以是Exits操作符,指定所有的PriorityClass必须有对应的quota存在, 否则该namespace就无法创建该优先级的pod,这些操作符与上面resouceQuota中定义的一一对应。通过这样就限制了一些优先级只能在有资源约束的namespace下创建。
- 如果没有显式指定优先级,则默认的优先级值为0,需要结合业务规划决定是否有必要调整默认优先级。
- 对于一些daemonset需要显式设置较高的优先级来防止被抢占,在部署一个新的daemonset的时候需要考虑是否会造成大规模pod的抢占。
- 等到所有的优先级设置完毕之后就可以开启抢占功能了,此时集群中所有pending 的高优先级pod就会瞬间抢占,还是需要额外小心,确保集群中高优先级的pod不会导致低优先级的pod大规模被kill,如果我们提前设置了对应的resource quota值,则会有一定的资源约束。
- 优先级和抢占对于资源的精细化运营考验很大,对于resource quota的设置需要十分精细,需要考虑两个维度来设置: namespace层面和priority层面,我们既希望限制namespace使用的资源,有希望某个priority使用的资源,防止低优先级的pod资源饥饿。 可以在初期只考虑namespace层面的限制,priority层面通过上层业务来保证,例如创建任务的时候保证集群中高优先级的资源使用量不超过50%等。
其他思考
笔者的线上环境中, 有些再跑的模型训练任务业务对于自动failove实现不是很好,如果中途被抢占了只能从头开始计算,需要占用额外的GPU资源,这种工作类型不允许被抢占,但是如果把他设置为高优先级又不太合适,因为它确实不是最高的优先级,优先级最高的还是在线业务,不能让它抢占在线业务。 它属于中间优先级,可以抢占低优先级的pod。 经过探索发现目前kubernetes并不支持该中类型,当前支持的抢占策略为: Never, PreemptLowerPriority都无法满足需求。所以在此基础上开发了NonPreemptible类型的抢占策略,该优先级的pod是不允许被其他人抢占的,调度还是按照优先级在队列里排队,但是一旦调度上去就无法被抢占。
这种抢占策略略显"霸道",所以需要谨慎使用,设置resouceQuota,并且只能由特定的任务使用。 并且为了不影响deamonset等优先级最高的任务,允许被某个指定Priority数值之上的pod抢占。并且随着业务的发展,这部分逻辑需要逐步去掉,之所有存在这部分逻辑是因为pod不能被中断,不能被抢占,所以还是需要使这些任务支持重启与挂起,具体来说就是: pod挂载远程磁盘并自动checkpoint,重启之后从以前的恢复点继续执行。等这些业务改造完成之后,逐步去掉这种工作抢占策略
reference
Pod Priority and Preemption
Priority in ResourceQuota
Allow PriorityClasses To Be Non-Preempting
生产环境中的kubernetes 优先级与抢占的更多相关文章
- Kubernetes 在生产环境中常用架构
Kubernetes 在生产环境中常用架构 首先,我们来梳理下Kubernetes生产架构,其设计适用于绝大多数环境.如下图所示 在该架构中,我们可以将其分为四层,如下: Client层:即Kuber ...
- Kubernetes用户指南(三)--在生产环境中使用Pod来工作、管理部署
一.在生产环境中使用Pod来工作 本节将介绍一些在生产环境中运行应用非常有用的功能. 1.持久化存储 容器的文件系统只有当容器正常运行时有效,一旦容器奔溃或者重启,所有对文件系统的修改将会丢失,从一个 ...
- 生产环境中使用Docker Swarm的一些建议
译者按: 实践中会发现,生产环境中使用单个Docker节点是远远不够的,搭建Docker集群势在必行.然而,面对Kubernetes, Mesos以及Swarm等众多容器集群系统,我们该如何选择呢?它 ...
- Dubbo Mesh 在闲鱼生产环境中的落地实践
本文作者至简曾在 2018 QCon 上海站以<Service Mesh 的本质.价值和应用探索>为题做了一次分享,其中谈到了 Dubbo Mesh 的整体发展思路是“借力开源.反哺开源” ...
- 明白生产环境中的jvm参数
明白生产环境中的jvm参数 写代码的时候,程序写完了,发到线上去运行,跑一段时间后,程序变慢了,cpu负载高了--一堆问题出来了,所以了解一下生产环境的机器上的jvm配置是有必要的.比如说: JDK版 ...
- .NET跨平台之旅:在生产环境中上线第一个运行于Linux上的ASP.NET Core站点
2016年7月10日,我们在生产环境中上线了第一个运行于Linux上的ASP.NET Core站点,这是一个简单的提供后端服务的ASP.NET Core Web API站点. 项目是在Windows上 ...
- 理解Docker(6):若干企业生产环境中的容器网络方案
本系列文章将介绍 Docker的相关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...
- .NET跨平台之旅:生产环境中第2个跑在Linux上的ASP.NET Core站点
今天我们在生产环境中上线了第2个跑在Linux上的ASP.NET Core站点.这是一个简单的Web API站点,通过命令行的方式调用安装在Linux服务器上的程序完成操作.之前用的是nodejs,现 ...
- 【原】Storm Local模式和生产环境中Topology运行配置
Storm入门教程 1. Storm基础 Storm Storm主要特点 Storm基本概念 Storm调度器 Storm配置 Guaranteeing Message Processing(消息处理 ...
随机推荐
- 新手学习FFmpeg - 调用API调整视频局部速率
通过修改setpts代码实现调整视频部分的播放速率. 完整代码可参考: https://andy-zhangtao.github.io/ffmpeg-examples/ 在前面提到了PTS/DTS/T ...
- Webdriver元素定位的方法
webdriver提供了8种元素定位方法: 1.id 2.name 3.tag name 4.class name 5.link text 6.partial link text 7.xpath 8. ...
- (附源码gitHub下载地址)spring boot -jta-atomikos分布式事务
应用场景:双数据源,就是某些项目会涉及到两个数据源或者两个以上的数据源,这个多数据源的项目一般是数据同步,也就是把数据从另一个系统中,保存到另一个系统,两边的 数据库又不一样,比如一个Mysql.一个 ...
- JAVA多线程高并发面试题总结
ReadMe : 括号里的内容为补充或解释说明. 多线程和高并发是毕业后求职大厂面试中必问的知识点,自己之前总是面试前才去找相关的知识点面试题来背背,隔段时间又忘了,没有沉淀下来,于是自己总结了下相关 ...
- Http 协议简略
用户在浏览器中输入一个网址并回车,浏览器会向服务器发送一个http请求,服务器端程序会接受这个请求,并对请求进行相应的处理,然后发送一个回应,浏览器收到回应,再把回应的内容显示到页面,这种请求—相应的 ...
- Linux 笔记 - 第八章 文档的打包与压缩
博客地址:http://www.moonxy.com 一.前言 在 Linux 系统中,文件的后缀名没有实际的意义,加或者不加都无所谓.但是为了便于区分,我们习惯在定义文件名时加一个后缀名,比如常见的 ...
- C++ const 引用 指针
先简单回忆一下常量的性质: int main() { const int buffSize = 512; buffsize = 512; //× buffSize是常量 } 初始化时: const i ...
- C# 10分钟入门基于WebOffice实现在线编辑文档,实时保存到服务器(所有office,兼容WPS)
今天,他来了(weboffice在线编辑文档). 上次写了一个在线预览的博,当然,效果并不是太理想,但是紧急解决了当时的问题. 后来,小编重新查找资料,求助大牛,终于使用新的方式替换了之前的low方法 ...
- 豆瓣电影TOP250和书籍TOP250爬虫
豆瓣电影 TOP250 和书籍 TOP250 爬虫 最近开始玩 Python , 学习爬虫相关知识的时候,心血来潮,爬取了豆瓣电影TOP250 和书籍TOP250, 这里记录一下自己玩的过程. 电影 ...
- (转)在阿里云 CentOS 服务器(ECS)上搭建 nginx + mysql + php-fpm 环境
阿里云的云服务器(ECS)可以选择多种操作系统,打算用它运行 Drupal或者 WordPress ,你最好选择 Linux 系统,这篇文章的演示是基于阿里云的 CentOS 操作系统的服务器.我们在 ...