Kubernetes自定义调度器 — 初窥门径

Prodan Labs 等级 596 0 0

Kubernetes自定义调度器 — 初窥门径 通过上一篇文章对scheduler-framework调度框架已经有了大致了解,根据我们的实际生产的一些问题(如计算服务没有被调度到实际CPU最优的节点)和需求,来实现一个简单的基于CPU指标的自定义调度器。自定义调度器通过kubernetes资源指标服务metrics-server来获取各节点的当前的资源情况,并进行打分,然后把Pod调度到分数最高的节点

PreFilter扩展点


对Pod的信息进行预处理,检查Pod或集群是否满足前提条件。

通过pod已声明的Annotations参数 rely.on.namespaces/namerely.on.pod/labs来获取该pod依赖的pod是否就绪,如依赖的pod未就绪,则终止调度,pod处于Pending状态。

func (pl *sample) PreFilter(ctx context.Context, state *framework.CycleState, p *v1.Pod) *framework.Status {

  namespace := p.Annotations["rely.on.namespaces/name"]
  podLabs := p.Annotations["rely.on.pod/labs"]

  if namespace == "" || podLabs == "" {
    return framework.NewStatus(framework.Success, "ont rely")
  }
  if prefilter.IsExist(namespace) == false {
    return framework.NewStatus(framework.Unschedulable, "not found namespace: "+namespace)
  }

  if prefilter.IsReady(namespace, podLabs) == false {
    return framework.NewStatus(framework.Unschedulable, "rely pod not ready")
  }
  klog.Infoln("rely pod is ready :", namespace, podLabs, prefilter.IsReady(namespace, podLabs))
  return framework.NewStatus(framework.Success, "rely pod is ready")
}

调度失败结果:

Events:
  Type     Reason            Age   From              Message
  ----     ------            ----  ----              -------
  Warning  FailedScheduling  9s    sample-scheduler  0/2 nodes are available: 2 rely pod not ready.
  Warning  FailedScheduling  9s    sample-scheduler  0/2 nodes are available: 2 rely pod not ready.

如满足Pod的前置条件,则正常调度,进入下一阶段

I1025 12:26:59.435773       1 plugins.go:50] rely pod is ready : kube-system k8s-app=metrics-server true

Filter扩展点


对不满足Pod调度要求的节点进行过滤掉。


func (pl *sample) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, node *framework.NodeInfo) *framework.Status {

  if node.Node().Labels["cpu"] != "true" {
    return framework.NewStatus(framework.Unschedulable, "not found labels")
  }
  nodeUsedCPU, nodeUsedMen, nodeCPU, nodeMen, cpuRate, menRate := filter.ResourceStatus(node.Node().Name)

  for i := 0; i < len(pod.Spec.Containers); i++ {
    requestsCPUCore, _ := strconv.ParseFloat(strings.Replace(pod.Spec.Containers[i].Resources.Requests.Cpu().String(), "n", "", 1), 64)
    requestsCPU := requestsCPUCore * 1000 * (1000 * 1000)
    requestsMen := pod.Spec.Containers[i].Resources.Requests.Memory().Value() / 1024 / 1024
    limitsCPUCore, _ := strconv.ParseFloat(strings.Replace(pod.Spec.Containers[i].Resources.Limits.Cpu().String(), "n", "", 1), 64)
    limitsCPU := limitsCPUCore * 1000 * (1000 * 1000)
    limitsMen := pod.Spec.Containers[i].Resources.Limits.Memory().Value() / 1024 / 1024
    if requestsCPU > float64(nodeCPU) || requestsMen > nodeMen {
      return framework.NewStatus(framework.Unschedulable, "out of Requests resources")
    }
    if limitsCPU > float64(nodeCPU) || limitsMen > nodeMen {
      return framework.NewStatus(framework.Unschedulable, "out of Limits resources")
    }
    if requestsCPU > float64(nodeCPU)-nodeUsedCPU || requestsMen > (nodeMen-nodeUsedMen) {
      return framework.NewStatus(framework.Unschedulable, "out of Requests resources system")
    }
    if limitsCPU > float64(nodeCPU)-nodeUsedCPU || limitsMen > (nodeMen-nodeUsedMen) {
      return framework.NewStatus(framework.Unschedulable, "out of Limits resources system")
    }

  }

  klog.Infof("node:%s, CPU:%v ,  Memory: %v", node.Node().Name, cpuRate, menRate)
  cpuThreshold := filter.GetEnvFloat("CPU_THRESHOLD", 0.85)
  menThreshold := filter.GetEnvFloat("MEN_THRESHOLD", 0.85)
  if cpuRate > cpuThreshold || menRate > menThreshold {
    return framework.NewStatus(framework.Unschedulable, "out of system resources")
  }

  return framework.NewStatus(framework.Success, "Node: "+node.Node().Name)
}

