Kubernetes--Pod优先级调度

一、Pod Priority Preemption

    对于运行的各种负载(如Service、Job)的中等规模或者打规模的集群来说,由于各种原因,需要尽可能提高集群的资源利用率。而提高资源利用率的常规做法是采用优先级方案,即不同负载对应不用的优先级,同时允许集群中的所有负载所需的资源超过集群可提供的资源,在这种情况下,当发生资源不足的情况下时,系统可以选择性释放一些不重要的负载(优先级最低的),保证最重要的负载能够获取足够的资源稳定运行。

     在Kubernetes1.8版本之前,当集群的可用资源不足时,在用户提交新的Pod创建请求之后,该Pod会一直处于Pending状态,即使这个Pod是一个重要的Pod,也只能被动等待其它Pod被删除并释放资源,才能被调度成功。Kubernetes 1.8版本之后引入基于Pod优先级(Pod Priority Preempition)的调度策略,此时Kubernetes会尝试释放Pod,这种调度方式被称为“抢占式调度”。如果声明一个负载相对其它负载“更重要”,可以通过以下几个维度定义:

  • Priority,优先级
  • Qos,服务器质量等级
  • 系统定义的其它度量指标

   优先级抢占式调度策略的核心行为分别是驱逐(Eviction)和抢占式(Preemption),这两种行为使用场景不同,效果相同。

          Eviction是kubelet进程的行为,即当一个Node资源不足时(under resource pressure)的情况时,该节点上的kubelet进程会执行驱逐动作,此时Kubelet会综合考虑Pod的优先级、资源申请量与实际使用量等信息计算哪些Pod需要驱逐;当同样优先级的Pod需要被驱逐时,实际使用的资源量超过申请量最大倍数的高耗能Pod会被首先驱逐。对于Qos等级为"Best Effort"的Pod来说,由于没有定义资源申请(CPU/Memory Request),所以它们实际使用的资源可能非常大。

     Preemption是Scheduler执行的行为,当一个新的Pod因为资源无法满足而不能被调度时,Scheduler可能(有权决定)选择驱逐部分优先级低的Pod实例来满足此Pod的调度目标,这就是Preemption机制。Scheduler可能会驱逐Node A上的一个Pod以满足Node B上的一个新的Pod调度任务。比如:

      一个低优先级的Pod A在Nde A(属于机架R)上运行时,此时一个高优先级的Pob B等待调度,目标节点同属于机架R,他们中的一个或全部都定义了anti-affinity规则,不允许在同一个机架上运行,此时Scheduler只好驱逐低优先级的Pod A以满足高优先级的Pod B调度。

二、Pod优先级调度例子

 首先由管理员创建PriorityClasses,PriorityClass不属于任何命名空间:

apiVersion: schedule.k8s.io/v1beta1
kind: PriorityClass
metadate:
  name: high-priority
value: 100000
globalDefault: false
description: "This priority class should be use service pods only"

    上述YAML文件定义了一个名为high-priority的优先级类别,优先级为100000,数字越大,优先级越高,超过1亿的 数字被系统保留,用于指派给系统组件。

apiVersion: v1
kind: Pod
metadata:
- name: nginx
  label:
    env: test
spec:
  containers:
  - name: nignx
    image: nginx
    imagePullPolicy: IfNotPresent
    priorityClassName: higt-priority

    如果发生了需要抢占式的调度,高优先级 Pod就可能抢占节点N,并且将其低优先级的Pod驱逐出节点N,高优先级Pod的status信息中的nominiatedNodeName字段会记录目标节点N的名称。需要注意,高优先级Pod仍然无法保证最终被调度到节点N上,在节点N上低优先级Pod被驱逐过程中,如果有新的节点满足高优先级Pod的需求,又出现了优先级更高的Pod,调度器会调度这个更高优先级的Pod到节点N上,并重新调度之前等待的高优先级Pod。

    优先级抢占式调度可能会导致调度陷入”死循环“状态。当Kubernetes集群配置了多个调度器(Scheduler)时,这一行为可能会发生,比如:

    scheduler A为了调度一个(批)Job,特定驱逐一些Pod,因此在集群中有了空余的空间可以用来调度,此时Scheduler B恰好抢先在Scheduler A之前调度了一个新的Pod,消耗了相应的资源。因此,Scheduler A清理完资源后正式发起Pod调度时,却发现资源不足,被目标节点的kubelet进程拒绝调度请求,这种情况就无解了,最好的做法就是让多个Scheduler协同工作共同实现一个目标。

    使用优先级抢占式调度策略可能会导致某些Pod永远无法成功被调度。因此优先级调度不但增加了系统的复杂性,还可能带来额外的不稳定因素。因此,一旦资源紧张局面,首先考虑的是集群扩容。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用kubernetes-client java获取pod容器内存与CPU使用率,可以按照以下步骤进行操作。 首先,你需要在Java项目中添加kubernetes-client的依赖,例如在pom.xml文件中添加以下代码: ```xml <dependencies> <dependency> <groupId>io.kubernetes</groupId> <artifactId>client-java</artifactId> <version>9.0.0</version> </dependency> </dependencies> ``` 接下来,你可以使用以下代码获取pod的相关信息: ```java import io.kubernetes.client.apis.CoreV1Api; import io.kubernetes.client.custom.Quantity; import io.kubernetes.client.models.V1Container; import io.kubernetes.client.models.V1ContainerStatus; import io.kubernetes.client.models.V1NamespaceList; import io.kubernetes.client.models.V1Pod; import io.kubernetes.client.models.V1PodList; import io.kubernetes.client.models.V1PodMetrics; import io.kubernetes.client.models.V1PodMetricsList; import io.kubernetes.client.util.Config; import java.util.Map; public class KubernetesClientExample { public static void main(String[] args) throws Exception { // 创建Kubernetes客户端 io.kubernetes.client.Configuration config = Config.defaultClientConfig(); io.kubernetes.client.apis.CoreV1Api api = new CoreV1Api(); // 获取pod列表 V1PodList podList = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null); for (V1Pod pod : podList.getItems()) { // 获取pod所属的命名空间和名称 String namespace = pod.getMetadata().getNamespace(); String name = pod.getMetadata().getName(); // 获取pod容器列表和相关状态信息 for (V1Container container : pod.getSpec().getContainers()) { String containerName = container.getName(); V1ContainerStatus containerStatus = pod.getStatus().getContainerStatuses().stream() .filter(status -> status.getName().equals(containerName)) .findFirst().orElse(null); if (containerStatus != null) { // 获取容器的CPU和内存使用率 Map<String, Quantity> usage = containerStatus.getUsage(); Quantity cpuUsage = usage.get("cpu"); Quantity memoryUsage = usage.get("memory"); System.out.println("Namespace: " + namespace + ", Pod: " + name + ", Container: " + containerName + ", CPU Usage: " + cpuUsage + ", Memory Usage: " + memoryUsage); } } } } } ``` 上述代码中,我们首先创建了Kubernetes的客户端,然后通过CoreV1Api实例来获取pod列表。对于每个pod,我们遍历其容器列表,并获取容器的名称以及相关状态信息。在状态信息中,我们可以找到容器的CPU和内存使用率,以及其他相关指标。 需要注意的是,这里获取的是当前时刻的使用率数据,如果你想要定时获取容器的使用率信息,可以使用定时任务等方法来实现。 这是一个简单的示例,你可以根据实际需求和项目结构进行相应的扩展和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值