k8s(七)Pod调度

Pod的调度

概述

在默认情况下,一个Pod在哪个Node节点上运行,是由Scheduler组件采用相应的算法计算出来的,这个过程是不受人工控制的。但是在实际使用中,这并不满足需求,因为很多情况下,我们想控制某些Pod到达某些节点上,那么应该怎么做?这就要求了解kubernetes对Pod的调度规则,kubernetes提供了四大类调度方式。

  • 自动调度:运行在哪个Node节点上完全由Scheduler经过一系列的算法计算得出。
  • 定向调度:NodeName、NodeSelector。(NodeSelector是查找主机的label)
  • 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity。(既可以指定和主机的亲和度也可以指定和Pod的亲和度 也是使用标签实现的)
  • 污点(容忍)调度:Taints、Toleration (污点是站在主机的角度上说的)

定向调度

概述
定向调度,指的是利用在Pod上声明的nodeName或nodeSelector,以此将Pod调度到期望的Node节点上。注意,这里的调度是强制的,这就意味着即使要调度的目标Node不存在,也会向上面进行调度,只不过Pod运行失败而已。
nodeName

nodeName用于强制约束将Pod调度到指定的name的Node节点上。这种方式,其实是直接跳过Scheduler的调度逻辑,直接将Pod调度到指定名称的节点。

创建一个pod-nodename.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodename
  namespace: dev
  labels:
    user: xudaxian
spec:
  containers: # 容器配置
    - name: nginx
      image: nginx:1.17.1
      imagePullPolicy: IfNotPresent
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
  nodeName: k8s-node1 # 指定调度到k8s-node1节点上	强制性的 无论存不存在
• 创建Pod:
kubectl create -f pod-nodename.yaml
• 查看Pod:
kubectl get pod pod-nodename -n dev -o wide

nodeSelector
nodeSelector用于将Pod调度到添加了指定标签的Node节点上,它是通过kubernetes的label-selector机制实现的,换言之,在Pod创建之前,会由Scheduler使用MatchNodeSelector调度策略进行label匹配,找出目标node,然后将Pod调度到目标节点,该匹配规则是强制约束。
首先给node节点添加标签:

kubectl label node k8s-node1 nodeevn=pro
kubectl label node k8s-node2 nodeenv=test

创建pod-nodeselector.yaml文件,内容如下:

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeselector
  namespace: dev
spec:
  containers: # 容器配置
    - name: nginx
      image: nginx:1.17.1
      imagePullPolicy: IfNotPresent
      ports:
        - name: nginx-port
          containerPort: 80
          protocol: TCP
  nodeSelector:
    nodeenv: pro # 指定调度到具有nodeenv=pro的Node节点上
• 创建Pod:
kubectl create -f pod-nodeselector.yaml
• 查看Pod:
kubectl get pod pod-nodeselector -n dev -o wide

亲和性调度

概述
虽然定向调度的两种方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的Node,那么Pod将不会被运行,即使在集群中还有可用的Node列表也不行,这就限制了它的使用场景。(强制性)

基于上面的问题,kubernetes还提供了一种亲和性调度(Affinity)。它在nodeSelector的基础之上进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使得调度更加灵活。
Affinity主要分为三类:

  • nodeAffinity(node亲和性):以Node为目标,解决Pod可以调度到那些Node的问题。
  • podAffinity(pod亲和性):以Pod为目标,解决Pod可以和那些已存在的Pod部署在同一个拓扑域中的问题。
  • podAntiAffinity(pod反亲和性):以Pod为目标,解决Pod不能和那些已经存在的Pod部署在同一拓扑域中的问题。
    关于亲和性和反亲和性的使用场景的说明:

使用场景

• 亲和性:如果两个应用频繁交互,那么就有必要利用亲和性让两个应用尽可能的靠近,这样可以较少因网络通信而带来的性能损耗。
• 反亲和性:当应用采用多副本部署的时候,那么就有必要利用反亲和性让各个应用实例打散分布在各个Node上,这样可以提高服务的高可用性。