过滤掉没有 cpu=true labels的节点; Pod调度资源值和限制资源值大于节点当前可用资源的节点,则过滤; 默认过滤cpu内存使用率超过 85%的节点。 CPU_THRESHOLDMEN_THRESHOLD 环境变量设置该值。 调度失败结果:

Events:
  Type     Reason            Age    From              Message
  ----     ------            ----   ----              -------
  Warning  FailedScheduling  9m33s  sample-scheduler  0/2 nodes are available: 1 Insufficient cpu, 1 out of Limits resources system.
  Warning  FailedScheduling  9m33s  sample-scheduler  0/2 nodes are available: 1 Insufficient cpu, 1 out of Limits resources system.

可以通过日志查看当前获取到的系统资源利用率

I1025 12:29:21.360979       1 plugins.go:87] node:k8s-test09, CPU:0.06645718025 ,  Memory: 0.33549941504789904
I1025 12:29:21.361471       1 plugins.go:87] node:k8s-test10, CPU:0.0411259705 ,  Memory: 0.15946609553600768

Score扩展点


用于对已通过过滤阶段的节点进行打分。

func (pl *sample) Score(ctx context.Context, state *framework.CycleState, p *v1.Pod, nodeName string) (int64, *framework.Status) {

  isSamePod := score.IsSamePod(nodeName, p.Namespace, p.Labels) // max 2
  cpuLoad := score.CPURate(nodeName)                            // max 3
  menLoad := score.MemoryRate(nodeName)                         // max 3
  core := score.CpuCore(nodeName)                               // max 3

  c := isSamePod + cpuLoad + core + menLoad
  klog.Infoln(nodeName+" score is :", c)
  return c, framework.NewStatus(framework.Success, nodeName)
}

打分规则:

  • 配置高的节点权重大
  • 当前资源使用率底的节点权重大
  • 运行多组pod的情况下,运行相同pod的节点权重底
  • 如果Score插件的打分结果不是[0-100]范围内的整数,则调用NormalizeScore进行归一化。

调度结果:

