7、高级调度任务

news/2024/7/4 10:42:27/文章来源:https://www.cnblogs.com/ggbaooo/p/18277294

七、高级调度任务、污点与容忍、亲和力(Affinity)

1. Job

1.1 Job概述

Job 是一个资源对象,负责处理任务(即仅执行一次的任务,直到任务完成),并将继续重试 Pod 的执行,它保证批处理任务的一个或多个 Pod 直到指定数量的 Pod 成功终止。

  • Job 跟踪记录成功完成的 Pod 个数, 当数量达到指定的成功个数阈值时,任务(即 Job)结束。
  • 删除 Job 的操作会清除所创建的全部 Pod。
  • 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。

1.2 使用Job

创建一个Job的yaml文件

[root@k8s-master01 job]# cat /yaml/job/test-job.yaml
apiVersion: batch/v1
kind: Job
metadata:labels:job-name: echoname: echonamespace: default
spec:#suspend: true # 1.21+ 开启后不会自动进行。#ttlSecondsAfterFinished: 100 #Job在执行结束之后(状态为completed或 Failed)自动清理。设置为0表示执行结束立即删除,不设置则不会清除,需要开启TTLAfterFinished特性。backoffLimit: 2  #如果任务执行失败,失败多少次后不再执行。completions: 5   #有多少个Pod执行成功,认为任务是成功的。如果为空默认和parallelism数值一样。parallelism: 3   #并行执行任务的数量,如果parallelism数值大于未完成任务数,只会创建未完成的数量; 比如completions是4,并发是3,第一次会创建3个Pod执行任务, 第二次只会创建1个Pod执行任务。template:spec:containers:- command:- echo- Hello, Jobname: echoimage: registry.cn-beijing.aliyuncs.com/dotbalo/busyboximagePullPolicy: IfNotPresentresources: {}restartPolicy: Never

创建并查看任务执行情况

image-20240503005717956

查看Job的详细信息

image-20240503005831857

Job 对象在创建后,它的 Pod 模板,被自动加上了一个 controller-uid=< 一个随机字符串 > 这样的 Label 标签,而这个 Job 对象本身,则被自动加上了这个 Label 对应的 Selector,从而 保证了 Job 与它所管理的 Pod 之间的匹配关系。而 Job 控制器之所以要使用这种携带了 UID 的 Label,就是为了避免不同 Job 对象所管理的 Pod 发生重合。

1.3 Job如何终止与清理

Job 完成时不会再创建新的 Pod,不过已有的 Pod 通常也不会被删除。 保留这些 Pod 使得你可以查看已完成的 Pod 的日志输出,以便检查错误、警告或者其它诊断性输出。

Job 完成时 Job 对象也一样被保留下来,这样你就可以查看它的状态。 在查看了 Job 状态之后删除老的 Job 的操作留给了用户自己。 你可以使用 kubectl 来删除 Job, 当使用 kubectl 来删除 Job 时,该 Job 所创建的 Pod 也会被删除。

默认情况下,Job 会持续运行,除非某个 Pod 失败(restartPolicy=Never) 或者某个容器出错退出(restartPolicy=OnFailure)。 这时,Job 基于前述的 spec.backoffLimit 来决定是否以及如何重试。 一旦重试次数到达 .spec.backoffLimit 所设的上限,Job 会被标记为失败, 其中运行的 Pod 都会被终止。

终止 Job 的另一种方式是设置一个活跃期限。 你可以为 Job 的 .spec.activeDeadlineSeconds 设置一个秒数值。 该值适用于 Job 的整个生命期,无论 Job 创建了多少个 Pod。 一旦 Job 运行时间达到 activeDeadlineSeconds 秒,其所有运行中的 Pod 都会被终止, 并且 Job 的状态更新为 type: Failedreason: DeadlineExceeded

Tips:Job 的 .spec.activeDeadlineSeconds 优先级高于其 .spec.backoffLimit 设置。

2. CronJob

2.1 CronJob概述

CronJob 其实就是在 Job 的基础上加上了时间调度,我们可以在给定的时间点运行一个任务,也可以周期性地在给定时间点运行。这个实际上和我们 Linux 中的 crontab 就非常类似了。

# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系统上,7 也是星期日)
# │ │ │ │ │                          或者是 sun,mon,tue,web,thu,fri,sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *步长可被用于范围组合。范围后面带有 /<数字> 可以声明范围内的步幅数值。 例如,0-23/2 可被用在小时字段来声明命令在其他数值的小时数执行 (V7 标准中对应的方法是 0,2,4,6,8,10,12,14,16,18,20,22)。 步长也可以放在通配符后面,因此如果你想表达 “每两小时”,就用 */2 。

2.2 使用CronJob

创建一个 CronJob 的yaml文件

