活动公告

系统通知
05-18 21:22
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

全面揭秘Kubernetes调度器工作原理与优化技巧从资源感知到智能调度掌握容器编排核心提升集群效率构建稳定云原生环境

SunJu_FaceMall

3万

主题

2860

科技点

3万

积分

白金月票

碾压王

积分
32872

塔罗立华奏

<font color=白金月票" /> 发表于 2025-9-25 13:50:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1. Kubernetes调度器概述

Kubernetes作为当今最流行的容器编排平台,其调度器(Scheduler)是整个系统的核心组件之一。调度器负责将新创建的Pod分配到集群中的合适节点上运行,这一过程看似简单,实则涉及复杂的决策逻辑和资源管理策略。在云原生环境中,调度器的效率和智能程度直接影响整个集群的资源利用率、应用性能和系统稳定性。

Kubernetes调度器的主要职责是监视新创建尚未分配节点的Pod,并根据一系列规则和策略为它们选择最合适的运行节点。这一过程需要考虑多方面因素,包括资源需求、硬件/软件/策略约束、亲和性和反亲和性规范、数据位置、工作负载间的干扰以及截止时间等。

调度器在Kubernetes架构中扮演着至关重要的角色。它作为控制平面的核心组件,与API Server、etcd、Controller Manager和kubelet等其他组件紧密协作,共同维持集群的正常运行。一个高效、智能的调度器能够显著提升集群资源利用率,降低运营成本,并确保应用性能和可靠性。

2. 调度器工作原理详解

Kubernetes调度器的工作流程可以概括为两个主要阶段:过滤(Filtering)和打分(Scoring)。让我们深入了解这两个阶段的具体实现。

2.1 调度流程概述

调度器的工作流程如下:

1. 监视Pod:调度器持续监视Kubernetes API Server,查找尚未分配节点的Pod(即spec.nodeName为空的Pod)。
2. 过滤阶段:对于每个待调度的Pod,调度器会遍历集群中的所有节点,通过一系列谓词(Predicates)规则筛选出满足Pod基本运行需求的节点。
3. 打分阶段:对过滤阶段筛选出的节点,调度器会应用一系列优先级(Priorities)规则进行打分,选出最适合运行该Pod的节点。
4. 绑定阶段:调度器将Pod与选定的节点进行绑定,更新Pod的spec.nodeName字段,然后kubelet会负责在目标节点上创建并运行Pod。

2.2 过滤阶段详解

过滤阶段是调度决策的第一步,其目的是快速排除那些明显不适合运行Pod的节点。Kubernetes提供了一系列内置的谓词规则,包括:

• PodFitsResources:检查节点是否有足够的CPU、内存等资源满足Pod的需求。
• PodFitsHostPorts:检查Pod请求的端口是否已被节点上的其他Pod占用。
• PodMatchNodeSelector:检查节点的标签是否匹配Pod的nodeSelector。
• NoVolumeZoneConflict:检查Pod请求的卷是否在节点所在的可用区。
• CheckNodeMemoryPressure:检查节点是否处于内存压力状态。
• CheckNodeDiskPressure:检查节点是否处于磁盘压力状态。
• MatchInterPodAffinity:检查Pod是否满足与其他Pod的亲和性/反亲和性规则。

让我们通过一个示例来了解过滤阶段的具体实现:
  1. // 伪代码示例:过滤阶段实现
  2. func (g *GenericScheduler) Schedule(pod *v1.Pod, nodeLister algorithm.NodeLister) (result ScheduleResult, err error) {
  3.     // 获取所有节点
  4.     nodes, err := nodeLister.List()
  5.     if err != nil {
  6.         return result, err
  7.     }
  8.    
  9.     // 过滤阶段:应用谓词规则
  10.     filteredNodes, failedPredicateMap, err := g.findNodesThatFit(pod, nodes)
  11.     if err != nil {
  12.         return result, err
  13.     }
  14.    
  15.     // 如果没有节点满足条件,返回错误
  16.     if len(filteredNodes) == 0 {
  17.         return result, &FitError{
  18.             Pod:              pod,
  19.             NumAllNodes:      len(nodes),
  20.             FailedPredicates: failedPredicateMap,
  21.         }
  22.     }
  23.    
  24.     // 打分阶段:应用优先级规则
  25.     priorityList, err := g.prioritizeNodes(pod, filteredNodes)
  26.     if err != nil {
  27.         return result, err
  28.     }
  29.    
  30.     // 选择得分最高的节点
  31.     host, err := g.selectHost(priorityList)
  32.     if err != nil {
  33.         return result, err
  34.     }
  35.    
  36.     return ScheduleResult{
  37.         SuggestedHost:  host,
  38.         EvaluatedNodes: len(filteredNodes),
  39.         FeasibleNodes:  len(filteredNodes),
  40.     }, nil
  41. }
复制代码

2.3 打分阶段详解

打分阶段是调度决策的第二步,其目的是从满足基本条件的节点中选出最优节点。每个优先级规则会为节点打分,最终得分是所有规则得分的加权和。Kubernetes提供了一系列内置的优先级规则,包括:

• LeastRequestedPriority:优先选择资源请求量较少的节点,以平衡资源使用。
• BalancedResourceAllocation:优先选择CPU和内存资源使用更均衡的节点。
• NodeAffinityPriority:优先选择与Pod的节点亲和性规则匹配度更高的节点。
• TaintTolerationPriority:优先选择与Pod的容忍规则匹配度更高的节点。
• InterPodAffinityPriority:优先选择与其他Pod的亲和性规则匹配度更高的节点。
• NodePreferAvoidPodsPriority:优先选择那些没有标记要避免Pod的节点。
• ImageLocalityPriority:优先选择已经存在Pod所需容器镜像的节点。

以下是一个打分阶段的示例实现:
  1. // 伪代码示例:打分阶段实现
  2. func (g *GenericScheduler) prioritizeNodes(pod *v1.Pod, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) {
  3.     // 初始化节点得分列表
  4.     result := make(schedulerapi.HostPriorityList, 0, len(nodes))
  5.    
  6.     // 并行计算每个节点在每个优先级规则下的得分
  7.     for _, node := range nodes {
  8.         // 计算节点在所有优先级规则下的总得分
  9.         score := 0
  10.         for _, priorityConfig := range g.prioritizers {
  11.             // 调用优先级函数计算得分
  12.             nodeScore, err := priorityConfig.Function(pod, node)
  13.             if err != nil {
  14.                 return nil, err
  15.             }
  16.             // 加权求和
  17.             score += nodeScore * priorityConfig.Weight
  18.         }
  19.         
  20.         result = append(result, schedulerapi.HostPriority{
  21.             Host:  node.Name,
  22.             Score: score,
  23.         })
  24.     }
  25.    
  26.     return result, nil
  27. }
复制代码

2.4 绑定阶段详解

绑定阶段是调度决策的最后一步,调度器将Pod与选定的节点进行绑定。这个过程包括:

1. 更新Pod的spec.nodeName字段为选定的节点名称。
2. 将更新后的Pod对象写入etcd。
3. 目标节点上的kubelet监视到分配给自己的Pod后,负责创建并运行该Pod。

绑定阶段的示例代码如下:
  1. // 伪代码示例:绑定阶段实现
  2. func (b *Binder) Bind(binding *v1.Binding) error {
  3.     // 创建绑定请求
  4.     err := b.Client.CoreV1().Pods(binding.Namespace).Bind(binding)
  5.     if err != nil {
  6.         return err
  7.     }
  8.     return nil
  9. }
  10. // 调度器调用绑定
  11. func (sched *Scheduler) bind(binding *v1.Binding) error {
  12.     // 尝试绑定
  13.     err := sched.Binder.Bind(binding)
  14.     if err != nil {
  15.         // 绑定失败,记录错误并重试
  16.         return err
  17.     }
  18.    
  19.     // 绑定成功,记录事件
  20.     sched.Recorder.Eventf(&v1.Pod{
  21.         ObjectMeta: metav1.ObjectMeta{
  22.             Name:      binding.Name,
  23.             Namespace: binding.Namespace,
  24.         },
  25.     }, v1.EventTypeNormal, "Scheduled", "Successfully assigned %v/%v to %v", binding.Namespace, binding.Name, binding.Target.Name)
  26.    
  27.     return nil
  28. }
复制代码

3. 资源感知机制

Kubernetes调度器的资源感知机制是其核心功能之一,它使调度器能够根据节点的资源状况做出智能决策。本节将深入探讨调度器如何感知、评估和利用集群资源。

3.1 资源模型

Kubernetes使用两种主要的资源度量方式:请求(Request)和限制(Limit)。

• 请求(Request):Pod需要的最小资源量,用于调度决策和节点资源分配。
• 限制(Limit):Pod可以使用的最大资源量,用于运行时资源限制。

调度器主要关注资源请求量,因为它决定了Pod能否在节点上运行。节点的可分配资源(Allocatable)是其总资源容量减去系统预留资源后的值,调度器会确保节点上所有Pod的资源请求总和不超过节点的可分配资源。

以下是一个资源模型的示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: resource-pod
  5. spec:
  6.   containers:
  7.   - name: resource-container
  8.     image: nginx
  9.     resources:
  10.       requests:
  11.         cpu: "500m"      # 0.5 CPU核心
  12.         memory: "512Mi"  # 512 MiB内存
  13.       limits:
  14.         cpu: "1000m"     # 1 CPU核心
  15.         memory: "1Gi"    # 1 GiB内存
