Kubernetes之Scheduler详解

本文尝试从Kubernetes Scheduler的功能介绍、交互逻辑、伪代码实现、最佳实践、自定义Scheduler举例及其历史演进6个方面进行详细阐述。希望对您有所帮助!

一、Kubernetes Scheduler 功能

Kubernetes Scheduler 是 Kubernetes 集群的核心组件之一,负责将新创建的 Pod 分配到合适的节点上。它根据一系列规则和策略,确保集群资源的最佳利用和应用的高效运行。以下是 Kubernetes Scheduler 的功能详解。

1. Scheduler 工作流程

Kubernetes Scheduler 的工作流程主要包括以下几个步骤:

  1. 监听未分配的 Pod:Scheduler 监听 API Server,当有新的 Pod 被创建且未绑定到任何节点时,Scheduler 会将其加入调度队列中。
  2. 预选节点(Filtering):Scheduler 通过一系列过滤规则筛选出符合条件的节点。例如,节点是否有足够的资源(CPU、内存等)、节点是否满足 Pod 的亲和性/反亲和性规则等。
  3. 优选节点(Scoring):对通过过滤的节点进行打分,依据不同的优选规则对节点进行评分(如节点资源的剩余情况、Pod 分布等),最终选择得分最高的节点。
  4. 绑定 Pod 到节点:Scheduler 将 Pod 绑定到选定的节点,API Server 会更新 Pod 的状态。

2. Scheduler 的主要功能

节点过滤(Predicates)

节点过滤是调度过程中的第一步,主要包括以下几种过滤规则:

  • PodFitsResources:检查节点是否有足够的资源(CPU、内存等)供 Pod 使用。
  • PodFitsHostPorts:检查节点上是否有指定的主机端口可用。
  • PodFitsHost:检查 Pod 是否要求运行在特定的节点上。
  • NoDiskConflict:检查节点上是否有 Pod 使用了同一持久卷。
  • MatchNodeSelector:检查节点标签是否满足 Pod 的节点选择器要求。
  • CheckNodeUnschedulable:检查节点是否可调度。
  • PodToleratesNodeTaints:检查 Pod 是否容忍节点的污点。
节点优选(Priorities)

在通过过滤规则后,Scheduler 会对符合条件的节点进行打分,依据不同的优选规则对节点进行评分:

  • LeastRequestedPriority:优先选择资源请求最少的节点。
  • BalancedResourceAllocation:优先选择资源分配最平衡的节点。
  • NodePreferAvoidPodsPriority:优先选择没有被其他 Pod 标记为“避开”的节点。
  • NodeAffinityPriority:依据节点亲和性规则对节点进行打分。
  • TaintTolerationPriority:依据污点容忍规则对节点进行打分。
Pod 亲和性和反亲和性(Pod Affinity and Anti-Affinity)

Pod 亲和性和反亲和性允许用户定义更复杂的调度规则,以确保 Pod 能够调度到特定的节点或避免调度到某些节点。例如,可以定义 Pod 必须与某些标签的 Pod 在同一节点上,或者必须与某些标签的 Pod 不在同一节点上。

节点亲和性(Node Affinity)

节点亲和性允许用户定义 Pod 只能调度到某些特定的节点。它是节点选择器的更灵活和表达力更强的形式,可以基于节点的标签进行配置。

Taints 和 Tolerations

Taints 和 Tolerations 用于避免 Pod 被调度到不适合的节点。节点可以有污点(Taints),只有容忍这些污点(Tolerations)的 Pod 才能被调度到这些节点上。

3. 自定义 Scheduler

Kubernetes 允许用户编写和部署自定义的调度器,替代默认的调度器或与之共存。以下是编写自定义调度器的基本步骤:

  1. 创建调度器插件:基于 Kubernetes 提供的调度框架,创建新的调度插件。调度插件可以是过滤插件、打分插件、预绑定插件等。
  2. 配置调度器:在 kube-scheduler 配置文件中添加或修改调度插件。
  3. 部署自定义调度器:将自定义调度器部署到 Kubernetes 集群中,并在 Pod 定义中指定使用自定义调度器。