[root@k8s-master01 job]# cat /yaml/job/cronjob.yaml
apiVersion: batch/v1  #batch/v1beta1 1.21以上 batch/v1
kind: CronJob
metadata:labels:run: helloname: hellonamespace: default
spec:concurrencyPolicy: Allow#Allow:允许同时运行多个任务。#Forbid:不允许并发运行,如果之前的任务尚未完成,新的任务不会被创建。#Replace:如果之前的任务尚未完成,新的任务会替换的之前的任务。failedJobsHistoryLimit: 1 #应保留多少已失败的任务,0则不保留。jobTemplate:metadata:spec:template:metadata:labels:run: hellospec:containers:- args:- /bin/sh- -c- date; echo Hello from the Kubernetes clusterimage: nginx:1.14.2imagePullPolicy: IfNotPresentname: helloresources: {}restartPolicy: OnFailuresecurityContext: {}schedule: '*/1 * * * *'  #调度周期,和Linux一致,分别是分时日月周。successfulJobsHistoryLimit: 3  #应保留多少已完成的任务,0则不保留。suspend: false  #如果设置为true,则暂停后续的任务,默认为false。
image-20240503011734802

现在将cronjob.yaml中的suspend: false改为suspend: true,重新更新一下CronJob资源,能看到下图的任务暂停情况。

image-20240503011948153

2.3 CronJob的终止与清理

删除CronJob即可。

img

3. 初始化容器

3.1 初始化容器概述

初始化容器(Init容器),顾名思义,初始化容器是用来进行初始化操作的。很多情况下,程序的启动需要依赖各类配置、资源,但是又不能继承在原有的启动命令或者镜像当中,因为程序的镜像可能并没有加载配置命令,此时InitContainer就起到了很大的作用。

初始化容器在Pod内的应用容器启动之前运行,可以包括一些应用镜像中不存在的实用工具和安装脚本,用以在程序启动时进行初始化,比如创建文件、修改内核参数、等待依赖程序启动等。

3.2 初始化容器作用

在生产环境中,为了应用的安全和优化镜像的体积,业务镜像一般不会安装高危工具和并不常用的运维工具,比如curl、sed、awk、python或dig等,同时建议使用非root用户去启动容器。但是某些应用启动之前可能需要检测依赖的服务有没有成功运行,或者需要高权限去修改一些系统级配置,而这些检测或配置更改都是一次性的,所以在制作业务镜像时没有必要为了一次配置的变更去安装一个配置工具,更没有必要因为使用一次高权限而把整个镜像改成以root身份运行。

Init容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:

  • Init容器可以包含安装过程中应用容器中不存在的实用工具或个性化代码。
  • Init容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。
  • Init容器可以以root身份运行,执行一些高权限命令。
  • Init容器相关操作执行完成后就会退出,不会给业务容器带来安全隐患。

由于Init容器必须在应用容器启动之前运行完成,因此Init容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足一组先决条件,Pod内的所有应用容器才会并行启动。

3.3 初始化容器的特点

每个Pod中可以包含多个容器,同时Pod也可以有一个或多个先于应用容器启动的Init容器,在Pod定义中和containers同级,按顺序逐个执行,当所有的Init容器运行完成时,Kubernetes才会启动Pod内的普通容器。

Init容器与普通的容器非常像,除了如下几点:

  • 它们总是运行到完成。
  • 上一个运行完成才会运行下一个。
  • 如果Pod的Init容器失败,Kubernetes会不断地重启该Pod,直到Init容器成功为止,但是Pod对应的restartPolicy值为Never,Kubernetes不会重新启动Pod。

Tips:Init容器不支持lifecycle(管理容器的整个生命周期)、livenessProbe(存活探针)、readinessProbe(就绪探针)和startupProbe(启动探针),因为它们必须在Pod就绪之前运行完成。

3.4 使用初始化容器

初始化容器的常用案例:

  • 某些服务需要依赖其他组件才能启动,比如后端应用需要数据库启动之后,应用才能正常启动,所以此时需要检测数据库实例是否正常,待数据库可以正常使用时,再启动后端应用。
  • 利用一个git镜像进行拉取代码到指定目录中去。
  • 对某个挂载目录进行初始化授予权限。
  • 运行多个初始化容器,比如一个应用需要等待该应用所在Namespace的一个Service对应的Pod启动,也需要一个DB的Service启动,当两个InitContainer都成功后,才可以启动业务应用容器。

初始化容器创建文件,然后主容器运行后可以看到此文件。