复制代码

3.2 资源监控与报告

Kubernetes通过kubelet组件收集节点资源使用情况,并定期向API Server报告。调度器利用这些信息了解节点的资源状况,做出合理的调度决策。

kubelet通过cAdvisor(Container Advisor)收集容器资源使用数据,包括CPU、内存、磁盘和网络等。这些数据通过节点状态(NodeStatus)更新到API Server,调度器可以访问这些信息进行调度决策。

以下是节点资源状态的示例:
  1. apiVersion: v1
  2. kind: Node
  3. metadata:
  4.   name: node-1
  5. status:
  6.   capacity:
  7.     cpu: "4"
  8.     memory: 16Gi
  9.     pods: "110"
  10.   allocatable:
  11.     cpu: "3900m"
  12.     memory: 15Gi
  13.     pods: "110"
  14.   conditions:
  15.   - type: MemoryPressure
  16.     status: "False"
  17.   - type: DiskPressure
  18.     status: "False"
  19.   - type: PIDPressure
  20.     status: "False"
  21.   - type: Ready
  22.     status: "True"
复制代码

3.3 资源感知调度策略

Kubernetes调度器提供了多种资源感知的调度策略,帮助优化集群资源利用率。

正确设置Pod的资源请求和限制是资源感知调度的基础。请求值用于调度决策,确保节点有足够资源运行Pod;限制值用于运行时资源控制,防止Pod消耗过多资源影响其他应用。

以下是一个资源请求与限制的最佳实践示例:
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: resource-aware-deployment
  5. spec:
  6.   replicas: 3
  7.   selector:
  8.     matchLabels:
  9.       app: resource-aware
  10.   template:
  11.     metadata:
  12.       labels:
  13.         app: resource-aware
  14.     spec:
  15.       containers:
  16.       - name: app
  17.         image: myapp:1.0
  18.         resources:
  19.           requests:
  20.             cpu: "500m"
  21.             memory: "512Mi"
  22.           limits:
  23.             cpu: "1000m"
  24.             memory: "1Gi"
  25.       - name: sidecar
  26.         image: sidecar:1.0
  27.         resources:
  28.           requests:
  29.             cpu: "200m"
  30.             memory: "256Mi"
  31.           limits:
  32.             cpu: "500m"
  33.             memory: "512Mi"
复制代码

Kubernetes提供了资源配额(ResourceQuota)和限制范围(LimitRange)两种机制,帮助管理员控制命名空间的资源使用。

• 资源配额:限制命名空间中可以创建的对象数量以及计算资源总量。
• 限制范围:为命名空间中的Pod或容器设置默认资源请求和限制,以及最小/最大资源限制。

以下是一个资源配额和限制范围的示例:
  1. # 资源配额示例
  2. apiVersion: v1
  3. kind: ResourceQuota
  4. metadata:
  5.   name: compute-resources
  6.   namespace: dev-namespace
  7. spec:
  8.   hard:
  9.     requests.cpu: "4"
  10.     requests.memory: 8Gi
  11.     limits.cpu: "8"
  12.     limits.memory: 16Gi
  13.     pods: "10"
  14. # 限制范围示例
  15. apiVersion: v1
  16. kind: LimitRange
  17. metadata:
  18.   name: resource-limits
  19.   namespace: dev-namespace
  20. spec:
  21.   limits:
  22.   - default:
  23.       cpu: "500m"
  24.       memory: "512Mi"
  25.     defaultRequest:
  26.       cpu: "250m"
  27.       memory: "256Mi"
  28.     max:
  29.       cpu: "2000m"
  30.       memory: "2Gi"
  31.     min:
  32.       cpu: "100m"
  33.       memory: "128Mi"
  34.     type: Container
复制代码

Kubernetes允许配置资源过量使用(Overcommitment),即节点上所有Pod的资源请求总和可以超过节点的可分配资源。这种策略可以提高资源利用率,但也增加了资源耗尽的风险。

资源过量使用通过kubelet的--kube-reserved和--system-reserved参数配置,它们分别指定为Kubernetes系统和系统进程预留的资源。

以下是一个kubelet资源配置示例:
  1. kubelet --kube-reserved=cpu=500m,memory=1Gi --system-reserved=cpu=200m,memory=500Mi
复制代码

3.4 扩展资源与设备插件

除了CPU和内存等标准资源,Kubernetes还支持扩展资源(Extended Resources),如GPU、FPGA、高性能网卡等。这些资源通过设备插件(Device Plugin)机制集成到Kubernetes中。

设备插件负责:

1. 发现节点上的特定硬件设备。
2. 将这些设备作为扩展资源广告给Kubelet。
3. 监控设备健康状况。
4. 在Pod需要时分配设备。

以下是一个使用GPU资源的Pod示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: gpu-pod
  5. spec:
  6.   containers:
  7.   - name: cuda-container
  8.     image: nvidia/cuda:10.0-base
  9.     resources:
  10.       limits:
  11.         nvidia.com/gpu: 2  # 请求2个GPU
复制代码

4. 智能调度策略

Kubernetes提供了多种智能调度策略,使调度器能够根据业务需求和应用特性做出更精细的调度决策。这些策略包括节点亲和性、Pod亲和性/反亲和性、污点和容忍等。

4.1 节点亲和性调度

节点亲和性(Node Affinity)允许Pod根据节点标签选择性地调度到特定节点上。它分为两种类型:requiredDuringSchedulingIgnoredDuringExecution(硬性要求)和preferredDuringSchedulingIgnoredDuringExecution(软性偏好)。

硬性节点亲和性规则必须满足,否则Pod不会被调度到节点上。它使用nodeSelector的扩展形式,提供更丰富的匹配语法。

以下是一个硬性节点亲和性的示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: affinity-pod
  5. spec:
  6.   affinity:
  7.     nodeAffinity:
  8.       requiredDuringSchedulingIgnoredDuringExecution:
  9.         nodeSelectorTerms:
  10.         - matchExpressions:
  11.           - key: kubernetes.io/e2e-az-name
  12.             operator: In
  13.             values:
  14.             - e2e-az1
  15.             - e2e-az2
  16.   containers:
  17.   - name: nginx
  18.     image: nginx
复制代码

软性节点亲和性规则是偏好而非强制要求,调度器会尝试满足这些规则,但在无法满足时仍会调度Pod。

以下是一个软性节点亲和性的示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: affinity-pod
  5. spec:
  6.   affinity:
  7.     nodeAffinity:
  8.       preferredDuringSchedulingIgnoredDuringExecution:
  9.       - weight: 1  # 权重,范围1-100
  10.         preference:
  11.           matchExpressions:
  12.           - key: another-node-label-key
  13.             operator: In
  14.             values:
  15.             - another-node-label-value
  16.   containers:
  17.   - name: nginx
  18.     image: nginx
复制代码

4.2 Pod亲和性与反亲和性调度

Pod亲和性(Pod Affinity)和反亲和性(Pod Anti-Affinity)允许Pod根据其他Pod的标签选择性地调度到特定节点上。这种策略对于需要部署在一起或分开的应用非常有用。

Pod亲和性确保Pod被调度到与具有特定标签的Pod相同的节点上。它同样分为硬性要求和软性偏好两种类型。

以下是一个Pod亲和性的示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: pod-affinity-pod
  5. spec:
  6.   affinity:
  7.     podAffinity:
  8.       requiredDuringSchedulingIgnoredDuringExecution:
  9.       - labelSelector:
  10.           matchExpressions:
  11.           - key: security
  12.             operator: In
  13.             values:
  14.             - S1
  15.         topologyKey: topology.kubernetes.io/zone
  16.   containers:
  17.   - name: nginx
  18.     image: nginx
复制代码

Pod反亲和性确保Pod不被调度到与具有特定标签的Pod相同的节点上。这对于避免单点故障和提高应用可用性非常重要。

以下是一个Pod反亲和性的示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: pod-antiaffinity-pod
  5. spec:
  6.   affinity:
  7.     podAntiAffinity:
  8.       requiredDuringSchedulingIgnoredDuringExecution:
  9.       - labelSelector:
  10.           matchExpressions:
  11.           - key: app
  12.             operator: In
  13.             values:
  14.             - web-frontend
  15.         topologyKey: kubernetes.io/hostname
  16.   containers:
  17.   - name: nginx
  18.     image: nginx
复制代码

4.3 污点与容忍调度

污点(Taints)和容忍(Tolerations)是另一种控制Pod调度的机制。污点应用于节点,表示节点不能接受某些Pod;容忍应用于Pod,表示Pod可以容忍具有特定污点的节点。

节点污点由键、值和效果组成。效果可以是NoSchedule、PreferNoSchedule或NoExecute。

以下是为节点添加污点的示例:
  1. kubectl taint nodes node1 key=value:NoSchedule
复制代码

Pod可以通过容忍来接受具有特定污点的节点。容忍必须与污点的键、值和效果匹配。

以下是一个Pod容忍的示例:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: toleration-pod
  5. spec:
  6.   tolerations:
  7.   - key: "key"
  8.     operator: "Equal"
  9.     value: "value"
  10.     effect: "NoSchedule"
  11.   containers:
  12.   - name: nginx
  13.     image: nginx
复制代码

4.4 自定义调度器

除了默认调度器,Kubernetes还允许用户开发自定义调度器,满足特定业务需求。自定义调度器可以与默认调度器并行运行,或者完全替代默认调度器。