4. 调试和监控

Kubernetes Scheduler 提供了多种调试和监控工具,以便用户了解调度过程并解决调度问题。例如:

  • 调度事件日志:Scheduler 会记录调度过程中的事件日志,可以通过查看这些日志来了解调度过程。
  • 调度指标:Scheduler 提供了一些 Prometheus 指标,可以用来监控调度性能和调度决策。

通过上述功能和工具,Kubernetes Scheduler 能够实现灵活、高效的调度策略,满足不同应用的需求。

二、Kubernetes Scheduler与其他组件交互示意图

下图表示 Kubernetes Scheduler 与其他组件交互过程 。图示包括 API Server、Scheduler、Controller Manager、etcd、Kubelet 和节点。

示意图

User API Server Scheduler Controller Manager etcd Kubelet Node Create Pod Store Pod Spec Acknowledge Pod Creation Notify of Pending Pod Get Pod Spec Get Node Information Node Information Filter Nodes Score Nodes Bind Pod to Node Update Pod Binding Acknowledge Binding Notify of Pod Update Get Pod Spec Update Pod Status Notify of Pod Assignment Get Pod Spec Create and Start Pod Pod Running Update Pod Status Store Pod Status Pod Running User API Server Scheduler Controller Manager etcd Kubelet Node

交互流程解释

  1. 用户创建 Pod

    • 用户向 API Server 提交 Pod 创建请求。
    • API Server 将 Pod 的配置信息存储在 etcd 中,并确认创建成功。
  2. 调度 Pod

    • API Server 通知 Scheduler 有新的待调度 Pod。
    • Scheduler 从 API Server 获取 Pod 的配置信息,并从 etcd 获取集群中节点的信息。
    • Scheduler 过滤和打分节点,选择最合适的节点。
    • Scheduler 将 Pod 绑定到选定的节点,并通知 API Server。
  3. 更新 Pod 绑定信息

    • API Server 将 Pod 的绑定信息更新到 etcd。
    • Scheduler 确认绑定成功。
  4. 控制器管理 Pod

    • API Server 通知 Controller Manager Pod 的更新信息。
    • Controller Manager 从 etcd 获取 Pod 配置信息,并更新 Pod 的状态。
  5. Kubelet 启动 Pod

    • API Server 通知 Kubelet Pod 已分配到其管理的节点上。
    • Kubelet 从 etcd 获取 Pod 的配置信息。
    • Kubelet 在节点上创建并启动 Pod。
    • 节点返回 Pod 的运行状态给 Kubelet。
    • Kubelet 更新 Pod 的状态到 API Server。
  6. 存储 Pod 状态并通知用户

    • API Server 将 Pod 的运行状态存储到 etcd。
    • API Server 通知用户 Pod 处于运行状态。

通过这个交互示意图和解释,可以清晰地了解 Kubernetes Scheduler 与其他组件的交互流程和机制。

三、Kubernetes Scheduler伪代码实现

下面是一个使用 Go 语言编写的 Kubernetes Scheduler 功能的伪代码示例。此示例包括基本的调度流程,包括从 API Server 获取未调度的 Pod,筛选节点,评分节点,并将 Pod 绑定到选定的节点。

Kubernetes Scheduler 伪代码

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    "path/filepath"
    "k8s.io/kubernetes/pkg/scheduler"
    "k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
    "k8s.io/kubernetes/pkg/scheduler/framework/plugins/registry"
    "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
)