I1025 12:28:35.620198       1 plugins.go:105] k8s-test10 score is : 6
I1025 12:28:35.626170       1 plugins.go:105] k8s-test09 score is : 7
I1025 12:28:35.626394       1 trace.go:205] Trace[232544630]: "Scheduling" namespace:default,name:test-scheduler-84859f9467-rgfpd (25-Oct-2020 12:28:35.488) (total time: 137ms):
Trace[232544630]: ---"Computing predicates done" 38ms (12:28:00.526)
Trace[232544630]: ---"Prioritizing done" 99ms (12:28:00.626)
Trace[232544630]: [137.453956ms] [137.453956ms] END
I1025 12:28:35.626551       1 default_binder.go:51] Attempting to bind default/test-scheduler-84859f9467-rgfpd to k8s-test09
I1025 12:28:35.632736       1 eventhandlers.go:205] delete event for unscheduled pod default/test-scheduler-84859f9467-rgfpd
I1025 12:28:35.632893       1 scheduler.go:597] "Successfully bound pod to node" pod="default/test-scheduler-84859f9467-rgfpd" node="k8s-test09" evaluatedNodes=2 feasibleNodes=2
I1025 12:28:35.633369       1 eventhandlers.go:225] add event for scheduled pod default/test-scheduler-84859f9467-rgfpd 
I1025 12:29:21.328791       1 eventhandlers.go:173] add event for unscheduled pod default/test-scheduler-84859f9467-48wlr
I1025 12:29:21.328897       1 scheduler.go:452] Attempting to schedule pod: default/test-scheduler-84859f9467-48wlr
I1025 12:29:21.351126       1 plugins.go:50] rely pod is ready : kube-system k8s-app=metrics-server true
I1025 12:29:21.360979       1 plugins.go:87] node:k8s-test09, CPU:0.06645718025 ,  Memory: 0.33549941504789904
I1025 12:29:21.361471       1 plugins.go:87] node:k8s-test10, CPU:0.0411259705 ,  Memory: 0.15946609553600768
I1025 12:29:21.419137       1 plugins.go:105] k8s-test10 score is : 6
I1025 12:29:21.419210       1 plugins.go:105] k8s-test09 score is : 5
I1025 12:29:21.419407       1 default_binder.go:51] Attempting to bind default/test-scheduler-84859f9467-48wlr to k8s-test10
I1025 12:29:21.427243       1 scheduler.go:597] "Successfully bound pod to node" pod="default/test-scheduler-84859f9467-48wlr" node="k8s-test10" evaluatedNodes=2 feasibleNodes=2
I1025 12:29:21.427441       1 eventhandlers.go:205] delete event for unscheduled pod default/test-scheduler-84859f9467-48wlr
I1025 12:29:21.427472       1 eventhandlers.go:225] add event for scheduled pod default/test-scheduler-84859f9467-48wlr 

完整的示例代码: https://github.com/prodanlabs/scheduler-framework Kubernetes自定义调度器 — 初窥门径


感兴趣的读者可以关注下微信号 Kubernetes自定义调度器 — 初窥门径

收藏
评论区

相关推荐