自定义调度器通常作为独立的进程运行,通过监视Kubernetes API Server获取待调度Pod和节点信息,然后应用自定义调度逻辑,最后将Pod绑定到选定节点。

以下是一个简单的自定义调度器框架:
  1. package main
  2. import (
  3.     "flag"
  4.     "fmt"
  5.     "time"
  6.     corev1 "k8s.io/api/core/v1"
  7.     "k8s.io/apimachinery/pkg/labels"
  8.     "k8s.io/client-go/informers"
  9.     "k8s.io/client-go/kubernetes"
  10.     "k8s.io/client-go/tools/cache"
  11.     "k8s.io/client-go/tools/clientcmd"
  12.     "k8s.io/klog/v2"
  13. )
  14. type CustomScheduler struct {
  15.     clientset     kubernetes.Interface
  16.     podInformer    cache.SharedIndexInformer
  17.     nodeInformer   cache.SharedIndexInformer
  18.     unscheduledPods chan *corev1.Pod
  19. }
  20. func NewCustomScheduler(clientset kubernetes.Interface) *CustomScheduler {
  21.     factory := informers.NewSharedInformerFactory(clientset, 30*time.Second)
  22.    
  23.     podInformer := factory.Core().V1().Pods().Informer()
  24.     nodeInformer := factory.Core().V1().Nodes().Informer()
  25.    
  26.     scheduler := &CustomScheduler{
  27.         clientset:     clientset,
  28.         podInformer:    podInformer,
  29.         nodeInformer:   nodeInformer,
  30.         unscheduledPods: make(chan *corev1.Pod, 100),
  31.     }
  32.    
  33.     // 设置Pod事件处理器
  34.     podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
  35.         AddFunc: func(obj interface{}) {
  36.             pod := obj.(*corev1.Pod)
  37.             if pod.Spec.NodeName == "" && pod.Status.Phase == corev1.PodPending {
  38.                 scheduler.unscheduledPods <- pod
  39.             }
  40.         },
  41.         UpdateFunc: func(oldObj, newObj interface{}) {
  42.             oldPod := oldObj.(*corev1.Pod)
  43.             newPod := newObj.(*corev1.Pod)
  44.             if oldPod.Spec.NodeName == "" && newPod.Spec.NodeName == "" && newPod.Status.Phase == corev1.PodPending {
  45.                 scheduler.unscheduledPods <- newPod
  46.             }
  47.         },
  48.     })
  49.    
  50.     return scheduler
  51. }
  52. func (s *CustomScheduler) Run(stopCh <-chan struct{}) {
  53.     // 启动informer
  54.     go s.podInformer.Run(stopCh)
  55.     go s.nodeInformer.Run(stopCh)
  56.    
  57.     // 等待缓存同步
  58.     if !cache.WaitForCacheSync(stopCh, s.podInformer.HasSynced, s.nodeInformer.HasSynced) {
  59.         klog.Error("Timed out waiting for caches to sync")
  60.         return
  61.     }
  62.    
  63.     // 开始调度循环
  64.     for {
  65.         select {
  66.         case pod := <-s.unscheduledPods:
  67.             s.Schedule(pod)
  68.         case <-stopCh:
  69.             return
  70.         }
  71.     }
  72. }
  73. func (s *CustomScheduler) Schedule(pod *corev1.Pod) {
  74.     // 获取所有节点
  75.     nodes, err := s.nodeInformer.GetIndexer().ByIndex(cache.NamespaceIndex, "")
  76.     if err != nil {
  77.         klog.Errorf("Failed to get nodes: %v", err)
  78.         return
  79.     }
  80.    
  81.     // 自定义调度逻辑
  82.     selectedNode := s.selectNode(pod, nodes)
  83.     if selectedNode == nil {
  84.         klog.Infof("No available node for pod %s/%s", pod.Namespace, pod.Name)
  85.         return
  86.     }
  87.    
  88.     // 绑定Pod到节点
  89.     binding := &corev1.Binding{
  90.         ObjectMeta: metav1.ObjectMeta{Name: pod.Name, UID: pod.UID},
  91.         Target:     corev1.ObjectReference{Kind: "Node", Name: selectedNode.Name},
  92.     }
  93.    
  94.     err = s.clientset.CoreV1().Pods(pod.Namespace).Bind(binding)
  95.     if err != nil {
  96.         klog.Errorf("Failed to bind pod %s/%s to node %s: %v", pod.Namespace, pod.Name, selectedNode.Name, err)
  97.         return
  98.     }
  99.    
  100.     klog.Infof("Successfully bound pod %s/%s to node %s", pod.Namespace, pod.Name, selectedNode.Name)
  101. }
  102. func (s *CustomScheduler) selectNode(pod *corev1.Pod, nodes []interface{}) *corev1.Node {
  103.     // 这里实现自定义的节点选择逻辑
  104.     // 可以基于资源、标签、亲和性等因素进行选择
  105.    
  106.     for _, nodeObj := range nodes {
  107.         node := nodeObj.(*corev1.Node)
  108.         
  109.         // 检查节点是否可调度
  110.         if !isNodeSchedulable(node) {
  111.             continue
  112.         }
  113.         
  114.         // 检查节点是否有足够资源
  115.         if !nodeHasEnoughResources(node, pod) {
  116.             continue
  117.         }
  118.         
  119.         // 检查节点是否匹配Pod的节点选择器
  120.         if !nodeMatchesSelector(node, pod) {
  121.             continue
  122.         }
  123.         
  124.         // 如果所有检查都通过,选择该节点
  125.         return node
  126.     }
  127.    
  128.     return nil
  129. }
  130. func isNodeSchedulable(node *corev1.Node) bool {
  131.     return !node.Spec.Unschedulable
  132. }
  133. func nodeHasEnoughResources(node *corev1.Node, pod *corev1.Pod) bool {
  134.     // 实现资源检查逻辑
  135.     return true
  136. }
  137. func nodeMatchesSelector(node *corev1.Node, pod *corev1.Pod) bool {
  138.     // 实现节点选择器匹配逻辑
  139.     return true
  140. }
  141. func main() {
  142.     var kubeconfig string
  143.     var masterURL string
  144.    
  145.     flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
  146.     flag.StringVar(&masterURL, "master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
  147.     flag.Parse()
  148.    
  149.     // 创建Kubernetes客户端
  150.     config, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig)
  151.     if err != nil {
  152.         klog.Fatalf("Error building kubeconfig: %v", err)
  153.     }
  154.    
  155.     clientset, err := kubernetes.NewForConfig(config)
  156.     if err != nil {
  157.         klog.Fatalf("Error building kubernetes clientset: %v", err)
  158.     }
  159.    
  160.     // 创建并运行自定义调度器
  161.     scheduler := NewCustomScheduler(clientset)
  162.    
  163.     stopCh := make(chan struct{})
  164.     defer close(stopCh)
  165.    
  166.     go scheduler.Run(stopCh)
  167.    
  168.     // 等待终止信号
  169.     select {}
  170. }
复制代码

要在Pod中使用自定义调度器,需要在Pod规范中指定调度器名称:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: custom-scheduler-pod
  5. spec:
  6.   schedulerName: my-custom-scheduler
  7.   containers:
  8.   - name: nginx
  9.     image: nginx
复制代码

4.5 多调度器协同工作

Kubernetes支持多个调度器同时工作,每个调度器可以负责调度特定的Pod。这种模式允许集群管理员根据不同的业务需求使用不同的调度策略。

要配置多调度器,需要:

1. 部署自定义调度器。
2. 在Pod中指定使用哪个调度器。

以下是一个部署自定义调度器的示例:
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: custom-scheduler
  5. spec:
  6.   replicas: 1
  7.   selector:
  8.     matchLabels:
  9.       app: custom-scheduler
  10.   template:
  11.     metadata:
  12.       labels:
  13.         app: custom-scheduler
  14.     spec:
  15.       serviceAccountName: custom-scheduler
  16.       containers:
  17.       - name: custom-scheduler
  18.         image: my-custom-scheduler:1.0
  19.         imagePullPolicy: Always
  20.         command:
  21.         - /bin/custom-scheduler
  22.         - --kubeconfig=/etc/kubernetes/scheduler.conf
  23.         - --v=3
  24.         volumeMounts:
  25.         - name: kubeconfig
  26.           mountPath: /etc/kubernetes
  27.           readOnly: true
  28.       volumes:
  29.       - name: kubeconfig
  30.         secret:
  31.           secretName: custom-scheduler-kubeconfig
复制代码

为Pod指定调度器只需在Pod规范中设置schedulerName字段:
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: custom-scheduled-pod
  5. spec:
  6.   schedulerName: custom-scheduler
  7.   containers:
  8.   - name: nginx
  9.     image: nginx
复制代码

5. 调度器优化技巧

优化Kubernetes调度器可以显著提高集群资源利用率、应用性能和系统稳定性。本节将介绍一系列实用的调度器优化技巧。

5.1 资源分配优化

合理的资源分配是调度优化的基础。通过优化资源请求和限制,可以提高集群资源利用率,同时确保应用性能。

准确设置Pod的资源请求和限制是优化调度的第一步。资源请求过低可能导致节点资源过载,影响应用性能;资源请求过高则会导致资源浪费。

以下是一些设置资源请求和限制的最佳实践:

1. 基于监控数据设置资源:使用应用的历史监控数据确定合理的资源请求和限制。
2. 使用垂直Pod自动伸缩(VPA):VPA可以根据实际资源使用情况自动调整Pod的资源请求和限制。
3. 为不同环境设置不同资源:开发、测试和生产环境可以使用不同的资源配置。

以下是一个基于VPA的资源配置示例:
  1. apiVersion: autoscaling.k8s.io/v1
  2. kind: VerticalPodAutoscaler
  3. metadata:
  4.   name: my-app-vpa
  5. spec:
  6.   targetRef:
  7.     apiVersion: "apps/v1"
  8.     kind:       Deployment
  9.     name:       my-app
  10.   updatePolicy:
  11.     updateMode: "Auto"
复制代码

资源配额和限制范围可以帮助控制命名空间的资源使用,防止单个应用或团队占用过多资源。

以下是一个资源配额和限制范围的组合示例:
  1. # 资源配额
  2. apiVersion: v1
  3. kind: ResourceQuota
  4. metadata:
  5.   name: compute-resources
  6.   namespace: dev-namespace
  7. spec:
  8.   hard:
  9.     requests.cpu: "10"
  10.     requests.memory: 20Gi
  11.     limits.cpu: "20"
  12.     limits.memory: 40Gi
  13.     pods: "50"
  14.     persistentvolumeclaims: "10"
  15. # 限制范围
  16. apiVersion: v1
  17. kind: LimitRange
  18. metadata:
  19.   name: resource-limits
  20.   namespace: dev-namespace
  21. spec:
  22.   limits:
  23.   - default:
  24.       cpu: "500m"
  25.       memory: "512Mi"
  26.     defaultRequest:
  27.       cpu: "250m"
  28.       memory: "256Mi"
  29.     max:
  30.       cpu: "2000m"
  31.       memory: "2Gi"
  32.     min:
  33.       cpu: "100m"
  34.       memory: "128Mi"
  35.     type: Container
复制代码

资源过量使用可以提高资源利用率,但也增加了资源耗尽的风险。以下是一些优化资源过量使用的技巧:

1. 合理设置kubelet预留资源:为Kubernetes系统和系统进程预留足够资源。
2. 使用Pod优先级和抢占:确保关键Pod在资源不足时能够获得资源。
3. 监控资源使用情况:密切监控节点资源使用情况,避免资源耗尽。

以下是一个kubelet资源配置示例:
  1. kubelet --kube-reserved=cpu=500m,memory=1Gi,ephemeral-storage=1Gi \
  2.         --system-reserved=cpu=200m,memory=500Mi,ephemeral-storage=1Gi \
  3.         --eviction-hard=memory.available<500Mi,nodefs.available<10%
复制代码

5.2 调度性能调优

调度性能直接影响Pod的启动速度和集群的响应能力。通过优化调度器性能,可以提高集群的整体效率。

Kubernetes调度器支持并发调度多个Pod,通过调整并发度可以提高调度性能。

以下是一个调度器配置文件示例,展示了如何调整并发度:
  1. apiVersion: kubescheduler.config.k8s.io/v1beta2
  2. kind: KubeSchedulerConfiguration
  3. parallelism: 16  # 默认为16,可根据集群规模调整
复制代码

过多的谓词和优先级规则会增加调度决策的时间。以下是一些优化技巧:

1. 禁用不必要的规则:根据集群需求禁用不必要的谓词和优先级规则。
2. 自定义规则顺序:将计算成本高但过滤效果好的规则放在前面。
3. 使用自定义调度器:对于特定场景,开发专用的高效调度器。

以下是一个自定义调度器配置示例,展示了如何选择特定的谓词和优先级规则:
  1. apiVersion: kubescheduler.config.k8s.io/v1beta2
  2. kind: KubeSchedulerConfiguration
  3. profiles:
  4. - schedulerName: default-scheduler
  5.   plugins:
  6.     filter:
  7.       enabled:
  8.       - name: NodeUnschedulable
  9.       - name: NodeResourcesFit
  10.       - name: NodePorts
  11.       - name: VolumeBinding
  12.     score:
  13.       enabled:
  14.       - name: NodeResourcesBalancedAllocation
  15.       - name: NodeResourcesLeastAllocated
  16.       - name: ImageLocality
复制代码

Kubernetes调度器使用缓存来存储节点和Pod信息,减少API Server的访问次数。优化缓存配置可以提高调度性能。

以下是一些缓存优化技巧:

1. 增加缓存大小:对于大型集群,增加缓存大小可以提高性能。
2. 调整缓存过期时间:根据集群变化频率调整缓存过期时间。
3. 使用分布式缓存:对于多调度器部署,考虑使用分布式缓存。

以下是一个调度器缓存配置示例:
  1. apiVersion: kubescheduler.config.k8s.io/v1beta2
  2. kind: KubeSchedulerConfiguration
  3. percentageOfNodesToScore: 50  # 默认为50,表示只对50%的节点进行打分
复制代码

5.3 避免调度热点

调度热点是指某些节点被过度分配资源,而其他节点资源利用率较低的情况。避免调度热点可以提高集群资源利用率和应用性能。

Pod反亲和性可以确保应用实例分布在不同的节点上,避免单点过载。

以下是一个使用Pod反亲和性避免热点的示例:
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: web-frontend
  5. spec:
  6.   replicas: 5
  7.   selector:
  8.     matchLabels:
  9.       app: web-frontend
  10.   template:
  11.     metadata:
  12.       labels:
  13.         app: web-frontend
  14.     spec:
  15.       affinity:
  16.         podAntiAffinity:
  17.           requiredDuringSchedulingIgnoredDuringExecution:
  18.           - labelSelector:
  19.               matchExpressions:
  20.               - key: app
  21.                 operator: In
  22.                 values:
  23.                 - web-frontend
  24.             topologyKey: kubernetes.io/hostname
  25.       containers:
  26.       - name: web
  27.         image: nginx
  28.         resources:
  29.           requests:
  30.             cpu: "500m"
  31.             memory: "512Mi"
  32.           limits:
  33.             cpu: "1000m"
  34.             memory: "1Gi"
复制代码

在多可用区部署中,使用区域感知调度可以确保应用实例均匀分布在各个可用区,提高可用性。

以下是一个使用节点亲和性实现区域感知调度的示例:
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: zone-aware-app
  5. spec:
  6.   replicas: 6
  7.   selector:
  8.     matchLabels:
  9.       app: zone-aware
  10.   template:
  11.     metadata:
  12.       labels:
  13.         app: zone-aware
  14.     spec:
  15.       affinity:
  16.         nodeAffinity:
  17.           requiredDuringSchedulingIgnoredDuringExecution:
  18.             nodeSelectorTerms:
  19.             - matchExpressions:
  20.               - key: topology.kubernetes.io/zone
  21.                 operator: In
  22.                 values:
  23.                 - us-east-1a
  24.                 - us-east-1b
  25.                 - us-east-1c
  26.       containers:
  27.       - name: app
  28.         image: myapp:1.0
  29.         resources:
  30.           requests:
  31.             cpu: "500m"
  32.             memory: "512Mi"
  33.           limits:
  34.             cpu: "1000m"
  35.             memory: "1Gi"
复制代码

Kubernetes Descheduler是一个用于重新平衡集群资源的工具,它可以识别并重新调度那些可能导致不均衡的Pod。

以下是一个Descheduler配置示例:
  1. apiVersion: policy/v1
  2. kind: PodDisruptionBudget
  3. metadata:
  4.   name: descheduler-pdb
  5. spec:
  6.   selector:
  7.     matchLabels:
  8.       app: descheduler
  9.   maxUnavailable: 1
  10. ---
  11. apiVersion: apps/v1
  12. kind: Deployment
  13. metadata:
  14.   name: descheduler
  15.   namespace: kube-system
  16. spec:
  17.   replicas: 1
  18.   selector:
  19.     matchLabels:
  20.       app: descheduler
  21.   template:
  22.     metadata:
  23.       labels:
  24.         app: descheduler
  25.     spec:
  26.       serviceAccountName: descheduler-sa
  27.       containers:
  28.       - name: descheduler
  29.         image: k8s.gcr.io/descheduler/descheduler:v0.21.0
  30.         imagePullPolicy: Always
  31.         command:
  32.         - "/bin/descheduler"
  33.         args:
  34.         - "--policy-config-file=/policy-dir/policy.yaml"
  35.         - "--v=3"
  36.         volumeMounts:
  37.         - mountPath: /policy-dir
  38.           name: policy-volume
  39.       volumes:
  40.       - name: policy-volume
  41.         configMap:
  42.           name: descheduler-policy
  43. ---
  44. apiVersion: v1
  45. kind: ConfigMap
  46. metadata:
  47.   name: descheduler-policy
  48.   namespace: kube-system
  49. data:
  50.   policy.yaml: |
  51.     apiVersion: "descheduler/v1alpha1"
  52.     kind: "DeschedulerPolicy"
  53.     strategies:
  54.       "RemoveDuplicates":
  55.         enabled: true
  56.       "RemovePodsViolatingInterPodAntiAffinity":
  57.         enabled: true
  58.       "LowNodeUtilization":
  59.         enabled: true
  60.         params:
  61.           nodeResourceUtilizationThresholds:
  62.             thresholds:
  63.               "cpu" : 20
  64.               "memory": 20
  65.               "pods": 20
  66.             targetThresholds:
  67.               "cpu" : 50
  68.               "memory": 50
  69.               "pods": 50