func main() {
    // 加载Kubernetes配置
    var kubeconfig string
    if home := homedir.HomeDir(); home != "" {
        kubeconfig = filepath.Join(home, ".kube", "config")
    }

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatalf("Error building kubeconfig: %s", err.Error())
    }

    // 创建Kubernetes客户端
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatalf("Error creating Kubernetes client: %s", err.Error())
    }

    // 注册调度插件
    registry := registry.NewRegistry()
    pluginFactory := noderesources.NewFit
    registry.Register("NodeResourcesFit", pluginFactory)

    // 创建调度框架
    schedulerFramework, err := runtime.NewFramework(registry, nil, nil)
    if err != nil {
        log.Fatalf("Error creating scheduler framework: %s", err.Error())
    }

    // 创建自定义调度器
    sched := scheduler.New(
        clientset,
        schedulerFramework,
        nil,
        context.TODO(),
        "custom-scheduler",
    )

    // 主调度循环
    for {
        pod := getPendingPod(clientset)
        if pod != nil {
            nodes := getNodes(clientset)
            filteredNodes := filterNodes(pod, nodes)
            if len(filteredNodes) > 0 {
                bestNode := scoreNodes(pod, filteredNodes)
                bindPodToNode(clientset, pod, bestNode)
            }
        }
        time.Sleep(1 * time.Second)
    }
}

// 获取未调度的Pod
func getPendingPod(clientset *kubernetes.Clientset) *v1.Pod {
    pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
    if err != nil {
        log.Fatalf("Error listing pods: %s", err.Error())
    }
    for _, pod := range pods.Items {
        if pod.Spec.NodeName == "" {
            return &pod
        }
    }
    return nil
}

// 获取所有节点
func getNodes(clientset *kubernetes.Clientset) []v1.Node {
    nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
    if err != nil {
        log.Fatalf("Error listing nodes: %s", err.Error())
    }
    return nodes.Items
}

// 节点过滤
func filterNodes(pod *v1.Pod, nodes []v1.Node) []v1.Node {
    var filteredNodes []v1.Node
    for _, node := range nodes {
        if nodeHasSufficientResources(pod, &node) {
            filteredNodes = append(filteredNodes, node)
        }
    }
    return filteredNodes
}

// 检查节点是否有足够资源
func nodeHasSufficientResources(pod *v1.Pod, node *v1.Node) bool {
    // 实现资源检查逻辑,如CPU和内存是否足够
    return true
}

// 节点评分
func scoreNodes(pod *v1.Pod, nodes []v1.Node) *v1.Node {
    var bestNode *v1.Node
    var highestScore int
    for _, node := range nodes {
        score := calculateNodeScore(pod, &node)
        if score > highestScore {
            highestScore = score
            bestNode = &node
        }
    }
    return bestNode
}

// 计算节点分数
func calculateNodeScore(pod *v1.Pod, node *v1.Node) int {
    // 实现评分逻辑,如节点的资源利用率、亲和性等
    return 0
}

// 绑定Pod到节点
func bindPodToNode(clientset *kubernetes.Clientset, pod *v1.Pod, node *v1.Node) {
    binding := &v1.Binding{
        ObjectMeta: metav1.ObjectMeta{Name: pod.Name, Namespace: pod.Namespace},
        Target: v1.ObjectReference{
            Kind: "Node",
            Name: node.Name,
        },
    }
    err := clientset.CoreV1().Pods(pod.Namespace).Bind(context.TODO(), binding, metav1.CreateOptions{})
    if err != nil {
        log.Fatalf("Error binding pod: %s", err.Error())
    } else {
        fmt.Printf("Successfully bound pod %s to node %s\n", pod.Name, node.Name)
    }
}

伪代码解释

  1. 主函数

    • 加载 Kubernetes 配置并创建 Kubernetes 客户端。
    • 注册调度插件并创建调度框架。
    • 创建自定义调度器,并进入主调度循环。
  2. 主调度循环

    • 获取未调度的 Pod。
    • 获取所有节点。
    • 过滤节点,找出符合条件的节点。
    • 对符合条件的节点进行评分,选择得分最高的节点。
    • 将 Pod 绑定到选定的节点。
  3. 辅助函数

    • getPendingPod:获取未调度的 Pod。
    • getNodes:获取所有节点。
    • filterNodes:根据资源要求过滤节点。
    • nodeHasSufficientResources:检查节点是否有足够资源。
    • scoreNodes:对符合条件的节点进行评分。
    • calculateNodeScore:计算节点的分数。
    • bindPodToNode:将 Pod 绑定到选定的节点。

