目录

一、Kubernetes 集群调度

1、Kubernetes 组件协作机制

关键组件关系:

2、Pod 创建与工作机制流程

典型创建过程(List-Watch 模型)

(1)三大组件启动监听(List-Watch)

3、调度流程

3.1 过滤阶段(Predicate)

3.2 优选阶段(Priorities)

指定调度节点方式

nodeName(强制绑定)

ymal文件

查看调度节点

 nodeSelector(基于标签匹配)

当前的节点

给对应的 node 设置标签分别为 yjs=a 和 yjs=b

展示标签

修改label的值

删除标签

修改成 nodeSelector 调度方式

查看详细事件

节点亲和性与 Pod 亲和性

定义

类比举例子

硬策略

yaml文件

查看pod节点

删除所有的容器并不会被创建的命令

软策略

查看节点信息

软策略加硬策略

查看信息

Pod 亲和性与反亲和性

Pod 亲和性调度

创建一个标签为 app=myapp01 的 Pod

使用 Pod 亲和性调度,创建多个 Pod 资源

Pod 反亲和性调度

污点(Taint) 和 容忍(Tolerations)

命令示例

污点(Taint)

容忍 (Tolerations)

仍然能运行起来


一、Kubernetes 集群调度


1、Kubernetes 组件协作机制

Kubernetes 通过 List-Watch 机制使各个组件协作、数据同步,从而实现解耦与实时一致性。

关键组件关系:

组件职责
kubectl / API 客户端向 APIServer 发起资源创建或管理请求
APIServer负责 API 调用、权限校验、存储交互,是集群控制的核心入口
etcd存储集群所有状态信息
Controller Manager维持副本数、执行自愈逻辑(扩容、重建等)
Scheduler调度器,将未分配节点的 Pod 分配到合适的 Node
kubelet节点代理,负责 Pod 生命周期管理和容器运行状态上报

用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。
APIServer 经过 API 调用,权限控制,调用资源和存储资源的过程,实际上还没有真正开始部署应用。这里    需要 Controller Manager、Scheduler 和 kubelet 的协助才能完成整个部署过程。

在 Kubernetes 中,所有部署的信息都会写到 etcd 中保存。实际上 etcd 在存储部署信息的时候,会发送 Create 事件给 APIServer,而 APIServer 会通过监听(Watch)etcd 发过来的事件。其他组件也会监听(Watch)APIServer 发出来的事件。

2、Pod 创建与工作机制流程

Pod 创建的整个生命周期由多组件配合完成:

典型创建过程(List-Watch 模型)

(1)三大组件启动监听(List-Watch)
  • Controller Manager、Scheduler、kubelet 启动后会分别通过 Watch API Server(HTTPS 6443 端口)监听集群资源事件变化。

    • Controller Manager:监听副本控制类对象(如 ReplicaSet、Deployment)

    • Scheduler:监听未调度的 Pod

    • kubelet:监听分配到本节点的 Pod

3、调度流程

3.1 过滤阶段(Predicate)

过滤掉不满足条件的节点。

常见过滤算法:

算法名功能描述
PodFitsResources检查节点剩余资源是否满足 Pod 需求
PodFitsHost检查 NodeName 是否匹配
PodFitsHostPorts检查端口冲突
PodSelectorMatcheslabel 匹配
NoDiskConflictVolume 挂载冲突检测

若无节点满足条件,Pod 进入 Pending 状态,不断重试。

如果在 predicate 过程中没有合适的节点,pod 会一直在 pending 状态,不断重试调度,直到有节点满足条件。 经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序。


3.2 优选阶段(Priorities)

对可行节点进行打分排序。

常见算法:

优先级项描述
LeastRequestedPriority资源使用率越低,权重越高
BalancedResourceAllocationCPU 与内存使用率越接近越好(这个一般和上面的一起使用,不单独使用。比如 node01 的 CPU 和 Memory 使用率 20:60,node02 的 CPU 和 Memory 使用率 50:50,虽然 node01 的总使用率比 node02 低,但 node02 的 CPU 和 Memory 使用率更接近,从而调度时会优选 node02。)
ImageLocalityPriority优先节点上已有目标镜像的节点

指定调度节点方式

nodeName(强制绑定)

ymal文件

vim myapp.yaml

apiVersion: apps/v1  
kind: Deployment   # pod
metadata:
  name: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      nodeName: node01
      containers:
      - name: myapp
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80

kubectl apply -f myapp.yaml

查看调度节点

kubectl get pods -o wide

 kubectl describe pod myapp-699655c7fd-5qrp2|tail -6

 nodeSelector(基于标签匹配)

当前的节点

给对应的 node 设置标签分别为 yjs=a 和 yjs=b

kubectl label nodes node01 yjs=a

kubectl label nodes node02 yjs=b

展示标签

kubectl get node --show-labels

修改label的值

kubectl label node node02 yjs=c --overwrite

删除标签

kubectl label nodes node02 yjs-

修改成 nodeSelector 调度方式