复制代码

5.4 高级调度优化

除了基本的调度优化技巧,还有一些高级优化策略可以进一步提高调度效率。

Kubernetes调度器支持通过Webhook扩展调度功能,允许在调度决策过程中调用外部服务。

以下是一个调度器扩展的示例:
  1. apiVersion: kubescheduler.config.k8s.io/v1beta2
  2. kind: KubeSchedulerConfiguration
  3. profiles:
  4. - schedulerName: default-scheduler
  5.   plugins:
  6.     filter:
  7.       enabled:
  8.       - name: NodeResourcesFit
  9.       - name: MyCustomFilter
  10.     score:
  11.       enabled:
  12.       - name: NodeResourcesBalancedAllocation
  13.       - name: MyCustomScore
  14.   pluginConfig:
  15.   - name: MyCustomFilter
  16.     args:
  17.       favoriteColor: blue
  18.       favoriteNumber: 7
  19.   - name: MyCustomScore
  20.     args:
  21.       favoriteAnimal: dog
  22.       favoriteFood: pizza
复制代码

Kubernetes调度框架(Scheduling Framework)是一组插件API,允许开发自定义调度插件,扩展调度器功能。

以下是一个自定义调度插件的示例:
  1. package main
  2. import (
  3.     "context"
  4.     "fmt"
  5.     "time"
  6.     "k8s.io/api/core/v1"
  7.     "k8s.io/apimachinery/pkg/runtime"
  8.     "k8s.io/klog/v2"
  9.     "k8s.io/kubernetes/pkg/scheduler/framework"
  10.     "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder"
  11.     "k8s.io/kubernetes/pkg/scheduler/framework/plugins/queuesort"
  12. )
  13. const (
  14.     Name = "custom-plugin"
  15. )
  16. type CustomPlugin struct {
  17.     handle framework.Handle
  18. }
  19. var _ framework.FilterPlugin = &CustomPlugin{}
  20. var _ framework.ScorePlugin = &CustomPlugin{}
  21. func (cp *CustomPlugin) Name() string {
  22.     return Name
  23. }
  24. func (cp *CustomPlugin) Filter(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeInfo *framework.NodeInfo) *framework.Status {
  25.     // 实现过滤逻辑
  26.     node := nodeInfo.Node()
  27.     if node.Labels["custom-label"] != "enabled" {
  28.         return framework.NewStatus(framework.Unschedulable, "Node does not have custom-label=enabled")
  29.     }
  30.     return nil
  31. }
  32. func (cp *CustomPlugin) Score(ctx context.Context, state *framework.CycleState, pod *v1.Pod, nodeName string) (int64, *framework.Status) {
  33.     // 实现打分逻辑
  34.     nodeInfo, err := cp.handle.SnapshotSharedLister().NodeInfos().Get(nodeName)
  35.     if err != nil {
  36.         return 0, framework.AsStatus(err)
  37.     }
  38.    
  39.     node := nodeInfo.Node()
  40.     score := int64(0)
  41.    
  42.     // 根据节点标签计算得分
  43.     if node.Labels["priority"] == "high" {
  44.         score = 100
  45.     } else if node.Labels["priority"] == "medium" {
  46.         score = 50
  47.     } else {
  48.         score = 10
  49.     }
  50.    
  51.     return score, nil
  52. }
  53. func (cp *CustomPlugin) ScoreExtensions() framework.ScoreExtensions {
  54.     return cp
  55. }
  56. func (cp *CustomPlugin) NormalizeScore(ctx context.Context, state *framework.CycleState, pod *v1.Pod, scores framework.NodeScoreList) *framework.Status {
  57.     // 实现得分归一化逻辑
  58.     var highest int64 = 0
  59.     for _, nodeScore := range scores {
  60.         if nodeScore.Score > highest {
  61.             highest = nodeScore.Score
  62.         }
  63.     }
  64.    
  65.     if highest == 0 {
  66.         return nil
  67.     }
  68.    
  69.     for i, nodeScore := range scores {
  70.         scores[i].Score = nodeScore.Score * framework.MaxNodeScore / highest
  71.     }
  72.    
  73.     return nil
  74. }
  75. type CustomArgs struct {
  76.     FavoriteColor  string `json:"favoriteColor,omitempty"`
  77.     FavoriteNumber int    `json:"favoriteNumber,omitempty"`
  78. }
  79. func New(_ runtime.Object, handle framework.Handle) (framework.Plugin, error) {
  80.     return &CustomPlugin{handle: handle}, nil
  81. }
  82. func main() {
  83.     // 这里是插件注册逻辑,通常在scheduler初始化时调用
  84.     // scheme := runtime.NewScheme()
  85.     // utilruntime.Must(scheme.AddUnversionedTypes(corev1.SchemeGroupVersion, &CustomArgs{}))
  86.     // framework.Register(Name, func(_ runtime.Object, handle framework.Handle) (framework.Plugin, error) {
  87.     //     return New(nil, handle)
  88.     // })
  89.    
  90.     // 在实际使用中,插件会被编译成独立的二进制文件,并通过--plugins参数加载
  91.     fmt.Println("Custom plugin compiled successfully")
  92. }
复制代码

对于批量任务,使用批处理调度器如Volcano可以提高资源利用率和任务完成速度。

以下是一个Volcano作业的示例:
  1. apiVersion: batch.volcano.sh/v1alpha1
  2. kind: Job
  3. metadata:
  4.   name: test-job
  5. spec:
  6.   minAvailable: 3
  7.   schedulerName: volcano
  8.   priorityClassName: high-priority
  9.   policies:
  10.     - event: PodEvicted
  11.       action: RestartJob
  12.   plugins:
  13.     ssh: []
  14.     env: []
  15.     svc: []
  16.   maxRetry: 5
  17.   queue: default
  18.   tasks:
  19.     - replicas: 3
  20.       name: "default-nginx"
  21.       template:
  22.         metadata:
  23.           name: web
  24.         spec:
  25.           containers:
  26.             - image: nginx
  27.               imagePullPolicy: IfNotPresent
  28.               name: nginx
  29.               resources:
  30.                 requests:
  31.                   cpu: "1"
  32.                   memory: "1Gi"
  33.           restartPolicy: OnFailure
复制代码

6. 实际案例分析

通过实际案例,我们可以更好地理解Kubernetes调度器的工作原理和优化技巧的应用。本节将介绍几个典型的调度优化案例。

6.1 大规模微服务集群调度优化

某互联网公司拥有一个包含数千个微服务的Kubernetes集群,面临资源利用率低、Pod启动慢、节点负载不均等问题。通过一系列调度优化,他们显著提高了集群效率和稳定性。

通过监控数据分析,团队发现以下问题:

1. 资源请求设置不合理:许多Pod的资源请求远高于实际使用量,导致节点资源利用率低。
2. 调度热点:某些节点负载过高,而其他节点资源闲置。
3. Pod启动慢:由于调度决策复杂,Pod启动时间过长。
4. 关键应用受干扰:关键应用与批处理任务混部,导致性能不稳定。

针对上述问题,团队实施了以下优化措施:

1. 资源请求优化:使用VPA自动调整Pod资源请求和限制。为不同类型的应用设置不同的资源请求策略。
2. 使用VPA自动调整Pod资源请求和限制。
3. 为不同类型的应用设置不同的资源请求策略。

• 使用VPA自动调整Pod资源请求和限制。
• 为不同类型的应用设置不同的资源请求策略。
  1. apiVersion: autoscaling.k8s.io/v1
  2.    kind: VerticalPodAutoscaler
  3.    metadata:
  4.      name: web-app-vpa
  5.    spec:
  6.      targetRef:
  7.        apiVersion: "apps/v1"
  8.        kind:       Deployment
  9.        name:       web-app
  10.      updatePolicy:
  11.        updateMode: "Auto"
  12.      resourcePolicy:
  13.        containerPolicies:
  14.        - containerName: "*"
  15.          minAllowed:
  16.            cpu: "100m"
  17.            memory: "128Mi"
  18.          maxAllowed:
  19.            cpu: "2000m"
  20.            memory: "2Gi"
复制代码

1. 避免调度热点:使用Pod反亲和性确保应用实例分布在不同节点。使用Descheduler定期重新平衡集群资源。
2. 使用Pod反亲和性确保应用实例分布在不同节点。
3. 使用Descheduler定期重新平衡集群资源。

• 使用Pod反亲和性确保应用实例分布在不同节点。
• 使用Descheduler定期重新平衡集群资源。
  1. apiVersion: apps/v1
  2.    kind: Deployment
  3.    metadata:
  4.      name: web-app
  5.    spec:
  6.      replicas: 10
  7.      template:
  8.        spec:
  9.          affinity:
  10.            podAntiAffinity:
  11.              requiredDuringSchedulingIgnoredDuringExecution:
  12.              - labelSelector:
  13.                  matchExpressions:
  14.                  - key: app
  15.                    operator: In
  16.                    values:
  17.                    - web-app
  18.                topologyKey: kubernetes.io/hostname
复制代码

1. 调度性能优化:增加调度器并发度。优化谓词和优先级规则。
2. 增加调度器并发度。
3. 优化谓词和优先级规则。