这个伪代码示例展示了一个基本的自定义调度器的工作流程和关键函数。实际实现中,你可以根据具体需求扩展和修改这些函数。

下面是表示上述自定义 Kubernetes Scheduler 伪代码的调用图。这张图展示了调度器的主要流程,包括获取未调度的 Pod、获取节点、过滤节点、评分节点以及将 Pod 绑定到选定节点的过程。

Nodes
etcd
Kubernetes API
No
Yes
No
Yes
Communicates
Fetch Pods
Fetch Nodes
Bind Pod
Stores
Node1
Node2
Node3
Filter Nodes
Score Nodes
Pod & Node Information
API Server
Start Scheduler
Get Pending Pod
Get Nodes
Bind Pod to Node
Pod Found?
Filtered Nodes Found?
Select Best Node
Log Success

图解说明

  1. Start Scheduler

    • 调度器启动并进入主循环。
  2. Get Pending Pod

    • 从 API Server 获取未调度的 Pod。
  3. Pod Found?

    • 判断是否找到未调度的 Pod,如果没有找到则返回主循环继续检查。
  4. Get Nodes

    • 从 API Server 获取所有节点的信息。
  5. Filter Nodes

    • 根据资源要求和调度规则过滤节点。
  6. Filtered Nodes Found?

    • 判断是否有符合条件的节点,如果没有找到则返回主循环。
  7. Score Nodes

    • 对符合条件的节点进行评分。
  8. Select Best Node

    • 选择得分最高的节点。
  9. Bind Pod to Node

    • 将 Pod 绑定到选定的节点,并更新 API Server。
  10. Log Success

    • 记录绑定成功的日志。
  11. Communicates with Kubernetes API

    • 调度器通过 API Server 与 Kubernetes 交互,获取 Pod 和节点信息,更新绑定状态。
  12. etcd

    • API Server 将 Pod 和节点信息存储到 etcd 中。
  13. Nodes

    • 显示集群中的节点,调度器对这些节点进行过滤和评分。

该图直观地展示了自定义 Kubernetes Scheduler 的主要工作流程和与其他组件的交互。

四、自定义 Kubernetes Scheduler最佳实践

自定义 Kubernetes Scheduler 是一个高级主题,需要仔细考虑和实现,确保它能够有效地管理和调度 Pod 到集群中的节点。以下是一些关于自定义 Kubernetes Scheduler 的最佳实践:

1. 确定需求和场景

在开始之前,确保明确你的需求和场景。了解你想要实现的特定调度逻辑和策略,例如特定的资源分配、亲和性/反亲和性需求、定制化的节点选择算法等。理解这些需求将有助于指导你设计和实现自定义 Scheduler。

2. 使用 Kubernetes 提供的调度框架和插件

Kubernetes 提供了灵活的调度框架和各种插件,例如节点资源调度、亲和性/反亲和性、污点和容忍等。在自定义 Scheduler 时,可以基于现有的调度框架进行扩展和定制化,使用已有的调度插件或编写新的插件以满足特定需求。

3. 编写调度器代码

编写自定义 Scheduler 的代码时,考虑以下几点:

  • 初始化 Kubernetes 客户端:确保能够与 Kubernetes API Server 进行通信。
  • 注册调度插件:根据需要注册适合的调度插件,如节点资源调度插件、亲和性/反亲和性插件等。
  • 实现调度逻辑:在主循环中实现从 API Server 获取未调度的 Pod、获取节点列表、过滤和评分节点、绑定 Pod 到节点等核心调度逻辑。
  • 错误处理和日志记录:添加适当的错误处理机制,并记录调度过程中的关键事件和决策。

4. 测试和验证