[root@k8s-master01 init]# cat /yaml/init/init.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: test-initname: test-init
spec:replicas: 3selector:matchLabels :app: test-inittemplate:metadata:labels:app: test-initspec:volumes:- name: dataemptyDir: {}initContainers :- command:- sh- -c- touch /mnt/test-init.txtimage: nginx:1.14.2imagePullPolicy: IfNotPresentname: init-touchvolumeMounts :- name: datamountPath: /mnt- command:- sh- -c- for i in `seq 1 100`; do echo $i; sleep 1; doneimage: nginx:1.14.2imagePullPolicy: IfNotPresentname: echocontainers:- image: nginx:1.14.2imagePullPolicy: IfNotPresentname: test-initvolumeMounts :- name: datamountPath: /mnt

创建并查看Pod状态

image-20240503013528994

看到初始化容器事件的进行,-c 进入到eco容器中就能看到还有任务在进行。

image-20240503013438760

等到初始化容器都完成后,进入到Pod中查看初始化容器的操作有没有进行,没问题!

image-20240503013711652

4. 污点(Taint)与容忍(Toleration)

4.1 污点与容忍基本概念

污点(Taint)作用在节点上,能够使节点排斥一类特定的Pod,也就是不能“兼容”该节点的污点的Pod。容忍(Toleration)是应用于 Pod 上的,容忍允许调度器调度带有对应污点的 Pod。 容忍允许调度但并不保证调度。

污点和容忍相互配合,可以用来避免 Pod 被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的 Pod,该节点不会接受任何不能容忍该污点的 Pod。

4.2 污点使用场景

污点一般用于调度Pod部署的节点,常用调度场景如下:

  • Pod不能部署在Master节点上

  • 某个节点需要维护/升级,需要将该节点上的Pod迁移到其他节点

  • GPU的Pod只能部署在GPU服务器上

  • Pod不能部署在没有完成可用性测试的节点上

  • 等等场景!

4.3 污点种类

污点分为外置污点和内置污点,主要说明如下:

  • 外置污点:人工使用Taint命令给节点打上的污点
  • 内置污点:系统自带的污点

当某种条件为真时,节点控制器会自动给节点添加一个污点。当前内置的污点包括:

  • node.kubernetes.io/not-ready:节点未准备好。这相当于节点状况 Ready 的值为 "False"。
  • node.kubernetes.io/unreachable:节点控制器访问不到节点. 这相当于节点状况 Ready 的值为 "Unknown"。
  • node.kubernetes.io/memory-pressure:节点存在内存压力。
  • node.kubernetes.io/disk-pressure:节点存在磁盘压力。
  • node.kubernetes.io/pid-pressure: 节点的 PID 压力。
  • node.kubernetes.io/network-unavailable:节点网络不可用。
  • node.kubernetes.io/unschedulable: 节点不可调度。
  • node.cloudprovider.kubernetes.io/uninitialized:如果 kubelet 启动时指定了一个“外部”云平台驱动, 它将给当前节点添加一个污点将其标志为不可用。在 cloud-controller-manager 的一个控制器初始化这个节点后,kubelet 将删除这个污点。

在节点被驱逐时,节点控制器或者 kubelet 会添加带有 NoExecute 效果的相关污点。 如果异常状态恢复正常,kubelet 或节点控制器能够移除相关的污点,但是被驱逐的Pod需要手动进行删除。

4.4 使用污点

查节点有哪些污点

#格式:kubectl describe node 节点名称 | grep Taints     筛选污点,最好再加-A 10 20,查看更多污点。# kubectl describe node k8s-master01 | grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule# kubectl get node k8s-master01 -o go-template --template {{.spec.taints}}
[map[effect:NoSchedule key:node-role.kubernetes.io/master]]

打上污点

#格式:kubectl taint node 节点名称 污点key=污点value:effect规则
kubectl taint nodes k8s-node01 ssd=true:NoSchedule

effect规则:

  • NoSchedule:禁止调度到该节点,已经在该节点上的Pod不受影响。
  • NoExecute:禁止调度到该节点,如果不符合这个污点,会立马被驱逐(或在一段时间后,默认300s,可修改)。
  • PreferNoSchedule:尽量避免将Pod调度到指定的节点上,如果没有更合适的节点,可以部署到该节点。

改污点

#格式:kubectl taint node 节点名称 污点key=污点value:effect规则 --overwrite
kubectl taint nodes k8s-node01 ssd=false:NoSchedule --overwrite

删除污点

#格式:kubectl taint node 节点名称 污点key=污点value:effect规则-
kubectl taint nodes k8s-node01 ssd=false:NoSchedule-#格式:kubectl taint node 节点名称 污点key:effect规则-
kubectl taint nodes k8s-node01 ssd:NoSchedule-#格式:kubectl taint node 节点名称 污点key- (删除所有该同样的key)
kubectl taint nodes k8s-node01 ssd-

4.5 容忍Toleration配置