nodeAffinity
查看nodeAffinity的可选配置项:

pod.spec.affinity.nodeAffinity

  requiredDuringSchedulingIgnoredDuringExecution  Node节点必须满足指定的所有规则才可以,相当于硬限制
    nodeSelectorTerms  节点选择列表
      matchFields   按节点字段列出的节点选择器要求列表  
      matchExpressions   按节点标签列出的节点选择器要求列表(推荐)
        key    键
        values 值
        operator 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt
  preferredDuringSchedulingIgnoredDuringExecution 优先调度到满足指定的规则的Node,相当于软限制 (倾向)     
    preference   一个节点选择器项,与相应的权重相关联
      matchFields 按节点字段列出的节点选择器要求列表
      matchExpres
### Kubernetes 调度器工作原理 Kubernetes 调度器的核心任务是将新创建的 Pod 分配到最适合运行它的节点上[^1]。这一过程涉及多个阶段,主要包括以下几个方面: #### 1. **调度流程概述** 调度器作为一个独立的控制平面组件,持续监控集群中的未分配 Pod,并为其寻找最佳目标节点[^3]。整个调度过程可以分为两个主要阶段:过滤(Filtering)和评分(Scoring)。 - **过滤阶段**:调度器首先筛选出能够满足 Pod 运行条件的所有候选节点。这一步骤基于预定义的规则集完成,例如资源可用性、亲和性和反亲和性约束等[^4]。 - **评分阶段**:对于通过过滤阶段的节点,调度器会应用一系列优先级函数对其进行打分。最终得分最高的节点会被选中作为目标节点。 #### 2. **绑定操作** 一旦选定目标节点,调度器会向 `kube-apiserver` 发送绑定请求,通知该 Pod 应当部署在哪一节点上。此步骤称为绑定(Binding),它是调度过程中不可或缺的一部分[^5]。 --- ### 配置方法 为了实现更灵活的调度行为,用户可以通过多种方式调整默认调度逻辑: #### 自定义调度策略 Kubernetes 支持自定义调度策略文件,允许管理员指定不同的调度算法或权重设置。以下是配置自定义调度策略的一个简单示例: ```yaml apiVersion: kubescheduler.config.k8s.io/v1beta1 kind: KubeSchedulerConfiguration profiles: - schedulerName: default-scheduler plugins: score: enabled: - name: NodeResourcesBalancedAllocation weight: 1 ``` 上述 YAML 文件展示了如何修改内置插件 `NodeResourcesBalancedAllocation` 的权重值。通过这种方式,用户可以根据实际需求微调调度决策。 #### 动态调度框架 从 v1.16 开始,Kubernetes 引入了扩展性强的动态调度框架(Dynamic Scheduling Framework)。开发者可以编写自定义调度插件并将其集成至现有调度器中,从而支持更为复杂的业务场景。 --- ### 使用注意事项 在大规模生产环境中使用 Kubernetes 调度器时需要注意以下几点: - **性能优化**:随着集群规模的增长,调度延迟可能成为瓶颈。为此,建议启用多线程调度模式以提升效率[^2]。 - **高可用性设计**:为了避免单点故障风险,通常推荐采用多副本的方式部署 kube-scheduler 实例。 --- ### 示例代码 下面是一段用于测试自定义调度策略效果的小型 Python 客户端脚本: ```python from kubernetes import client, config config.load_kube_config() v1 = client.CoreV1Api() pod_manifest = { 'apiVersion': 'v1', 'kind': 'Pod', 'metadata': {'name': 'test-pod'}, 'spec': { 'schedulerName': 'custom-scheduler', # 指定自定义调度器名称 'containers': [{ 'name': 'busybox', 'image': 'busybox', 'command': ['sleep', 'infinity'] }] } } resp = v1.create_namespaced_pod(body=pod_manifest, namespace='default') print(f"Pod {resp.metadata.name} created.") ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值