在部署自定义 Scheduler 之前,进行充分的测试和验证是必不可少的步骤。确保你的 Scheduler 能够正确地处理各种场景和边界条件,例如不同类型的 Pod、不同的节点状态、并发调度等。

5. 部署和监控

部署自定义 Scheduler 到 Kubernetes 集群后,确保能够有效地监控其性能和行为。使用 Kubernetes 提供的监控工具(如 Prometheus)或自定义指标来收集调度器的运行数据,并及时调整和优化调度策略。

6. 考虑安全性和可扩展性

在设计和实现自定义 Scheduler 时,要考虑安全性和可扩展性。确保 Scheduler 的操作是安全的,并且可以在集群的规模和负载增加时保持稳定和高效。

示例实现

以下是一个简单的示例实现,展示了如何使用 Go 和 Kubernetes 客户端库来创建自定义 Scheduler:

  • 初始化 Kubernetes 客户端和调度器框架。
  • 注册节点资源调度插件。
  • 实现调度逻辑,包括节点过滤、评分和绑定 Pod 到节点。
  • 在主循环中运行调度器,并持续监视未调度的 Pod。
// 请参考前面给出的Go语言伪代码实现。

通过遵循这些最佳实践,你可以成功地设计、开发和部署自定义 Kubernetes Scheduler,以满足特定的业务需求和调度策略。

五、自定义Kubernetes Scheduler示例

自定义 Kubernetes Scheduler 允许你定义调度逻辑以满足特定需求。下面是如何创建、配置和部署自定义 Scheduler 的详细步骤。

步骤 1:编写自定义调度器

你可以使用 Go 语言编写自定义调度器。以下是一个基本的自定义调度器示例:

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    "path/filepath"
    "k8s.io/kubernetes/pkg/scheduler"
    "k8s.io/kubernetes/pkg/scheduler/framework/plugins/noderesources"
    "k8s.io/kubernetes/pkg/scheduler/framework/plugins/registry"
    "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
)

func main() {
    var kubeconfig string
    if home := homedir.HomeDir(); home != "" {
        kubeconfig = filepath.Join(home, ".kube", "config")
    }

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatalf("Error building kubeconfig: %s", err.Error())
    }

    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatalf("Error creating Kubernetes client: %s", err.Error())
    }

    registry := registry.NewRegistry()
    pluginFactory := noderesources.NewFit
    registry.Register("NodeResourcesFit", pluginFactory)

    schedulerFramework, err := runtime.NewFramework(registry, nil, nil)
    if err != nil {
        log.Fatalf("Error creating scheduler framework: %s", err.Error())
    }

    sched := scheduler.New(
        clientset,
        schedulerFramework,
        nil,
        context.TODO(),
        "custom-scheduler",
    )

    for {
        err := sched.Run(context.TODO())
        if err != nil {
            log.Printf("Error running scheduler: %s", err.Error())
        }
        time.Sleep(1 * time.Second)
    }
}

步骤 2:构建 Docker 镜像

为你的自定义调度器创建一个 Docker 镜像。首先,创建一个 Dockerfile:

FROM golang:1.17 as builder

WORKDIR /go/src/custom-scheduler
COPY . .

RUN go get -d -v ./...
RUN go build -o custom-scheduler .

FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /root/
COPY --from=builder /go/src/custom-scheduler/custom-scheduler .

CMD ["./custom-scheduler"]

然后构建镜像:

docker build -t custom-scheduler:latest .

步骤 3:创建 Kubernetes Deployment

创建一个 Deployment 来运行自定义调度器:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: custom-scheduler
  labels:
    app: custom-scheduler
spec:
  replicas: 1
  selector:
    matchLabels:
      app: custom-scheduler
  template:
    metadata:
      labels:
        app: custom-scheduler
    spec:
      containers:
      - name: custom-scheduler
        image: custom-scheduler:latest
        imagePullPolicy: IfNotPresent
        command: ["./custom-scheduler"]
      serviceAccountName: system:scheduler