• 增加调度器并发度。
• 优化谓词和优先级规则。
  1. apiVersion: kubescheduler.config.k8s.io/v1beta2
  2.    kind: KubeSchedulerConfiguration
  3.    parallelism: 32
  4.    percentageOfNodesToScore: 30
  5.    profiles:
  6.    - schedulerName: default-scheduler
  7.      plugins:
  8.        filter:
  9.          enabled:
  10.          - name: NodeUnschedulable
  11.          - name: NodeResourcesFit
  12.          - name: NodePorts
  13.        score:
  14.          enabled:
  15.          - name: NodeResourcesBalancedAllocation
  16.          - name: NodeResourcesLeastAllocated
复制代码

1. 应用隔离:使用命名空间和资源配额隔离不同类型的应用。使用污点和容忍分离关键应用和批处理任务。
2. 使用命名空间和资源配额隔离不同类型的应用。
3. 使用污点和容忍分离关键应用和批处理任务。

• 使用命名空间和资源配额隔离不同类型的应用。
• 使用污点和容忍分离关键应用和批处理任务。
  1. # 为批处理节点添加污点
  2.    apiVersion: v1
  3.    kind: Node
  4.    metadata:
  5.      name: batch-node-1
  6.      labels:
  7.        role: batch
  8.    spec:
  9.      taints:
  10.      - key: batch
  11.        value: "true"
  12.        effect: NoSchedule
  13.    
  14.    # 批处理任务容忍污点
  15.    apiVersion: batch/v1
  16.    kind: Job
  17.    metadata:
  18.      name: batch-job
  19.    spec:
  20.      template:
  21.        spec:
  22.          tolerations:
  23.          - key: batch
  24.            operator: Equal
  25.            value: "true"
  26.            effect: NoSchedule
复制代码

通过上述优化,团队取得了显著效果:

1. 资源利用率提高:CPU利用率从30%提升到65%,内存利用率从40%提升到70%。
2. Pod启动时间缩短:平均Pod启动时间从45秒减少到15秒。
3. 节点负载均衡:节点间CPU和内存使用差异从±40%降低到±15%。
4. 应用性能稳定:关键应用响应时间波动从±200ms降低到±50ms。

6.2 多可用区高可用调度优化

某金融企业需要在多个可用区部署关键应用,确保高可用性和灾难恢复能力。他们通过优化调度策略,实现了应用在多可用区间的智能分布和故障自动转移。

企业的关键需求包括:

1. 应用实例必须分布在至少3个可用区。
2. 每个可用区至少运行一个应用实例。
3. 某个可用区故障时,应用能自动在其他可用区恢复。
4. 跨可用区网络延迟最小化。

针对上述需求,团队实施了以下解决方案:

1. 区域感知调度:使用节点亲和性确保Pod分布在多个可用区。使用Pod反亲和性避免单点故障。
2. 使用节点亲和性确保Pod分布在多个可用区。
3. 使用Pod反亲和性避免单点故障。

• 使用节点亲和性确保Pod分布在多个可用区。
• 使用Pod反亲和性避免单点故障。
  1. apiVersion: apps/v1
  2.    kind: Deployment
  3.    metadata:
  4.      name: critical-app
  5.    spec:
  6.      replicas: 6
  7.      template:
  8.        spec:
  9.          affinity:
  10.            nodeAffinity:
  11.              requiredDuringSchedulingIgnoredDuringExecution:
  12.                nodeSelectorTerms:
  13.                - matchExpressions:
  14.                  - key: topology.kubernetes.io/zone
  15.                    operator: In
  16.                    values:
  17.                    - us-east-1a
  18.                    - us-east-1b
  19.                    - us-east-1c
  20.            podAntiAffinity:
  21.              requiredDuringSchedulingIgnoredDuringExecution:
  22.              - labelSelector:
  23.                  matchExpressions:
  24.                  - key: app
  25.                    operator: In
  26.                    values:
  27.                    - critical-app
  28.                topologyKey: topology.kubernetes.io/zone
  29.              preferredDuringSchedulingIgnoredDuringExecution:
  30.              - weight: 100
  31.                podAffinityTerm:
  32.                  labelSelector:
  33.                    matchExpressions:
  34.                    - key: app
  35.                      operator: In
  36.                      values:
  37.                      - critical-app
  38.                  topologyKey: kubernetes.io/hostname
复制代码

1. 区域故障恢复:使用Pod Disruption Budget确保最小可用实例数。使用自定义控制器监控可用区状态,自动重新调度Pod。
2. 使用Pod Disruption Budget确保最小可用实例数。
3. 使用自定义控制器监控可用区状态,自动重新调度Pod。

• 使用Pod Disruption Budget确保最小可用实例数。
• 使用自定义控制器监控可用区状态,自动重新调度Pod。
  1. apiVersion: policy/v1
  2.    kind: PodDisruptionBudget
  3.    metadata:
  4.      name: critical-app-pdb
  5.    spec:
  6.      minAvailable: 3
  7.      selector:
  8.        matchLabels:
  9.          app: critical-app
复制代码

1. 网络优化:使用拓扑感知路由优化跨可用区网络流量。使用本地存储减少跨可用区数据访问。
2. 使用拓扑感知路由优化跨可用区网络流量。
3. 使用本地存储减少跨可用区数据访问。

• 使用拓扑感知路由优化跨可用区网络流量。
• 使用本地存储减少跨可用区数据访问。
  1. apiVersion: v1
  2.    kind: Service
  3.    metadata:
  4.      name: critical-app-service
  5.      annotations:
  6.        service.kubernetes.io/topology-aware-hints: "auto"
  7.    spec:
  8.      selector:
  9.        app: critical-app
  10.      ports:
  11.      - protocol: TCP
  12.        port: 80
  13.        targetPort: 8080
复制代码

通过上述优化,企业实现了以下目标:

1. 高可用性:应用实例均匀分布在3个可用区,每个可用区运行2个实例。
2. 故障恢复:模拟可用区故障时,应用在2分钟内自动恢复到其他可用区。
3. 网络性能:跨可用区网络延迟降低30%,应用响应时间提升25%。
4. 运营效率:自动化故障恢复减少了70%的人工干预。

6.3 GPU资源调度优化

某AI公司需要高效调度GPU资源,支持多种深度学习训练和推理任务。他们通过自定义调度策略,实现了GPU资源的高效利用和任务优先级管理。

公司面临的主要挑战包括:

1. GPU资源昂贵且有限,需要最大化利用率。
2. 不同任务对GPU资源的需求差异大。
3. 训练任务通常需要长时间独占GPU,而推理任务可以共享GPU。
4. 关键任务需要优先获得GPU资源。

针对上述挑战,团队实施了以下优化方案:

1. GPU资源管理:使用设备插件管理GPU资源。自定义GPU资源分配策略。
2. 使用设备插件管理GPU资源。
3. 自定义GPU资源分配策略。

• 使用设备插件管理GPU资源。
• 自定义GPU资源分配策略。
  1. # GPU设备插件配置
  2.    apiVersion: v1
  3.    kind: DaemonSet
  4.    metadata:
  5.      name: nvidia-device-plugin-daemonset
  6.      namespace: kube-system
  7.    spec:
  8.      template:
  9.        spec:
  10.          containers:
  11.          - image: nvcr.io/nvidia/k8s-device-plugin:v0.8.0
  12.            name: nvidia-device-plugin-ctr
  13.            env:
  14.              - name: FAIL_ON_INIT_ERROR
  15.                value: "false"
  16.            volumeMounts:
  17.              - name: device-plugin
  18.                mountPath: /var/lib/kubelet/device-plugins
  19.          volumes:
  20.            - name: device-plugin
  21.              hostPath:
  22.                path: /var/lib/kubelet/device-plugins
复制代码

1. 自定义调度器:开发专门的GPU调度器,支持GPU共享和抢占。实现任务优先级和资源预留机制。
2. 开发专门的GPU调度器,支持GPU共享和抢占。
3. 实现任务优先级和资源预留机制。

• 开发专门的GPU调度器,支持GPU共享和抢占。
• 实现任务优先级和资源预留机制。
  1. // 自定义GPU调度器伪代码
  2.    type GPUScheduler struct {
  3.      // 调度器状态
  4.      gpuNodes []*GPUNode
  5.      pendingQueue []*Task
  6.      runningTasks map[string]*Task
  7.      priorityClasses map[string]int
  8.    }
  9.    
  10.    func (s *GPUScheduler) Schedule() {
  11.      // 按优先级排序待调度任务
  12.      sort.Slice(s.pendingQueue, func(i, j int) bool {
  13.        return s.priorityClasses[s.pendingQueue[i].PriorityClass] >
  14.               s.priorityClasses[s.pendingQueue[j].PriorityClass]
  15.      })
  16.      
  17.      // 尝试调度每个任务
  18.      for _, task := range s.pendingQueue {
  19.        for _, node := range s.gpuNodes {
  20.          if s.canSchedule(task, node) {
  21.            s.assignTask(task, node)
  22.            break
  23.          }
  24.        }
  25.      }
  26.    }
  27.    
  28.    func (s *GPUScheduler) canSchedule(task *Task, node *GPUNode) bool {
  29.      // 检查节点是否有足够的GPU资源
  30.      if task.RequiresExclusiveGPU && node.AvailableExclusiveGPUs == 0 {
  31.        return false
  32.      }
  33.      
  34.      if !task.RequiresExclusiveGPU && node.AvailableSharedGPUMemory < task.RequiredGPUMemory {
  35.        return false
  36.      }
  37.      
  38.      // 检查节点是否满足其他约束
  39.      if !node.Labels.Match(task.NodeSelector) {
  40.        return false
  41.      }
  42.      
  43.      return true
  44.    }
  45.    
  46.    func (s *GPUScheduler) assignTask(task *Task, node *GPUNode) {
  47.      // 分配GPU资源
  48.      if task.RequiresExclusiveGPU {
  49.        node.AvailableExclusiveGPUs--
  50.        task.AssignedGPUs = []string{node.AllocateExclusiveGPU()}
  51.      } else {
  52.        allocatedMemory := task.RequiredGPUMemory
  53.        task.AssignedGPUs = node.AllocateSharedGPU(allocatedMemory)
  54.        node.AvailableSharedGPUMemory -= allocatedMemory
  55.      }
  56.      
  57.      // 更新任务状态
  58.      task.Status = "Running"
  59.      task.Node = node.Name
  60.      s.runningTasks[task.ID] = task
  61.      
  62.      // 从待调度队列中移除
  63.      for i, t := range s.pendingQueue {
  64.        if t.ID == task.ID {
  65.          s.pendingQueue = append(s.pendingQueue[:i], s.pendingQueue[i+1:]...)
  66.          break
  67.        }
  68.      }
  69.      
  70.      // 创建Pod
  71.      s.createPod(task)
  72.    }
