k8s--pod 调度、定向调度、亲和性调度、污点和容忍 (一)

简介: k8s--pod 调度、定向调度、亲和性调度、污点和容忍

介绍


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

  • 自动调度:运行在哪个节点上完全由 Scheduler 经过一系列的算法计算得出
  • 定向调度:有两种,根据节点名称(NodeName)或者节点选择器(NodeSelector)
  • 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
  • 污点(容忍)调度: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: zouzou
spec:
  containers:
  - name: nginx
    image: nginx:1.14
  nodeName: dce-10-6-215-190 # 指定调度到 dce-10-6-215-190 节点上

如果你不知道 nodeName 的话,使用下面命令查看

kubectl get node

创建 pod,查看 pod

# 创建 pod
kubectl apply -f pod-nodename.yaml

查看 pod 的信息,可以看到 pod 已经分配给了 dce-10-6-215-190 的节点上

# 可以看到 pod 分配到了 dce-10-6-215-190 的节点上,有人说,可能是随机分配的,那你也可以写一个不存在的 node 地址试下
[root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodename -n zouzou -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP               NODE               NOMINATED NODE   READINESS GATES
pod-nodename   1/1     Running   0          89s   172.29.190.141   dce-10-6-215-190   <none>           <none>


NodeSelector

NodeSelector 用于将 pod 调度到添加了指定标签的 node 节点上,它是通过 kubernetes 的 label-selector 机制实现的,也就是说,在 pod 创建之前,会由 scheduler 使用 MatchNodeSelector 调度策略进行 label 匹配,找出目标 node,然后将 pod 调度到目标节点,该匹配规则是强制约束。

接下来,实验一下:首先查看下节点的 labels

[root@dce-10-6-215-215 tmp]# kubectl get node --show-labels
NAME               STATUS   ROLES             AGE    VERSION    LABELS
dce-10-6-215-190   Ready    <none>            7d3h   v1.18.20   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=dce-10-6-215-190,kubernetes.io/os=linux
dce-10-6-215-200   Ready    <none>            7d1h   v1.18.20   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=dce-10-6-215-200,kubernetes.io/os=linux
dce-10-6-215-215   Ready    master,registry   8d     v1.18.20   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=dce-10-6-215-215,kubernetes.io/os=linux,node-role.kubernetes.io/master=,node-role.kubernetes.io/registry=

上面有很多的标签,为了测试方便,在此基础上给两个 node 节点添加两个简单的标签

kubectl label node dce-10-6-215-190 nodeenv=pro
kubectl label node dce-10-6-215-200 nodeenv=test

在来查看下对应的标签

这样我们就给两个节点打上了标签

创建一个 pod-nodeselector.yaml 文件,并使用它创建 Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeselector
  namespace: zouzou
spec:
  containers:
  - name: nginx
    image: nginx:1.14
  nodeSelector: 
    nodeenv: pro # 指定调度到具有 nodeenv=pro 标签的节点上

创建 pod 查看详情,可以看到,pod 分配给了 nodeenv=pro 的标签节点上

# 创建 pod
[root@dce-10-6-215-215 tmp]# kubectl apply -f pod-nodeselector.yaml
pod/pod-nodeselector created
# 查看 pod 在 dce-10-6-215-190 上了,你也可以写个不存在的标签测试是不是随机分配的
[root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeselector -n zouzou -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP               NODE               NOMINATED NODE   READINESS GATES
pod-nodeselector   1/1     Running   0          48s   172.29.190.142   dce-10-6-215-190   <none>           <none>


亲和性调度


上面,介绍了两种定向调度的方式,使用起来非常方便,但是也有一定的问题,那就是如果没有满足条件的 node,那么 pod 将不会被运行,即使在集群中还有可用 node 列表也不行,这就限制了它的使用场景

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

Affinity 主要分为三类

  • nodeAffinity(node 亲和性):以 node 为目标,解决 pod 可以调度到哪些 node 上的问题
  • podAffinity(pod 亲和性):以 pod 为目标,解决 pod 可以和哪些已存在的 pod 部署在同一个拓扑域中的问题
  • podAntiAffinity(pod 反亲和性):以 pod 为目标,解决 pod 不能和哪些已存在 pod 部署在同一个拓扑域中的问题

关于亲和性和反亲和性使用场景的说明:

亲和性:如果两个应用频繁交互,那就有必要利用亲和性让两个应用尽可能的靠近,这样可以减少因网络通信而带来的性能损耗,比如 web 应用和 mysql,要频繁的从数据库里查询和新增数据,所以应该让他们尽可能的在一起

反亲和性:当应用采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个 node 上,这样可以提高服务的高可用性,当一个服务器挂掉之后,其他的 pod 还可以提供服务


NodeAffinity

首先来看一下 NodeAffinity 的可配置项:

pod.spec.affinity.nodeAffinity
  requiredDuringSchedulingIgnoredDuringExecution  # Node节点必须满足指定的所有规则才可以,相当于硬限制
    nodeSelectorTerms  # 节点选择列表
      matchFields   # 按节点字段列出的节点选择器要求列表
      matchExpressions   # 按节点标签列出的节点选择器要求列表(推荐)
        key    # 键
        values # 值
        operat or # 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt
  preferredDuringSchedulingIgnoredDuringExecution # 优先调度到满足指定的规则的 Node,相当于软限制 (倾向)
    preference   # 一个节点选择器项,与相应的权重相关联
      matchFields  # 按节点字段列出的节点选择器要求列表
      matchExpressions  # 按节点标签列出的节点选择器要求列表(推荐)
        key    # 键
        values # 值
        operator # 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Lt
    weight # 倾向权重,在范围1-100。

关系符的说明

- matchExpressions:
  - key: nodeenv              # 匹配存在标签的 key 为 nodeenv 的节点
    operator: Exists
  - key: nodeenv              # 匹配标签的 key 为 nodeenv,且 value 是 "xxx" 或 "yyy" 的节点
    operator: In
    values: ["xxx","yyy"]
  - key: nodeenv              # 匹配标签的 key 为 nodeenv,且 value 大于 "xxx" 的节点
    operator: Gt
    values: "xxx"

接下来首先演示一下 requiredDuringSchedulingIgnoredDuringExecution

创建 pod-nodeaffinity-required.yaml,内容如下

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeaffinity-required
  namespace: zouzou
spec:
  containers:
  - name: nginx
    image: nginx:1.14
  affinity:  # 亲和性设置
    nodeAffinity: # 设置 node 亲和性
      requiredDuringSchedulingIgnoredDuringExecution: # 硬限制,没有满足就会失败
        nodeSelectorTerms: # node 选择器,可以有多个
        - matchExpressions: # 匹配标签
          - key: nodeenv # 标签的 key 要为 nodeenv
            operator: In  # 操作符,在里面
            values: ["xxx","yyy"] # 值在["xxx","yyy"]中的标签

创建 pod

#  创建 pod
kubectl create -f pod-nodeaffinity-required.yaml

查看 pod 和 pod 的 event

# 查看 pod ,发现 pod 没有调度到节点上,因为 nodeenv 的值没有 xxx 或者 yyy,而且是硬限制
[root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeaffinity-required -n zouzou -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod-nodeaffinity-required   0/1     Pending   0          81s   <none>   <none>   <none>           <none>
# 从 event 可以看到,调度失败,有三个 node 节点,但是没有满足标签选择器的 node
[root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-required -n zouzou
Name:         pod-nodeaffinity-required
Namespace:    zouzou
Priority:     0
Node:         <none>
Labels:       <none>
......
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  104s  default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.
  Warning  FailedScheduling  30s   default-scheduler  0/3 nodes are available: 3 node(s) didn't match node selector.

从上面我们可以看出,硬限制当没有匹配的标签时,会调度失败。因为我们两个 node 节点,只有 nodeenv=pro 和 nodeenv=test 的节点,没有 nodeenv=xxx 或者 nodeenv=yyy 的节点

接下来,我们删除 pod,把 yyy 改为 pro,因为 nodeenv=pro 是存在的

# 删除 pod
kubectl delete -f pod-nodeaffinity-required.yaml

修改后在创建 pod

# 创建 pod
kubectl create -f pod-nodeaffinity-required.yaml

查看 pod

# 可以看到,pod 分配给了 dce-10-6-215-190 的节点上,并成功运行了
[root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeaffinity-required -n zouzou -o wide
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE               NOMINATED NODE   READINESS GATES
pod-nodeaffinity-required   1/1     Running   0          17s   172.29.190.143   dce-10-6-215-190   <none>           <none>
# 从 event 里,也可以看出来,是成功调度的
[root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-required -n zouzou
Name:         pod-nodeaffinity-required
Namespace:    zouzou......
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  24s   default-scheduler  Successfully assigned zouzou/pod-nodeaffinity-required to dce-10-6-215-190
  Normal  Pulled     21s   kubelet            Container image "nginx:1.14" already present on machine
  Normal  Created    21s   kubelet            Created container nginx
  Normal  Started    20s   kubelet            Started container nginx

接下来再演示一下 requiredDuringSchedulingIgnoredDuringExecution

创建 pod-nodeaffinity-preferred.yaml,内容如下

apiVersion: v1
kind: Pod
metadata:
  name: pod-nodeaffinity-preferred
  namespace: zouzou
spec:
  containers:
  - name: nginx
    image: nginx:1.14
  affinity:  # 亲和性设置
    nodeAffinity: # 设置 node 亲和性
      preferredDuringSchedulingIgnoredDuringExecution: # 软限制,没有匹配的标签也会分配给某个 node
      - weight: 1 # 权重
        preference: # 一个节点选择器项,与相应的权重相关联
          matchExpressions:  # 匹配标签
          - key: nodeenv # 标签的 key 要为 nodeenv
            operator: In  # 操作符,在里面
            values: ["xxx","yyy"] # 匹配 env 的值在["xxx","yyy"]中的标签(当前环境没有)

创建 pod

kubectl create -f pod-nodeaffinity-preferred.yaml

查看 pod 和 pod event

# 可以看到,成功分配给了 dce-10-6-215-200 的节点上
[root@dce-10-6-215-215 tmp]# kubectl get pod pod-nodeaffinity-preferred -n zouzou -o wide
NAME                         READY   STATUS    RESTARTS   AGE   IP              NODE               NOMINATED NODE   READINESS GATES
pod-nodeaffinity-preferred   1/1     Running   0          53s   172.29.34.238   dce-10-6-215-200   <none>           <none>
# 从 event 中也可以看出,pod 是调度成功的
[root@dce-10-6-215-215 tmp]# kubectl describe pod pod-nodeaffinity-preferred -n zouzou
Name:         pod-nodeaffinity-preferred
Namespace:    zouzou
Priority:     0
Node:         dce-10-6-215-200/10.6.215.200
Start Time:   Sat, 16 Apr 2022 11:45:15 +0800
......
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  66s   default-scheduler  Successfully assigned zouzou/pod-nodeaffinity-preferred to dce-10-6-215-200
  Normal  Pulled     63s   kubelet            Container image "nginx:1.14" already present on machine
  Normal  Created    63s   kubelet            Created container nginx
  Normal  Started    62s   kubelet            Started container ngin

从上面的结果可以看出,软限制,当没有匹配到对应的标签时,也不会调度失败,会根据算法分配给合适的节点

NodeAffinity规则设置的注意事项:

  • 如果同时定义了 nodeSelector 和 nodeAffinity,那么必须两个条件都得到满足,Pod 才能运行在指定的 Node 上
  • 如果 nodeAffinity 指定了多个 nodeSelectorTerms,那么只需要其中一个能够匹配成功即可
  • 如果一个 nodeSelectorTerms 中有多个 matchExpressions ,则一个节点必须满足所有的才能匹配成功
  • 如果一个 pod 所在的 Node 在 Pod 运行期间其标签发生了改变,不再符合该 Pod 的节点亲和性需求,则系统将忽略此变化

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
Kubernetes 监控 调度
Kubernetes Pod调度:从基础到高级实战技巧
Kubernetes Pod调度:从基础到高级实战技巧
209 0
|
11天前
|
Kubernetes 网络协议 调度
kubernetes最小调度单元pod详解(二)
kubernetes最小调度单元pod详解(二)
|
11天前
|
Kubernetes 应用服务中间件 调度
kubernetes最小调度单元pod详解(一)
kubernetes最小调度单元pod详解(一)
|
1月前
|
存储 Kubernetes 调度
K8s Pod亲和性、污点、容忍度、生命周期与健康探测详解(下)
本文全面探讨了Kubernetes集群中Pod的四种关键机制——Pod亲和性、污点(Taints)、容忍度(Tolerations)、生命周期以及健康探测,为读者提供了深入理解并有效应用这些特性的指南。
|
2月前
|
Kubernetes 网络安全 调度
容器服务ACK常见问题之容器服务ACK的eci调度卡住如何解决
容器服务ACK(阿里云容器服务 Kubernetes 版)是阿里云提供的一种托管式Kubernetes服务,帮助用户轻松使用Kubernetes进行应用部署、管理和扩展。本汇总收集了容器服务ACK使用中的常见问题及答案,包括集群管理、应用部署、服务访问、网络配置、存储使用、安全保障等方面,旨在帮助用户快速解决使用过程中遇到的难题,提升容器管理和运维效率。
|
5月前
|
Kubernetes Cloud Native 调度
云原生|kubernetes |一文带你搞懂pod调度策略,驱逐策略,污点、容忍调度
云原生|kubernetes |一文带你搞懂pod调度策略,驱逐策略,污点、容忍调度
288 0
|
5月前
|
Kubernetes Cloud Native 调度
k8s学习-污点和容忍(概念、模版、创建、删除)
k8s学习-污点和容忍(概念、模版、创建、删除)
47 0
|
13天前
|
运维 Kubernetes 监控
Kubernetes 集群的持续性能优化实践
【4月更文挑战第26天】 在动态且不断增长的云计算环境中,维护高性能的 Kubernetes 集群是一个挑战。本文将探讨一系列实用的策略和工具,旨在帮助运维专家监控、分析和优化 Kubernetes 集群的性能。我们将讨论资源分配的最佳实践,包括 CPU 和内存管理,以及集群规模调整的策略。此外,文中还将介绍延迟和吞吐量的重要性,并提供日志和监控工具的使用技巧,以实现持续改进的目标。
|
1天前
|
Kubernetes Java API
Kubernetes详解(三)——Kubernetes集群组件
Kubernetes详解(三)——Kubernetes集群组件
9 1
|
6天前
|
运维 监控 Kubernetes
Kubernetes 集群的监控与维护策略
【5月更文挑战第4天】 在当今微服务架构盛行的时代,容器化技术已成为软件开发和部署的标准实践。Kubernetes 作为一个开源的容器编排平台,因其强大的功能和灵活性而广受欢迎。然而,随着 Kubernetes 集群规模的扩大,集群的监控和维护变得日益复杂。本文将探讨 Kubernetes 集群监控的重要性,分析常见的监控工具,并提出一套有效的集群维护策略,以帮助运维人员确保集群的健康运行和高可用性。
37 10