马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

生产环境中的kubernetes 优先级与抢占

[复制链接]
查看2080 | 回复0 | 2019-10-22 09:05:00 | 显示全部楼层 |阅读模式

kubernetes 中的抢占功能是调理器比较紧张的feature,但是真正使用起来还是比较伤害,否则很轻易把低优先级的pod给无辜kill。为了进步GPU集群的资源使用率,决定勇于实行一番该featrue。固然使用之前还是得阅读一下相关的代码做到心里有数,出了问题也方便定位修复。

根本原理

优先级与抢占是为了确保一个高优先级的pod在调理失败后,可以通过"挤走" 低优先级的pod,腾出空间后包管它可以调理成功。 我们起首必要在集群中声明PriorityClass来界说优先品级数值和抢占计谋,

  1. <code>apiVersion: scheduling.k8s.io/v1
  2. kind: PriorityClass
  3. metadata:
  4. name: high
  5. value: 10000
  6. preemptionPolicy: Never
  7. globalDefault: false
  8. description: "This priority class should be used for high priority service pods."
  9. ---
  10. apiVersion: scheduling.k8s.io/v1
  11. kind: PriorityClass
  12. metadata:
  13. name: low
  14. value: -999
  15. globalDefault: false
  16. description: "This priority class should be used for log priority service pods."</code>
复制代码

如上所示界说了两个PriorityClass对象。然后就可以在pod中声明使用它了:

  1. <code>apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. labels:
  5. run: nginx
  6. name: high-nginx
  7. spec:
  8. replicas: 1
  9. selector:
  10. matchLabels:
  11. run: nginx
  12. template:
  13. metadata:
  14. labels:
  15. run: nginx
  16. spec:
  17. containers:
  18. - image: nginx
  19. imagePullPolicy: Always
  20. name: nginx
  21. resources:
  22. limits:
  23. cpu: "500m"
  24. priorityClassName: high</code>
复制代码

这个 Pod 通过 priorityClassName 字段。声明了要使用名叫 high-priority 的 PriorityClass。当这个 Pod 被提交给 Kubernetes 之后,Kubernetes 的 Priority AdmissionController 就会自动将这个 Pod 的spec.priority 字段设置为10000。
如下:

  1. <code> preemptionPolicy: Never
  2. priority: 10000
  3. priorityClassName: high</code>
复制代码

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-control flag来指定admissionoController的话必要手动添加Priority admissonController,如果是通过--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来限定某个优先级能使用的资源量:
  1. <code>apiVersion: v1
  2. kind: ResourceQuota
  3. metadata:
  4. name: high-priority
  5. spec:
  6. hard:
  7. pods: "10"
  8. scopeSelector:
  9. matchExpressions:
  10. - operator : In
  11. scopeName: PriorityClass
  12. values: ["high"]</code>
复制代码

如上即为限定高优先级的pod最多能创建10个。operator指定了作用的对象,operator: In可以显式指定作用于的哪些priorityClass,operator: Exists则指定作用于该namespace下的全部priorityClass。

  • 偶然候我们想要只有priorityClass对应的resourceQuota存在之后才气创建pod,确保全部的priorityClass的pod资源都是受控的。 如果谁人namespacew没有该resourceQuota则拒绝该pod的创建,该操纵可以通过指定--admission-control-config-file文件来设置,内容如下:
  1. <code>apiVersion: apiserver.k8s.io/v1alpha1
  2. kind: AdmissionConfiguration
  3. plugins:
  4. - name: "ResourceQuota"
  5. configuration:
  6. apiVersion: resourcequota.admission.k8s.io/v1beta1
  7. kind: Configuration
  8. limitedResources:
  9. - resource: pods
  10. matchScopes:
  11. - scopeName: PriorityClass
  12. operator: In
  13. values: ["high"]</code>
复制代码

该设置界说了: "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







来源:https://www.cnblogs.com/gaorong/p/11318328.html
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则