步骤 4:配置调度器名称

为你的 Pod 指定使用自定义调度器。在 Pod 定义中设置 schedulerName

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  schedulerName: custom-scheduler
  containers:
  - name: example-container
    image: nginx

步骤 5:部署和验证

  1. 部署自定义调度器:

    kubectl apply -f custom-scheduler-deployment.yaml
    
  2. 创建一个使用自定义调度器的 Pod:

    kubectl apply -f example-pod.yaml
    
  3. 检查 Pod 是否使用自定义调度器成功调度:

    kubectl get pod example-pod -o jsonpath='{.spec.schedulerName}'
    

总结

通过以上步骤,你可以编写、构建、部署和使用自定义 Kubernetes Scheduler。这使你能够实现更灵活和特定需求的调度逻辑。

六、Kubernetes Scheduler历史演进

Kubernetes Scheduler 是 Kubernetes 集群管理系统的核心组件之一,它负责将未分配节点的 Pod 分配到合适的节点上。自 Kubernetes 项目启动以来,Kubernetes Scheduler 也经历了显著的演进。以下是 Kubernetes Scheduler 的历史演进:

1. Kubernetes 早期版本(2014-2015)

1.1. 初始设计
  • Kubernetes 于 2014 年开源,最初的调度器设计非常简单,主要基于静态调度策略,如 CPU 和内存资源。
  • 调度算法主要基于 “First Fit” 策略,即选择第一个满足资源要求的节点。
1.2. 调度器插件机制
  • 初始版本中,调度逻辑内嵌在调度器代码中,缺乏灵活性和扩展性。

2. Kubernetes 1.0(2015)

2.1. 初步稳定
  • Kubernetes 1.0 版本标志着 Kubernetes 的首次正式发布。
  • 调度器引入了更复杂的调度策略,如节点亲和性和反亲和性。

3. Kubernetes 1.2-1.5(2016-2017)

3.1. Pod 优先级和抢占
  • 引入 Pod 优先级和抢占机制,以便更好地处理资源紧张的场景。
  • 调度器能够根据优先级调整 Pod 的调度顺序。
3.2. 多调度器支持
  • Kubernetes 支持用户自定义调度器,使得在同一个集群中可以运行多个调度器实例。

4. Kubernetes 1.6-1.9(2017-2018)

4.1. 调度器扩展点
  • 引入调度器扩展点机制,使得用户可以插入自定义的调度策略和插件,增强调度器的可扩展性。
4.2. 事件驱动的调度
  • 调度器逐步从定期扫描变为事件驱动,更高效地响应 Pod 和节点状态的变化。

5. Kubernetes 1.10-1.13(2018-2019)

5.1. 调度框架(Scheduling Framework)
  • Kubernetes 1.11 引入了调度框架(Scheduling Framework),允许用户通过插件扩展调度器的行为。
  • 这一框架提供了多个扩展点,如预过滤、过滤、优选、绑定等。
5.2. 调度器性能优化
  • 持续的性能优化,提升调度器在大规模集群中的表现。

6. Kubernetes 1.14-1.19(2019-2020)

6.1. 调度框架逐步稳定
  • 调度框架功能逐步完善,用户可以更加灵活地自定义调度逻辑。
  • 增加了更多内置插件,提升了调度器的默认能力。
6.2. 调度器配置文件(Scheduler Configuration)
  • 引入调度器配置文件,允许用户通过配置文件定制调度器行为,而无需修改代码。

7. Kubernetes 1.20-1.23(2020-2021)

7.1. 调度框架的广泛采用
  • 调度框架被广泛采用,并逐渐成为定制调度逻辑的标准方式。
  • 更多的社区插件和企业插件被开发出来,满足不同场景的需求。
7.2. 性能和稳定性提升
  • 持续的性能和稳定性改进,使调度器能够在更大规模和更复杂的环境中运行。

8. Kubernetes 1.24+(2022-至今)