复制代码

1. 任务优先级管理:使用Pod优先级和抢占机制。实现任务排队和超时处理。
2. 使用Pod优先级和抢占机制。
3. 实现任务排队和超时处理。

• 使用Pod优先级和抢占机制。
• 实现任务排队和超时处理。
  1. # 优先级类定义
  2.    apiVersion: scheduling.k8s.io/v1
  3.    kind: PriorityClass
  4.    metadata:
  5.      name: high-priority
  6.    value: 1000000
  7.    globalDefault: false
  8.    description: "This priority class should be used for critical GPU training jobs only."
  9.    ---
  10.    apiVersion: scheduling.k8s.io/v1
  11.    kind: PriorityClass
  12.    metadata:
  13.      name: medium-priority
  14.    value: 500000
  15.    globalDefault: false
  16.    description: "This priority class should be used for regular GPU training jobs."
  17.    ---
  18.    apiVersion: scheduling.k8s.io/v1
  19.    kind: PriorityClass
  20.    metadata:
  21.      name: low-priority
  22.    value: 100000
  23.    globalDefault: true
  24.    description: "This priority class should be used for GPU inference jobs."
  25.    
  26.    # 使用优先级类的Pod
  27.    apiVersion: v1
  28.    kind: Pod
  29.    metadata:
  30.      name: high-priority-gpu-job
  31.    spec:
  32.      priorityClassName: high-priority
  33.      containers:
  34.      - name: gpu-container
  35.        image: tensorflow/tensorflow:latest-gpu
  36.        resources:
  37.          limits:
  38.            nvidia.com/gpu: 2
复制代码

通过上述优化,公司取得了显著效果:

1. GPU利用率提升:从60%提升到90%,支持更多并发任务。
2. 任务完成时间缩短:高优先级任务平均等待时间从30分钟减少到5分钟。
3. 资源成本降低:通过GPU共享和智能调度,节省了30%的GPU资源成本。
4. 运营效率提升:自动化调度减少了80%的人工干预。

7. 构建稳定云原生环境的最佳实践

通过优化Kubernetes调度器,我们可以构建更加稳定、高效的云原生环境。本节将总结一些构建稳定云原生环境的最佳实践。

7.1 资源管理最佳实践

有效的资源管理是构建稳定云原生环境的基础。以下是一些资源管理的最佳实践:

为所有容器设置资源请求和限制,确保调度器能够做出合理的决策,防止资源耗尽。
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: resource-managed-app
  5. spec:
  6.   template:
  7.     spec:
  8.       containers:
  9.       - name: app
  10.         image: myapp:1.0
  11.         resources:
  12.           requests:
  13.             cpu: "500m"
  14.             memory: "512Mi"
  15.           limits:
  16.             cpu: "1000m"
  17.             memory: "1Gi"
复制代码

在命名空间级别使用资源配额和限制范围,防止单个应用或团队占用过多资源。
  1. # 资源配额
  2. apiVersion: v1
  3. kind: ResourceQuota
  4. metadata:
  5.   name: namespace-quota
  6. spec:
  7.   hard:
  8.     requests.cpu: "10"
  9.     requests.memory: "20Gi"
  10.     limits.cpu: "20"
  11.     limits.memory: "40Gi"
  12.     pods: "50"
  13. # 限制范围
  14. apiVersion: v1
  15. kind: LimitRange
  16. metadata:
  17.   name: container-limits
  18. spec:
  19.   limits:
  20.   - default:
  21.       cpu: "500m"
  22.       memory: "512Mi"
  23.     defaultRequest:
  24.       cpu: "250m"
  25.       memory: "256Mi"
  26.     type: Container
复制代码

使用资源监控和自动伸缩机制,确保应用能够根据负载动态调整资源使用。
  1. # 水平Pod自动伸缩(HPA)
  2. apiVersion: autoscaling/v2
  3. kind: HorizontalPodAutoscaler
  4. metadata:
  5.   name: app-hpa
  6. spec:
  7.   scaleTargetRef:
  8.     apiVersion: apps/v1
  9.     kind: Deployment
  10.     name: app
  11.   minReplicas: 2
  12.   maxReplicas: 10
  13.   metrics:
  14.   - type: Resource
  15.     resource:
  16.       name: cpu
  17.       target:
  18.         type: Utilization
  19.         averageUtilization: 50
  20.   - type: Resource
  21.     resource:
  22.       name: memory
  23.       target:
  24.         type: Utilization
  25.         averageUtilization: 70
  26. # 垂直Pod自动伸缩(VPA)
  27. apiVersion: autoscaling.k8s.io/v1
  28. kind: VerticalPodAutoscaler
  29. metadata:
  30.   name: app-vpa
  31. spec:
  32.   targetRef:
  33.     apiVersion: "apps/v1"
  34.     kind:       Deployment
  35.     name:       app
  36.   updatePolicy:
  37.     updateMode: "Auto"
复制代码

7.2 调度策略最佳实践

合理的调度策略可以提高资源利用率,确保应用性能和稳定性。以下是一些调度策略的最佳实践:

使用节点和Pod的亲和性、反亲和性规则,控制Pod的分布,提高应用可用性和性能。
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: distributed-app
  5. spec:
  6.   template:
  7.     spec:
  8.       affinity:
  9.         # 节点亲和性:选择特定类型的节点
  10.         nodeAffinity:
  11.           requiredDuringSchedulingIgnoredDuringExecution:
  12.             nodeSelectorTerms:
  13.             - matchExpressions:
  14.               - key: node-role.kubernetes.io/worker
  15.                 operator: In
  16.                 values:
  17.                 - "true"
  18.         
  19.         # Pod反亲和性:避免Pod集中在同一节点
  20.         podAntiAffinity:
  21.           requiredDuringSchedulingIgnoredDuringExecution:
  22.           - labelSelector:
  23.               matchExpressions:
  24.               - key: app
  25.                 operator: In
  26.                 values:
  27.                 - distributed-app
  28.             topologyKey: kubernetes.io/hostname
  29.         
  30.         # Pod亲和性:将相关应用部署在一起
  31.         podAffinity:
  32.           preferredDuringSchedulingIgnoredDuringExecution:
  33.           - weight: 100
  34.             podAffinityTerm:
  35.               labelSelector:
  36.                 matchExpressions:
  37.                 - key: app
  38.                   operator: In
  39.                   values:
  40.                   - cache-service
  41.               topologyKey: kubernetes.io/hostname
复制代码

使用污点和容忍机制隔离不同类型的工作负载,确保关键应用不受干扰。
  1. # 为关键节点添加污点
  2. apiVersion: v1
  3. kind: Node
  4. metadata:
  5.   name: critical-node-1
  6. spec:
  7.   taints:
  8.   - key: workload-type
  9.     value: critical
  10.     effect: NoSchedule
  11. # 关键应用容忍污点
  12. apiVersion: apps/v1
  13. kind: Deployment
  14. metadata:
  15.   name: critical-app
  16. spec:
  17.   template:
  18.     spec:
  19.       tolerations:
  20.       - key: workload-type
  21.         operator: Equal
  22.         value: critical
  23.         effect: NoSchedule
  24.       containers:
  25.       - name: app
  26.         image: critical-app:1.0
复制代码

对于有特殊调度需求的应用,使用自定义调度器实现更精细的调度控制。
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4.   name: custom-scheduled-pod
  5. spec:
  6.   schedulerName: custom-scheduler
  7.   containers:
  8.   - name: app
  9.     image: special-app:1.0
复制代码

7.3 高可用性和容灾最佳实践

构建高可用、容灾能力强的云原生环境是确保业务连续性的关键。以下是一些高可用性和容灾的最佳实践:

将应用部署在多个可用区,确保单个可用区故障时应用仍能正常运行。
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: multi-az-app
  5. spec:
  6.   replicas: 6
  7.   template:
  8.     spec:
  9.       affinity:
  10.         nodeAffinity:
  11.           requiredDuringSchedulingIgnoredDuringExecution:
  12.             nodeSelectorTerms:
  13.             - matchExpressions:
  14.               - key: topology.kubernetes.io/zone
  15.                 operator: In
  16.                 values:
  17.                 - us-east-1a
  18.                 - us-east-1b
  19.                 - us-east-1c
  20.         podAntiAffinity:
  21.           requiredDuringSchedulingIgnoredDuringExecution:
  22.           - labelSelector:
  23.               matchExpressions:
  24.               - key: app
  25.                 operator: In
  26.                 values:
  27.                 - multi-az-app
  28.             topologyKey: topology.kubernetes.io/zone
复制代码

使用Pod中断预算(PDB)确保在维护或故障期间始终有足够的应用实例运行。
  1. apiVersion: policy/v1
  2. kind: PodDisruptionBudget
  3. metadata:
  4.   name: app-pdb
  5. spec:
  6.   minAvailable: 2
  7.   selector:
  8.     matchLabels:
  9.       app: multi-az-app
复制代码

为应用配置适当的健康检查,确保不健康的容器能够自动重启或替换。
  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4.   name: health-checked-app
  5. spec:
  6.   template:
  7.     spec:
  8.       containers:
  9.       - name: app
  10.         image: health-checked-app:1.0
  11.         livenessProbe:
  12.           httpGet:
  13.             path: /health
  14.             port: 8080
  15.           initialDelaySeconds: 30
  16.           periodSeconds: 10
  17.           timeoutSeconds: 5
  18.           failureThreshold: 3
  19.         readinessProbe:
  20.           httpGet:
  21.             path: /ready
  22.             port: 8080
  23.           initialDelaySeconds: 5
  24.           periodSeconds: 5
  25.           timeoutSeconds: 3
  26.           failureThreshold: 1
复制代码

7.4 安全性最佳实践

确保云原生环境的安全性是保护应用和数据的关键。以下是一些安全性的最佳实践:

使用Pod安全策略(Pod Security Policy)限制Pod的安全配置,防止不安全的设置。
  1. apiVersion: policy/v1beta1
  2. kind: PodSecurityPolicy
  3. metadata:
  4.   name: restricted-psp
  5. spec:
  6.   privileged: false
  7.   allowPrivilegeEscalation: false
  8.   requiredDropCapabilities:
  9.     - ALL
  10.   volumes:
  11.     - 'configMap'
  12.     - 'emptyDir'
  13.     - 'projected'
  14.     - 'secret'
  15.     - 'downwardAPI'
  16.     - 'persistentVolumeClaim'
  17.   runAsUser:
  18.     rule: 'MustRunAsNonRoot'
  19.   seLinux:
  20.     rule: 'RunAsAny'
  21.   fsGroup:
  22.     rule: 'RunAsAny'
复制代码

使用网络策略(Network Policy)控制Pod之间的网络通信,防止未授权访问。
  1. apiVersion: networking.k8s.io/v1
  2. kind: NetworkPolicy
  3. metadata:
  4.   name: app-network-policy
  5. spec:
  6.   podSelector:
  7.     matchLabels:
  8.       app: secure-app
  9.   policyTypes:
  10.   - Ingress
  11.   - Egress
  12.   ingress:
  13.   - from:
  14.     - podSelector:
  15.         matchLabels:
  16.           app: frontend
  17.     ports:
  18.     - protocol: TCP
  19.       port: 80
  20.   egress:
  21.   - to:
  22.     - podSelector:
  23.         matchLabels:
  24.           app: database
  25.     ports:
  26.     - protocol: TCP
  27.       port: 5432
复制代码

使用基于角色的访问控制(RBAC)限制用户和服务账户对Kubernetes资源的访问权限。
  1. # 角色
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: Role
  4. metadata:
  5.   namespace: default
  6.   name: app-operator
  7. rules:
  8. - apiGroups: [""]
  9.   resources: ["pods", "services", "configmaps"]
  10.   verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  11. - apiGroups: ["apps"]
  12.   resources: ["deployments", "replicasets"]
  13.   verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  14. # 角色绑定
  15. apiVersion: rbac.authorization.k8s.io/v1
  16. kind: RoleBinding
  17. metadata:
  18.   name: app-operator-binding
  19.   namespace: default
  20. subjects:
  21. - kind: ServiceAccount
  22.   name: app-operator-sa
  23.   namespace: default
  24. roleRef:
  25.   kind: Role
  26.   name: app-operator
  27.   apiGroup: rbac.authorization.k8s.io
复制代码

7.5 监控和日志最佳实践

有效的监控和日志系统是确保云原生环境稳定运行的关键。以下是一些监控和日志的最佳实践:

使用Prometheus、Grafana等工具实施全面监控,覆盖基础设施、Kubernetes组件和应用性能。
  1. # Prometheus监控配置示例
  2. apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5.   name: prometheus-config
  6. data:
  7.   prometheus.yml: |
  8.     global:
  9.       scrape_interval: 15s
  10.     scrape_configs:
  11.     - job_name: 'kubernetes-apiservers'
  12.       kubernetes_sd_configs:
  13.       - role: endpoints
  14.       scheme: https
  15.       tls_config:
  16.         ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  17.       bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  18.       relabel_configs:
  19.       - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
  20.         action: keep
  21.         regex: default;kubernetes;https
  22.    
  23.     - job_name: 'kubernetes-nodes'
  24.       kubernetes_sd_configs:
  25.       - role: node
  26.       scheme: https
  27.       tls_config:
  28.         ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  29.       bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  30.       relabel_configs:
  31.       - action: labelmap
  32.         regex: __meta_kubernetes_node_label_(.+)
  33.       - target_label: __address__
  34.         replacement: kubernetes.default.svc:443
  35.       - source_labels: [__meta_kubernetes_node_name]
  36.         regex: (.+)
  37.         target_label: __metrics_path__
  38.         replacement: /api/v1/nodes/${1}/proxy/metrics
复制代码

使用Elasticsearch、Fluentd、Kibana(EFK)或Loki等工具实施集中化日志管理,便于故障排查和分析。
  1. # Fluentd日志收集配置示例
  2. apiVersion: v1
  3. kind: ConfigMap
  4. metadata:
  5.   name: fluentd-config
  6. data:
  7.   fluent.conf: |
  8.     <source>
  9.       @type tail
  10.       path /var/log/containers/*app*.log
  11.       pos_file /var/log/fluentd-containers.log.pos
  12.       tag kubernetes.*
  13.       format json
  14.       time_format %Y-%m-%dT%H:%M:%S.%NZ
  15.     </source>
  16.    
  17.     <match kubernetes.**>
  18.       @type elasticsearch
  19.       host elasticsearch-logging
  20.       port 9200
  21.       index_name fluentd
  22.       type_name _doc
  23.     </match>
复制代码

基于监控指标设置合理的告警规则,确保在问题发生时能够及时通知运维人员。
  1. # Prometheus告警规则示例
  2. apiVersion: monitoring.coreos.com/v1
  3. kind: PrometheusRule
  4. metadata:
  5.   name: app-alert-rules
  6. spec:
  7.   groups:
  8.   - name: app.rules
  9.     rules:
  10.     - alert: HighPodMemoryUsage
  11.       expr: sum(container_memory_usage_bytes{container!="POD", pod=~"app-.*"}) by (pod) / sum(container_spec_memory_limit_bytes{container!="POD", pod=~"app-.*"}) by (pod) > 0.9
  12.       for: 5m
  13.       labels:
  14.         severity: warning
  15.       annotations:
  16.         summary: "High memory usage of pod {{ $labels.pod }}"
  17.         description: "Pod {{ $labels.pod }} memory usage is above 90% for 5 minutes."
  18.    
  19.     - alert: PodCrashLooping
  20.       expr: rate(kube_pod_container_status_restarts_total{pod=~"app-.*"}[15m]) * 60 * 15 > 0
  21.       for: 5m
  22.       labels:
  23.         severity: critical
  24.       annotations:
  25.         summary: "Pod {{ $labels.pod }} is crash looping."
  26.         description: "Pod {{ $labels.pod }} ({{ $labels.container }}) is restarting {{ $value }} times per 15 minutes."
复制代码

结论

Kubernetes调度器作为容器编排系统的核心组件,其工作原理和优化技巧对于构建高效、稳定的云原生环境至关重要。通过深入理解调度器的工作流程、资源感知机制和智能调度策略,我们可以更好地优化集群资源利用率,提高应用性能和系统稳定性。

本文从调度器的基本工作原理出发,详细介绍了过滤、打分和绑定等关键步骤,探讨了资源感知机制和智能调度策略,并提供了一系列实用的优化技巧和实际案例分析。最后,我们总结了构建稳定云原生环境的最佳实践,涵盖资源管理、调度策略、高可用性、安全性以及监控和日志等方面。

随着云原生技术的不断发展,Kubernetes调度器也在持续演进。未来,我们可以期待更多智能化、自动化的调度功能,如基于机器学习的资源预测、更灵活的调度策略和更高效的调度算法。通过不断学习和实践,我们可以更好地掌握Kubernetes调度器的核心原理和优化技巧,为构建高效、稳定的云原生环境贡献力量。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

0

主题

1304

科技点

654

积分

候风辨气

积分
654
候风辨气 发表于 2025-9-25 14:48:34 | 显示全部楼层
感謝分享
温馨提示:看帖回帖是一种美德,您的每一次发帖、回帖都是对论坛最大的支持,谢谢! [这是默认签名,点我更换签名]
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则