Kubernetes 处理多个 Taint 和 Toleration 的过程就像一个过滤器:从一个节点的所有Taint开始遍历,过滤掉那些 Pod 中存在与之相匹配的 Toleration 的 Taint,余下未被过滤的 Taint 的 effect 值决定了 Pod 是否会被分配到该节点,特别是以下情况:

  • 如果未被过滤的Taint中存在一个以上 effect 值为 NoSchedule 的 Taint,则 Kubernetes 不会将 Pod 分配到该节点。(如果 Pod 已经在节点上运行了,无影响)
  • 如果未被过滤的 Taint 中不存在 effect 值为 NoExecute 的 Taint,但是存在 effect 值为 PreferNoSchedule 的 Taint,则 Kubernetes 会尝试将 Pod 分配到该节点。
  • 如果未被过滤的Taint中存在一个以上 effect 值为 NoExecute 的 Taint,则 Kubernetes 不会将 Pod 分配到该节点(如果Pod还未在节点上运行),或者将 Pod 从该节点驱逐(如果Pod已经在节点上运行)。

Tips:Node上的污点Taint相当于锁头,容忍Toleration相当于钥匙,要是Taint有三个污点,Toleration只有两个与之对应的配置,那就相当于有一个锁头钥匙没法开,此时就会看该污点所配置的规则。

4.5.1 完全匹配

tolerations:
- key: "taintKey"operator: "Equal"value: "taintValue"effect: "NoSchedule"

4.5.2 不完全匹配

tolerations:
- key: "taintKey"operator: "Exists"effect: "NoSchedule"

4.5.3 大范围匹配(不推荐key为内置Taint)

容忍中未定义 effect 但是定义了 key,Kubernetes 认为此容忍匹配所有 effect

- key: "taintKey"operator: "Exists"

4.5.4 匹配所有(不推荐)

容忍中未定义 key 但是定义了 operator 为 Exists,Kubernetes 认为此容忍匹配所有的污点

tolerations:
- operator: "Exists"

4.5.5 自定义驱逐时间

#自定义驱逐时间(默认300s),下面配置示例是3600秒
tolerations:
- key: "key1"operator: "Equal"value: "value1"effect: "NoExecute"tolerationSeconds: 3600