8.1. 提升调度器的智能化
  • 引入更多智能化的调度策略和算法,如机器学习驱动的调度。
  • 增加对异构资源(如 GPU、FPGA)的更好支持。
8.2. 多集群调度
  • 支持多集群环境中的调度需求,使得调度器能够跨多个 Kubernetes 集群进行资源调度。
8.3. 提升调度器的可观测性
  • 增加更多调度器的可观测性特性,使得管理员能够更好地了解调度决策和调度过程。

总结

Kubernetes Scheduler 的演进反映了 Kubernetes 社区对调度需求的不断理解和优化。随着 Kubernetes 的发展,调度器变得更加智能、灵活和高效,以应对现代应用程序的复杂需求和大规模集群的挑战。未来,调度器将继续演进,以支持更多新兴的计算资源和调度策略。

完。
希望对您有用!关注锅总,及时获得更多花里胡哨的运维实用操作!

一个秘密

在这里插入图片描述
锅总个人博客

https://gentlewok.blog.csdn.net/

锅总微信公众号
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/751358.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据处理python

1.列筛选 (1)某一列&某几列 对于一个表单里面的数据,如果我们想要对于这个表单里面的数据进行处理,我们可以一列一列进行处理,也可以多列一起进行处理; 一列一列处理: 只需要在这个dataf…

台式机通过网线直连笔记本,台式机通过笔记本上网【解决台式机没有网络的问题】

一、总览 将笔记本电脑和台式机使用网线连接起来。在笔记本电脑上打开网络和共享中心,进入“更改适配器设置”选项,找到当前连接的网卡,右键点击选择“属性”。在网卡属性中,找到“共享”选项卡,勾选“允许其他网络用…

帮助你简易起步一个BLOG(博客搭建)项目

Blog项目 后端项目结构1. 项目初始化2. 详细步骤3.postman测试 前端1. 项目初始化2. 详细步骤 本章节是为了帮助你起步一个完整的前后端分离项目。 前端技术栈: react、vite、mantine、tailwind CSS、zustand、rxjs、threejs 后端技术栈:nodemon、nodej…

平面点云格网过程及可视化介绍(python)

1、背景介绍 实际人工构造物中,很多物体表面为平面结构,因此将点云投影在二维平面上进行处理,如进行点云面积计算、点云边缘提取等。 具体案例可以参考博客:详解基于格网法统计平面点云面积_点云格网法计算xy投影面积-CSDN博客、点…

AI 开发平台(Coze)搭建《AI女友(多功能版本)》

前言 本文讲解如何从零开始,使用扣子平台去搭建《AI女友(多功能版本)》 bot直达:AI女友(多功能版) - 扣子 AI Bot (coze.cn) 欢迎大家前去体验!!! 正文 功能介绍 …

C#串口通信Seriaport和页面传值

串口通信 串口COM:是一种用于连接计算机和外设设备的接口,也叫串行接口,简称com,常见的串口有一半电脑应用的RS-232(使用25针或9针的 连接器)通俗来讲串口就是usb接口、鼠标串口。键盘串口 串口通讯:是指外…

Spring Clude 是什么?

目录 认识微服务 单体架构 集群和分布式架构 集群和分布式 集群和分布式区别和联系 微服务架构 分布式架构&微服务架构 微服务的优势和带来的挑战 微服务解决方案- Spring Cloud 什么是 Spring Cloud Spring Cloud 版本 Spring Cloud 和 SpringBoot 的关系 Sp…

VScode远程连接时卡住

将报错文件删除 ### 查找文件(base) ~ find /home -name 5c3e652f63e798a5ac2f31ffd0d863669328dc4c /home/cszx/.vscode-server/data/clp/99e4e0e4dad86d47de9777231596fd92.zh-cn/5c3e652f63e798a5ac2f31ffd0d863669328dc4c ### 删除(base) ~ rm -rf /home/cszx/.vscode-ser…

centOS7网络配置_NAT模式设置