Kubernetes(k8s)中文文档 Kubernetes概述
简介 Kubernetes(https://www.kubernetes.org.cn/)是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。 Kubernetes一个核心的特点就是能够自主的管理容
k8s超详细总结
一个目标:容器操作;两地三中心;四层服务发现;五种Pod共享资源;六个CNI常用插件;七层负载均衡;八种隔离维度;九个网络模型原则;十类IP地址;百级产品线;千级物理机;万级容器;相如无亿,K8s有亿:亿级日服务人次。 一个目标:容器操作 Kubernetes(k8s)是自动化容器操作的开源平台。这些容
Kubernetes + GitLab 微服务应用自动化部署
Kubernetes GitLab 微服务应用自动化部署 Docker 简化了单个服务的部署,Kubernetes 通过强大的容器编排能力使得运维人员可以轻松管理成千上万的容器,这些容器归属于多个服务,而这些服务又组合形成了多个应用。从代码到运行中的应用,需要经历构建、打包、测试和部署等阶段,如果每个步骤都手动执行,无疑会消耗研发人员的大量时间。本文讲解
Kubernetes Ingress — NGINX
在 Kubernetes 中,Service 是一种抽象的概念,它定义了每一组 Pod 的逻辑集合和访问方式,并提供一个统一的入口,将请求进行负载分发到后端的各个 Pod 上。Service 默认类型是 ClusterIP,集群内部的应用服务可以相互访问,但集群外部的应用服务无法访问。为此 Kubernetes 提供了 NodePorts,LoadBalan
Kubernetes Ingress — Kong
Kong 是由 Mashape 公司开源的一个高性能、高可用、易扩展的 API Gateway 项目,基于OpenResty(Nginx Lua模块),并提供了插件实现 API 的 AOP 功能。可以通过负载均衡、插件扩展等方式,来处理网络请求。 Kong 主要的概念Servi
Kubernetes部署高可用PostgreSQL集群
PostgreSQL 是一个功能强大的开源关系数据库,它使用和扩展了 SQL 语言,并结合了许多安全存储和扩展最复杂数据工作负载的功能。PostgreSQL 的起源可以追溯到 1986 年,作为加利福尼亚大学伯克利分校 POSTGRES 项目的一部分,与 Linux 内核相似,PostgreSQL 是由社区驱动的开源项目,由全世界贡献者所维护。Postgre
Kubernetes Pod 自动扩容 — HPA
Kubernetes 增强了应用服务的横向扩容能力,在应对线上应用服务的资源使用率在高峰和低谷的时候,我们需要能够自动去感知应用的负载变化去调整 Pod 的副本数量,削峰填谷,提高集群的整体资源利用率和应用的服务质量。为此,Kubernetes 1.2 版本中引入 Horizontal Pod Autoscaling (HPA), 它与 kubectl sc
Kubernetes自定义调度器 — 初识调度框架
Kubernetes 已经成为容器编排(Orchestration)平台的事实标准,它为容器化应用提供了简单且高效部署的方式、大规模可伸缩、资源调度等生命周期管理功能。kubescheduler作为kubernetes的核心组件,它负责整个集群资源的调度功能,根据特定的调度算法或调度策略,将Pod调度到最优的Node节点,使集群的资源得到合理且充分的利用。
Kubernetes自定义调度器 — 初窥门径
通过上一篇文章对schedulerframework调度框架已经有了大致了解,根据我们的实际生产的一些问题(如计算服务没有被调度到实际CPU最优的节点)和需求,来实现一个简单的基于CPU指标的自定义调度器。自定义调度器通过kubernetes资源指标服务metricsserver来获取各节点的当前的资源情况,并进行打分,然后把Pod调度到分数最高的节
Prometheus架构与实践分享
Prometheus已经被广泛应用于数据中心监控,尤其是和Kubernetes结合的容器监控。本文主要从架构分析到落地实践,详细介绍Prometheus原理和使用。对比Prometheus与其他监控工具(Zabbix、OpenFalcon)的特点与使用场景。然后介绍Prometheus与Kubernetes集成,主要从监控和自动伸缩两个方面。最后通过企业案
基于k8s的DevOps实践之路
原标题:基于k8s的DevOps实践之路很多快速发展的公司都面临着一个巨大挑战:在需求不断动态横向扩容的同时继续保持系统的高可用性。如何有效解决这一问题,Kubernetes(k8s)应运而生。k8s以运行可扩展工作负载而闻名,它可以根据资源使用情况调整工作负载。白山科技云分发团队基于多年的DevOps实践经验,在白山会运维日第三期与Thoughtworks
SRE和DevOps值得关注的十大开源项目
构建可扩展且高度可靠的软件系统是每个SRE的最终目标。在SRE/DevOps领域中,有大量出色的开源项目,每个项目都有新颖而激动人心的解决方案。在本文中,我们将会介绍一些在监视,部署和维护领域最受欢迎的开源项目。 1\. Cloudprober可以主动跟踪和监视应用程序,并帮助你提前发现故障。它使用“活动(active)”监视模型来检查你的组件是否按预
2021年值得关注的五个云原生安全问题
云原生正变得越来越流行,在2020年,统计发现,其中83%的组织也在生产环境中使用kubernetes。由于,团队可以轻松地构建和使用,,,以及管理服务,而不必担心底层的服务器。但是,云原生安全性仍然是一个真正的挑战。奇怪的是,云原生安全性的最大问题与所有新技术无关。首席安全官表示,如果组织希望以更好地开始新的一年,则应着手解决五个主要的云原生安全性问题。有
2021年云原生技术趋势
2020年3月下旬的几周时间里,COVID19使全球业务停滞不前,因此每个人都在试图找出应对这种疫情的最佳方法。那时候,没有人知道会发生什么,因此会议被取消,合同被搁置,项目被推迟。一切都停止了。但是,到2020年4月初,我们见证了IT社区的工作重新焕发活力。尽管其他行业还不能恢复正常,但很快我们就明白,仍然需要IT来进行经济和社会活动。你甚至可以得出这样
PaaS失败了吗?让我们看看Cloud Foundry的优势
软件团队常见的行为方式可以总结如下:1. 软件部署从Heroku或Firebase开始。2. 在应用程序需要快速扩展时,开始使用Docker进行容器化。3. 在遇到Docker困境的时候,考虑使用Kubernetes等容器编排工具。(https://cdn.thenewstack.io/media/2020/12/5105a24aimage011.