当满足如下条件时,Kubernetes 认为容忍和污点匹配:

  • 键(key)相同

  • 效果(effect)相同

  • 污点operator为:

    • Exists (此时污点中不应该指定 value
    • 或者 Equal (此时容忍的 value 应与污点的 value 相同)

如果不指定 operator,则其默认为 Equal

4.6 污点与容忍使用示例

以下所有示例只是练习污点与容忍的使用,生产环境配置不合理。

4.6.1 将Pod部署在Master节点

此时所有的Master都有这么一个污点 node-role.kubernetes.io/master:NoSchedule,只有key和value组

img

如果要想Pod运行在这些节点上,就得给它配一把容忍 “钥匙” 开这个污点 “锁”,那Pod的yaml配置如下:


apiVersion: v1
kind: Pod
metadata:name: nginxlabels:env: test
spec:containers:- name: nginximage: nginx:1.14.2imagePullPolicy: IfNotPresent#匹配该key即可tolerations:- key: "node-role.kubernetes.io/master"operator: "Exists"

此时还不一定会调度到Master节点上呢,因为Node节点都没有污点,此时给所有Node节点打上下面这条污点,看最终创建后Pod在哪里。

kubectl taint node Node节点名称 nodeploy:NoSchedule

都在Master节点上了

img

4.6.2 禁止新Pod再部署到Master

之前所有节点的污点都不变,此时向所有Master添加一条新的污点。

kubectl taint node Master节点名称 nodeploy=master:NoSchedule

已经在运行的Pod,不受新污点(规则为NoSchedule)的影响,但此时已经Master和Node节点都不允许调度。Master节点新添加的污点 “锁” ,没有容忍 “钥匙” 可以开了。

img

Tips:测试完上面两个实验,记得删除全部污点以及所有Pod。

4.6.3 将容器驱逐

创建一个新Pod,然后查看它在哪个节点上。

[root@k8s-master01 taint]# cat deployment-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: deploy-nginx
spec:replicas: 5selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: deploy-nginximage: nginx:1.14.2ports:- containerPort: 80tolerations:- key: "ssd"value: "false"effect: "NoExecute"operator: "Equal"

node01、02、03、04上都有,比如现在Node04需要进行升级,此时配置污点让容器驱逐。

img
#在k8s-node04上进行
kubectl taint node k8s-node04 ssd=true:NoExecute

img

如果要驱逐到一个节点呢,全部在Node01,那么就在Node02、03上进行

kubectl taint node k8s-node02 ssd=true:NoExecute
kubectl taint node k8s-node03 ssd=true:NoExecute

img

Tips:到此删除deployment,同时将所有新添加的污点进行删除,生产环境中不大建议使用污点与容忍来控制!

5. 亲和力(Affinity)

亲和力(Affinity)是 Kubernetes 中的一种机制,用于指定 Pod 与其他资源(如节点、Pod 或标签)之间的关联性和偏好。

亲和力定义了 Pod 对其他资源的偏好和互动方式,以便在调度过程中进行合适的匹配。通过使用亲和力规则,可以将 Pod 调度到满足特定条件的节点上,或者将 Pod 与其他相关的 Pod 进行关联,以实现特定的调度需求和业务需求。

可以标明某规则是“软需求”或者“偏好”,这样调度器在无法找到匹配节点时仍然调度该Pod。

Tips:nodeSelector 只能选择拥有所有指定标签的节点!

污点是排斥,即宿主机不允许某些Pod部署到“自己身上”,而亲和力表示Pod需要和指定的Pod或节点部署在一起,当然也可以进行互斥。

5.1 亲和力策略

亲和性调度可以分成软策略和硬策略两种方式:

  • 软策略就是如果现在没有满足调度要求的节点的话,Pod 就会忽略这条规则,继续完成调度过程,说白了就是满足条件最好了,没有的话也无所谓。
  • 硬策略就比较强硬了,如果没有满足条件的节点的话,就不断重试直到满足条件为止,简单说就是你必须满足我的要求,不然就不干了。

亲和性和反亲和性都有这两种规则可以设置:

  • 软策略 preferredDuringSchedulingIgnoredDuringExecution
  • 硬策略requiredDuringSchedulingIgnoredDuringExecution

5.2 亲和力分类

Affinity根据功能的不同分为节点亲和力(Node Affinity)和Pod亲和力(Pod Affinity)。

  • 每种亲和力还有两种不同的“实现方法”,即必须和尽量。
  • 亲和力又分为软亲和力(非强制性)和硬亲和力(强制性)。
  • Pod之间可以相互排斥,也可以相互吸引,所以Pod亲和力又分为PodAffinity(Pod亲和力)和PodAntiAffinity(Pod反亲和力)。

img

5.3 亲和力配置详解

5.3.1 默认规则

如果同时指定了NodeSelector和NodeAffinity,需要两者都满足才能被调度。

如果配置了多个NodeSelectorTerms,满足其一即可调度到指定的节点上。

如果配置了多个MatchExpressions,需要全部满足才能调度到指定的节点上。

如果删除了被调度节点上的标签,Pod不会被删除,也就是说亲和力配置只有在调度的时候才会起作用。

5.3.2 Node硬亲和力规则

requiredDuringSchedulingIgnoredDuringExecution:硬亲和力配置

#与containers同级
affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- k8s-node01- k8s-node02
#该配置是匹配有label标签 key是kubernetes.io/hostname,且values是k8s-node01、k8s-node02之一即可。

nodeSelectorTerms:节点选择器配置,可以配置多个matchExpressions(满足其一)

matchExpressions:可以配置多个key、value类型的选择器(都需要满足),其中values可以配置多个 (满足其一)

operator:标签匹配方式

  • In:相当于key = value的形式
  • NotIn:相当于key != value的形式
  • Exists:节点存在label的key为指定的值即可,不能配置values字段
  • DoesNotExist:节点不存在label的key为指定的值即可,不能配置values字段
  • Gt:大于value指定的值
  • Lt:小于value指定的值

5.3.3 Node软亲和力规则

preferredDuringSchedulingIgnoredDuringExecution:软亲和力配置

#与containers同级
affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 3preference:matchExpressions:- key: SSDoperator: Invalues:- "true"- weight: 2preference:matchExpressions:- key: HDDoperator: Invalues:- "true"
#在pod副本为40情况下,会有几率调度到HDD=true这个标签的节点上,主要还得看SSD节点的负载,由调度器去权重!

weight:软亲和力的权重,权重越高优先级越大,范围1-100

preference:软亲和力配置项,和weight同级,可以配置多个,可以配置多个key、value类型的选择器(都需要满足),其中values可以配置多个 (满足其一)

operator:标签匹配方式

  • In:相当于key = value的形式
  • NotIn:相当于key != value的形式
  • Exists:节点存在label的key为指定的值即可,不能配置values字段
  • DoesNotExist:节点不存在label的key为指定的值即可,不能配置values字段
  • Gt:大于value指定的值
  • Lt:小于value指定的值

5.3.4 Pod亲和力、反亲和力规则

#Pod亲和力(软、硬)
affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: key名称operator: Invalues:- value值podAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 80podAffinityTerm:labelSelector:matchExpressions:- key: key名称operator: Invalues:- value值

labelSelector:Pod选择器配置,可以配置多个

matchExpressions:可以配置多个key、value类型的选择器(都需要满足),其中values可以配置多个 (满足其一)

weight:软亲和力的权重,权重越高优先级越大,范围1-100

operator:标签匹配方式(Pod亲和力、反亲和力都无Gt、Lt)

  • In:相当于key = value的形式
  • NotIn:相当于key != value的形式
  • Exists:节点存在label的key为指定的值即可,不能配置values字段
  • DoesNotExist:节点不存在label的key为指定的值即可,不能配置values字段
#Pod反亲和力(软、硬)
affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: key名称operator: Invalues:- value值topologyKey: kubernetes.io/hostnamepodAntiAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 80podAffinityTerm:labelSelector:matchExpressions:- key: key名称operator: Invalues:- value值topologyKey: kubernetes.io/hostname

labelSelector:Pod选择器配置,可以配置多个

matchExpressions:可以配置多个key、value类型的选择器(都需要满足),其中values可以配置多个 (满足其一)

weight:软亲和力的权重,权重越高优先级越大,范围1-100

topologyKey:匹配的拓扑域的key,也就是节点上label的key,key和value相同的为同一个域,用于标注不同的机房和地区。默认填kubernetes.io/hostname,也就是在每个节点上去进行Pod的反亲和力。

operator:标签匹配方式(Pod亲和力、反亲和力都无Gt、Lt)

  • In:相当于key = value的形式

  • NotIn:相当于key != value的形式

  • Exists:节点存在label的key为指定的值即可,不能配置values字段

  • DoesNotExist:节点不存在label的key为指定的值即可,不能配置values字段

5.4 常用方案

5.4.1 同一个应用部署至不同的Node节点

在使用Kubernetes时,一般都会有很多节点运行容器,此时可以使用Pod反亲和力将同一个应用部署到不同的节点上,达到更高的可用率,以免同一个应用部署到相同的宿主机带来的风险。

编写yaml文件

[root@k8s-master01 ~]# cat /yaml/affinity/podAntiAffinity-node.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: nginxname: nginx
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- nginxtopologyKey: kubernetes.io/hostnamecontainers:- image: nginx:1.14.2imagePullPolicy: IfNotPresentname: nginx

此时创建一个Pod为3副本的Deployment,查看Pod情况,分别在3个node节点上创建。

image-20240504232026652

进行更改副本数,新增的两个副本就调度分配不了了。因为topologyKey有三个域(也就是3个Node节点)都分配了Pod,yaml配置了反亲和力且Pod的label是app=pod,匹配上了,无法在这些Node节点上创建。

image-20240504232623844

报错信息:0/6个节点可用:3个节点具有pod无法容忍的污点{node-role.kubernetes.io/master:},4个节点与pod反亲和规则不匹配。

image-20240504232743034

Tips:实验完成,删除Deployment。

5.4.2 尽量调度到高配置Node节点

例如目前有四台Node节点,有两台节点是配置了SSD高速硬盘,两台是配置了传统的HDD机械硬盘。那想让它们优先部署在SSD的节点,但也不排除部署在HDD节点,可以通过使用节点软亲和力来配置。

编写yaml文件

[root@k8s-master01 affinity]# cat node-affinity.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: node-nginxname: node-affinity-nginx
spec:replicas: 6selector:matchLabels:app: node-nginxtemplate:metadata:labels:app: node-nginxspec:affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 3preference:matchExpressions:- key: SSDoperator: Invalues:- "true"- weight: 2preference:matchExpressions:- key: HHDoperator: Invalues:- "true"containers:- name: node-affinity-nginximage: nginx:1.14.2imagePullPolicy: IfNotPresentports:- containerPort: 80

配置label标签

kubectl label nodes k8s-node01 k8s-node02 HDD=true
kubectl label nodes k8s-node03 SSD=true

此时创建一个Pod为6副本的Deployment,查看Pod情况,此时都调度在Node03、04节点上,应该是该节点负载不高。

image-20240504235901099

更改副本数为40,再查看Pod情况,已经有Pod调度在Node01、02上来,再进行筛选统计一下。

kubectl scale deployment node-affinity-nginx --replicas=40

image-20240504235007557

image-20240505001152845

5.4.3 同一个应用多区域部署

拓扑域,主要针对宿主机,相当于对宿主机进行区域的划分。用label进行判断,不同的key和不同的value是属于不同的拓扑域,同一个key和不同的value属于不同一个区域。

例如有多地机房通过专线互联,一个集群下的节点分别在不同的区域。项目上线时,想把Pod分布在不同的区域里,且同一区域不能重复部署该项目。可以通过label标注各地地区节点,同时使用Pod的反亲和力和topologyKey来实现。

先删除Master节点上的污点来增加可部署的节点

kubectl taint node k8s-master01 node-role.kubernetes.io/master:NoSchedule-
kubectl taint node k8s-master02 node-role.kubernetes.io/master:NoSchedule-
kubectl taint node k8s-master03 node-role.kubernetes.io/master:NoSchedule-[root@k8s-master01 affinity]# kubectl describe node | grep Taint
Taints:             <none>
Taints:             <none>
Taints:             <none>
Taints:             <none>
Taints:             <none>
Taints:             <none>
Taints:             <none>

根据标签区分区域,其中:
k8s-master01、k8s-master02 为南山区,region=nanshan

k8s-master03、k8s-node01 为罗湖区,region=luohu

k8s-node02、k8s-node03 为龙岗区,region=longgang

kubectl label node k8s-master01 k8s-master02 region=nanshan
kubectl label node k8s-master03 k8s-node01 region=luohu
kubectl label node k8s-node02 k8s-node03 region=longgang

image-20240505001804683

编写yaml文件

[root@k8s-master01 affinity]# cat web-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: web-nginxname: web-nginx
spec:replicas: 1selector:matchLabels:app: web-nginxtemplate:metadata:labels:app: web-nginxspec:affinity:podAntiAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: appoperator: Invalues:- web-nginxtopologyKey: regioncontainers:- image: nginx:1.14.2imagePullPolicy: IfNotPresentname: web-nginx

此时创建一个Pod为1副本的Deployment,查看Pod情况,部署在node02,也就是罗湖区。

image-20240505003433095

再依次增加到4副本,第二次部署在node03,是龙岗区。第三次部署在master01上,是南山区。增加到第四个副本时,就已经是Pending了,因为三个区域已经部署过了,此时在各区域内反亲和力产生了作用,不能在同一区域继续部署了。

kubectl scale deployment web-nginx --replicas=

image-20240505003649931

注:本篇学习笔记内容参考杜宽的《云原生Kubernetes全栈架构师》,视频、资料文档等,大家可以多多支持!还有YinJayChen语雀、k8s训练营、“我为什么这么菜”知乎博主等资料文档,感谢无私奉献!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8、高级调度准入控制

九、资源配额、资源限制、服务质量Qos 1. 节点可用性延伸 已经从多个维度保障了服务的可用性,比如调度到不同的机器和机房、配置可靠的健康检查等。但是上述措施都是基于应用级别去做的,如果我们的 Kubernetes 集群用来运行容器的节点有了故障,带来的影响是很大的,所以在保…

邀请函 | 极限科技全新搜索引擎 INFINI Pizza 亮相 2024 可信数据库发展大会!

过去一年,在全球 AI 浪潮和国家数据局成立的推动下,数据库产业变革不断、热闹非凡。2024 年,站在中国数字经济产业升级和数据要素市场化建设的时代交汇点上,“2024 可信数据库发展大会” 将于 2024 年 7 月 16-17 日在北京悠唐皇冠假日酒店隆重召开,大会将以 “自主、创新…

debian12 创建本地harbor镜像库

前言harbor是一个docker/podman镜像管理库,可用于存储私人镜像。现将本人在debian12系统搭建harbor镜像库的过程记录下来,留作后续参考。 可以参考github harbor项目给定的安装教程,很详细了:https://goharbor.io/docs/2.11.0/install-config/configure-https/ 正文harbor 镜…

1、Kubernetes基础

一、Kubernetes基础 1. 为什么要用Kubernetes 在业务开始进行容器化时,前期需要容器化的项目可能并不多,涉及的容器也并不多,此时基于Docker容器直接部署至宿主机也能实现自己的需求。但是随着项目越来越多,管理的容器也越来越多,此时使用“裸容器”部署的方式管理起来就显…

一、Kubernetes基础

一、Kubernetes基础 1. 为什么要用Kubernetes 在业务开始进行容器化时,前期需要容器化的项目可能并不多,涉及的容器也并不多,此时基于Docker容器直接部署至宿主机也能实现自己的需求。但是随着项目越来越多,管理的容器也越来越多,此时使用“裸容器”部署的方式管理起来就显…

工创赛总结与展望——概述

开始 我们队是从2023年寒假开始准备的,我是做嵌入式软件的,那时候找了两个队友,机械Z和硬件Q,都是寒假前联系的,准备在寒假多学习一些相关内容,开学开干;寒假时,硬件Q联系不上了,队里缺画板子的,我寒假玩FreeRtos玩一半,开始学习硬件设计;整个寒假没有准备什么和工…

Halcon图像和文件操作

文件操作 dev_get_window (WindowHandle) * 遍历文件夹 list_files (C:/Users/Desktop/halcon deeplearn/Train_images, [files, recursive], Files) * 便利文件夹中的图像文件 list_image_files (C:/Users/Desktop/halcon deeplearn/Train_images/梨, default, [], ImageFiles…

36、k8s-Ingress的使用-搭建ingress-nginx服务和ingress-controller控制器--http代理

1、搭建ingress服务环境(安装ingress-controller控制器)--这里使用nginx做负载均衡 1、创建文件:mkdir /opt/ingresscd /opt/ingress 2、获取ingress-nginx和ingress控制器的yaml文件:##创建ingress-controller控制器的yaml文件wget https://github.com/kubernetes/ingress…

25、k8s-pod的控制器-第四种-DaemonSet(DS)-有几个node就自动创建几个pod

概念:DaemonSet类型的控制器可以保证集群中的每一台(或指定)节点上都运行一个副本、一般适用于日志收集、节点监控场景等、也就是说、如果一个pod 提供的功能是节点级别的(每个节点都需要且只需要一个)、那么这类pod就适合使用DaemonSet类型的控制器创建 DaemonSet的特点…

24、k8s-pod的控制器-第三种-HPA(Horizontal Pod Autoscaler)-自动调整pod的数量

监测pod的使用情况来做调整 概念:HPA可以获取每个pod的利用率、然后和HPA中定义的指标(如cpu、内存等使用情况)进行对比、同时计算出需要伸缩的具体值、最后实现pod数量的调整、其实HPA与之前的Deployment 控制器一样、也属于一种kubernetes资源对象、它通过追踪分析目标pod…

编译安装Haproxy

一、三种软负载均衡器的区别 1、关于三种负载均衡器的性能对比: LVS是基于内核实现的,他的性能最好; 其次是haproxy,最后是nginx 关于三种负载均衡器的代理类型对比: LVS只支持基于ip的四层代理转发,也不支持正则匹配; haproxy和nginx都可以作为四层代理和七层代理,同时…

CentOS7.9部署站点运行

简介 本章节主要讲的是在Linux系统CentOS7.9上去完成.NET Core 6.0软件的安装,确定Linux的版本是x64还是arm64的,然后到.NET Core的官网下载6.0的SDK,并进行安装 步骤 1.进入站点目录 2.运行站点 3.配置 Nginx 站点代理 4.浏览站点 实施 1.进入站点目录[root@ml006 /]# cd /…

三大财务报表之间的勾稽关系

财务须知:三大财务报表之间的勾稽关系是怎样,附合并报表系统 三大财务报表是利润表、资产负债表、现金流量表,财务报表之间有勾稽关系,好比资产负债表是底子,利润表就是外面的面子,而现金流量表就是实实在在的日子,可以通过财务报表看出企业财务经营状况是怎么样,那他们…

MMM高可用配置

目录1.MMM的概述2.MMM的工作原理3.如何实现主主复制 1.MMM的概述 MMM(Master-Master replication manager for MySQL,MySQL主主复制管理器) 是一套支持双主故障切换和双主日常管理的脚本程序。MMM 使用 Perl 语言开发,主要用来监控和管理 MySQL Master-Master (双主)复制…

《Programming from the Ground Up》阅读笔记:p1-p18

《Programming from the Ground Up》学习第1天,p1-18总结,总计18页。 一、技术总结 1.fetch-execute cycle p9, The CPU reads in instructions from memory one at a time and executes them. This is known as the fetch-execute cycle。 2.general-purpose vs special-pu…

SpringMVC-02-什么是SpringMVC

1、概述Spring MVC是Spring Framework的Web开发部分,是基于Java实现MVC的轻量级Web框架。官方文档:https://docs.spring.io/spring-framework/docs/4.3.24.RELEASE/spring-framework-reference/html/ 中文官方文档:https://www.w3cschool.cn/spring_mvc_documentation_lines…

视图控制器UINavigationController的介绍与基本使用

UINavigationController 是 iOS 中用于管理视图控制器层次结构的一个重要组件,通常用于实现基于堆栈的导航。它提供了一种用户界面,允许用户在视图控制器之间进行层次化的导航,例如从列表视图到详细视图。 UINavigationController 的主要功能管理视图控制器堆栈:使用一个堆…

拉普拉斯网格变形实现

因为课题需要,除了RBF还做了一个Laplace网格变形,其他大佬已经把原理写的很详细了,我就简单介绍一下公式,主要还是写写实现过程。过程同样参考了大佬的部分代码,而且实现的时候刚开始敲代码不久,所以有点乱QAQ。 首先,计算离散拉普拉斯坐标,网格上的点vi的拉普拉斯坐标…

文本三剑客之grep和awk

文本三剑客之grep和awk 目录文本三剑客之grep和awk 一、grep命令 grep命令的语法:grep[选项]...查找条件 目标文件命令 作用-m数字 多个匹配只取第一个-v 取反-i 忽略大小写-n 显示匹配的行号-c 统计匹配的行数-o 仅显示匹配到的字符串-A 数字 匹配后几行-B 数字 匹配前几行-C…