vim myapp1.yaml
apiVersion: apps/v1
kind: Deployment  
metadata:
  name: myapp1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp1
  template:
    metadata:
      labels:
        app: myapp1
    spec:
      nodeSelector:
	    yjs: a
      containers:
      - name: myapp1
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80 
        
kubectl apply -f myapp1.yaml 

获取pod信息

kubectl get pods -o wide

查看详细事件

kubectl describe pod myapp1-64c58784f9-42ctc|tail -10

节点亲和性与 Pod 亲和性

定义

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:   # 硬策略
    preferredDuringSchedulingIgnoredDuringExecution:  # 软策略

类比举例子

你更“想去”陈老师的班(软策略),还是“必须去”陈老师的班(硬策略)

运算符含义通俗理解示例
Inlabel 的值在列表中“只要它的值在我列的名单里,就选上它”env In (dev, test) → 选出 env=dev 或 env=test 的 Pod
NotInlabel 的值不在列表中“黑名单里的不要”env NotIn (prod) → 除了生产环境都选上
Gtlabel 的值大于某个数“比这个数字大的才要”version Gt 3 → 选出 version=4,5,6… 的 Pod
Ltlabel 的值小于某个数“比这个数字小的才要”version Lt 3 → 选出 version=1,2 的 Pod
Existslabel 存在即可“只要有这个标签就算数,不管值是啥”Exists zone → 只要有 zone 这个标签
DoesNotExistlabel 不存在“没有这个标签的才要”DoesNotExist debug → 没有 debug 标签的 Pod

硬策略

kubectl get nodes --show-labels

yaml文件

vim pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname    #指定node的标签
            operator: NotIn #设置Pod安装到kubernetes.io/hostname的标签值不在values列表中的node上
            values:
            - node02

kubectl apply -f pod1.yaml
                                       

查看pod节点

删除所有的容器并不会被创建的命令

kubectl delete deployments --all

软策略

vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1   #如果有多个软策略选项的话,数值越小,权重越大,优先级越高
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node03   # 这里没有node03这个节点

kubectl apply -f pod2.yaml

查看节点信息

软策略加硬策略

vim demo2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: affinity1
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:   #先满足硬策略,排除有kubernetes.io/hostname=node02标签的节点
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node02
      preferredDuringSchedulingIgnoredDuringExecution:  #再满足软策略,优先选择有yjsc=a标签的节点
	  - weight: 1
        preference:
          matchExpressions:
          - key: yjs
            operator: In
            values:
            - a

kubectl apply -f pod2.yaml

查看信息

Pod 亲和性与反亲和性

调度策略匹配标签操作符拓扑域支持调度目标
nodeAffinity主机IIn, NotIn, Exists,DoesNotExist, Gt, Lt❌指定主机
podAffinityPodIn, NotIn, Exists,DoesNotExist✅与指定 Pod 同域
podAntiAffinityPodIn, NotIn, Exists,DoesNotExist✅与指定 Pod 不同域

Pod 亲和性调度

创建一个标签为 app=myapp01 的 Pod

vim pod3.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1

kubectl apply -f pod3.yaml
	

使用 Pod 亲和性调度,创建多个 Pod 资源

apiVersion: v1
kind: Pod
metadata:
  name: myapp02
  labels:
    app: myapp02
spec:
  containers:
  - name: myapp02
    image: soscscs/myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp01
        topologyKey: yjs

Pod 反亲和性调度

vim pod5.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp10
  labels:
    app: myapp10
spec:
  containers:
  - name: myapp10
    image: soscscs/myapp:v1
  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - myapp01
          topologyKey: kubernetes.io/hostname

反亲和调度

vim pod6.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp20
  labels:
    app: myapp20
spec:
  containers:
  - name: myapp20
    image: soscscs/myapp:v1
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp01
        topologyKey: yjs

kubectl apply -f pod6.yaml

污点(Taint) 和 容忍(Tolerations)

类型描述
NoSchedule不调度到此节点
PreferNoSchedule尽量避免调度具有该污点的 Node 上
NoExecute不调度 + 驱逐已存在 Pod(只是将pod放到其他的node上面)

命令示例

# 主节点的污点
kubectl describe node master|grep Taint
Taints:             node-role.kubernetes.io/master:NoSchedule

# node01设置污点
kubectl taint node node01 key1=value1:NoSchedule
kubectl describe node node01|grep Taint
Taints:             key1=value1:NoSchedule


# 去除污点
kubectl taint node node01 key1:NoSchedule-
kubectl describe node node01|grep Taint
Taints:             <none>

污点(Taint)

kubectl taint node node02 check=mycheck:NoExecute

容忍 (Tolerations)

# 先给两个节点设置污点
kubectl taint node node01 key1=value1:NoSchedule
kubectl taint node node02 key1=value1:NoSchedule

按常理来说,镜像运行不起来

但是我们在文件中加上toleration的参数

vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  tolerations:
  - key: "check"
    operator: "Equal"  #operator: "Equal" #Equal意味着这个值等于value,如果是Exists,则不需要填写value,只要有这个key就容忍
    value: "mycheck"
    effect: "NoExecute"
    tolerationSeconds: 3600

仍然能运行起来

kubectl get pod -owide

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