第一步:查看电脑网卡 nat模式对应本地网卡的VMnet 8 ,查看对应的IP地址。 第二步:虚拟网络编辑器 打开VMWare,编辑--虚拟网络编辑器,整个都默认设置好了,只需要查看对应的DHCP设置中对应的IP的起始&#…

MySQL数据类型、运算符以及常用函数

MySQL数据类型 MySQL数据类型定义了数据的大小范围,因此使用时选择合适的类型,不仅会降低表占用的磁盘空间, 间接减少了磁盘I/O的次数,提高了表的访问效率,而且索引的效率也和数据的类型息息相关。 数值类型 浮点类型…

01.Ambari自定义服务开发-项目初始化

文章目录 基础环境在PyCharm中初始化项目配置项目相关依赖在PyCharm中导入依赖 基础环境 PyCharmPython 2.7已经安装完成的Ambari服务端 在PyCharm中初始化项目 项目名称就是我们要安装服务的名称,要求名称为全大写,如:DORIS创建Python2.7…

AUTOSAR以太网之IPv4

系列文章目录 返回总目录 文章目录 系列文章目录一、IPv4报文格式二、主要函数1.IPv4_Init()2.IPv4_Receive()3.IPv4_Transmit() 一、IPv4报文格式 二、主要函数 1.IPv4_Init() 这个函数除了对模块配置进行初始化,如果有分包和组包使能,则会对一些相关…

【高级篇】分区与分片:MySQL的高级数据管理技术(十三)

引言 在上一章,我们探讨了MySQL的主从复制与高可用性,这是构建健壮数据库架构的基石。现在,让我们深入到更高级的主题——分区与分片,这些技术对于处理大规模数据集和提升数据库性能至关重要。我们将详细介绍表分区的概念、类型及分片技术的应用,为下一章讨论MySQL集群与…

2.5 MAC扫描器

MAC扫描器是一款专门用来获取网卡物理地址的网络管理软件,相对于Windows系统的getmac命令,MAC扫描器功能更加强大,它不仅可以获取局域网计算机的MAC地址,还可以获取 Internet 中网卡的MAC地址。MAC扫描器通常被用来管理本地网络中…

22 Shell编程之免交互

目录 22.1 Here Document免交互 22.1.1 Here Document概述 22.1.2 Here Document免交互 22.1.3 Here Document变量设定 22.1.4 Here Document格式控制 22.1.5 Here Document多行注释 22.2 expect免交互 22.2.1 expect概述 22.2.2 expect安装 22.2.3 基本命令介绍 22.2.4expec…

Python操作MySQL数据库--使用pymysql模块

Python操作MySQL数据库--使用pymysql模块 一、新建数据库和数据表1.1 新建book数据库1.2 新建bookprice数据表二、连接数据库2.1 建立数据库连接三、新增数据3.1 新增单条数据3.2 新增多条数据3.3 批量新增四、修改数据4.1 修改单条数据4.2 修改多条数据五、删除数据5.1 删除单…

Java基础(四)——字符串、StringBuffer、StringBuilder、StringJoiner

个人简介 👀个人主页: 前端杂货铺 ⚡开源项目: rich-vue3 (基于 Vue3 TS Pinia Element Plus Spring全家桶 MySQL) 🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展 &#x1…

配置 Cmder 到鼠标右键

win Q 快捷键搜索 cmd,以管理员身份运行 在命令行输入 cmder.exe /REGISTER ALL

浏览器插件利器-allWebPluginV2.0.0.14-beta版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品,致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器,实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

推荐系统三十六式学习笔记:原理篇.模型融合14|一网打尽协同过滤、矩阵分解和线性模型

目录 从特征组合说起FM模型1.原理2.模型训练3.预测阶段4.一网打尽其他模型5.FFM 总结 在上一篇文章中,我们讲到了使用逻辑回归和梯度提升决策树组合的模型融合办法,用于CTR预估,给这个组合起了个名字,叫“辑度组合”。这对组合中&…