k8s-高级调度学习
k8s-高级调度中,定时任务器,污点,容忍,亲和力以及反亲和力的学习记录。
k8s
-高级调度学习
1 CronJob
计划任务
在 k8s
中周期性运行计划任务,与 linux
中的 crontab
相同。换句话说就是提前写好程序命令,然后当CronJob
任务再启动后会按照其设置的时间,定期去执行程序命令。
(1)定期任务时间格式如下。
* * * * *
- - - - -
| | | | |
| | | | +----- 星期中星期几 (0 - 6) (星期天 为0)
| | | +---------- 月份 (1 - 12)
| | +--------------- 一个月中的第几天 (1 - 31)
| +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59
每分钟定时执行一次 * * * * *
每小时定时执行一次 0 * * * *
每天定时执行一次 0 0 * * *
每周定时执行一次 0 0 * * 0
每月定时执行一次 0 0 1 * *
每月最后一天定时执行一次 0 0 L * *
每年定时执行一次 0 0 1 1 *
(2)CroJob
配置如下。jobTemplate
可以换为自己需要执行的命令,此处的jobTemplate
为示例演示。
apiVersion: batch/v1
kind: CronJob # 类型为定时任务
metadata:
name: cron-job-test # 定时任务的名字
spec:
concurrencyPolicy: Allow # 并发调度策略:Allow 允许并发调度,Forbid:不允许并发执行,Replace:如果之前的任务还没执行完,就直接执行新的,放弃上一个任务
failedJobsHistoryLimit: 1 # 保留多少个失败的任务
successfulJobsHistoryLimit: 3 # 保留多少个成功的任务
suspend: false # 是否挂起任务,若为 true 则该任务不会执行
# startingDeadlineSeconds: 30 # 间隔多长时间检测失败的任务并重新执行,时间不能小于 10
schedule: "* * * * *" # 调度策略,此处为每分钟调度一次,由于successfulJobsHistoryLimit为3,所以调度3次
# 以下为编写的程序,在busybox的命令行中进行执行,输出当前日期,并打印Hello from the Kubernetes cluster
jobTemplate:
spec:
template:
spec:
containers:
- name: busybox
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
(3)对以上cronJob
配置进行测试。其命令如下,结果如下如图所示。
# 创建定时任务
kubectl create -f xxx.yaml
# 查看定时任务是否启动成功
kubectl get cj
# 然后在pod中查看,可以发现3次任务的执行记录
kubectl get po
# 利用日志记录,可以观察到每个任务的执行记录
kubectl logs -f xxxx(pod名称)
2 InitContainer
初始化容器
在真正的容器启动之前,先启动 InitContainer
,在初始化容器中完成真实容器所需的初始化操作,完成后再启动真实的容器。就比如,在很多容器启动前都需要进行mysql
的连接配置,此时就可以写一个 InitContainer
,在每次启动容器前都先启动InitContainer
,这时就不需要在每个容器启动后再进行配置,有点像中间件。
(1)其配置内容如下所示。在pod
的spec
下进行添加。
# 比如此处的initContainer就是在nginx容器中执行将inited...输出到init中
spec:
initContainers:
- image: nginx
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "echo 'inited...' >> ~/.init"]
name: init-test
3 污点和容忍
污点:是标注在节点上的,当我们在一个节点上打上污点以后,k8s
会认为尽量不要将 pod
调度到该节点上,除非该 pod
上面表示可以容忍该污点,且一个节点可以打多个污点,此时则需要 pod
容忍所有污点才会被调度该节点。
容忍:是标注在pod
上的,当 pod
被调度时,如果没有配置容忍,则该 pod
不会被调度到有污点的节点上,只有该 pod
上标注了满足某个节点的所有污点,则会被调度到这些节点。
3.1 污点的基本操作
(1)污点的操作。
# 为节点打上污点
kubectl taint node (节点名称) key=value:NoSchedule
# 移除污点
kubectl taint node (节点名称) key=value:NoSchedule-
# 查看污点
kubectl describe no (节点名称)
(2)污点的影响。
NoSchedule
:
- 如果不能容忍该污点,那么
Pod
就无法调度到该节点上。但是已经部署在该节点上的Pod
不会被驱逐。
NoExecute
:
- 如果
Pod
不能忍受这类污点,Pod
会马上被驱逐。 - 如果
Pod
能够忍受这类污点,但是在容忍度定义中没有指定tolerationSeconds
, 则Pod
还会一直在这个节点上运行。 - 如果
Pod
能够忍受这类污点,而且指定了tolerationSeconds
, 则Pod
还能在这个节点上继续运行这个指定的时间长度。
(3)污点的使用示例。
# 1 先查看master节点的污点,master节点在集群搭建时会自带污点
kubectl describe no k8s-master
# 2 再查看所有pod的信息,会发现由于master节点存在污点,所以pod都部署在node1和node2上
kubectl get po -o wide
# 3 将master节点的污点去掉,然后重启deploy容器。
kubectl taint node master node-role.kubernetes.io/master:NoSchedule-
# 4 再次查看master节点的污点,会发现已经为none了。
# 5 由于deploy容器,在被删除后会自动进行创建。
kubectl delete po nginx-deploy-58f9984477-l292j nginx-deploy-58f9984477-qwdbc
# 6 由于deploy的副本数只有2个,所以删除后,部署在master节点的几率不大,所以直接修改了nginx-deploy的配置文件,将其副本数添加到了4个。此时就有容器部署到了master节点上。
# 7 此时给master节点添加NoExecute污点,将部署到master的容器进行驱逐
kubectl taint node master key=value:NoExecute
# 8 通过下图可以观察到之前部署到master节点的容器,已经停止了并重启了一个到node1上
# 9 实验到此结束,将master节点的污点设置为原来初始的值
kubectl taint node master key=value:NoExecute-
kubectl taint node master node-role.kubernetes.io/master:NoSchedule
3.2 容忍的配置与使用
(1)首先给node2
节点添加上NoSchedule
污点。此时如果不配置容忍,则无法将容器部署到node2
节点上。
kubectl taint node node2 memory=low:NoSchedule
(2)添加容忍,这里还是以nginx-deploy
为例。加入后,容器就可以部署到node2
上了。
# pod 的 spec 下面配置容忍
tolerations:
- key: memory # 污点的 key
value: low # 污点的 value
offect: NoSchedule # 污点产生的影响
operator: Equal # 表是 value 与污点的 value 要相等,也可以设置为 Exists 表示存在 key 即可,此时可以不用配置 value
(3)此时将node2
节点的污点换成NoExecute
,会发现node2
进行了驱逐,所有部署的容器都部署到了node1
。虽然之前给nginx-deploy
配置了容忍,但是那个配置的是NoSchedule
的。
# 先将NoSchedule污点删除
kubectl taint node node2 memory=low:NoSchedule-
# 添加NoExecute污点
kubectl taint node node2 memory=low:NoExecute
(4)此时修改nginx-deploy
的容忍配置。并加入了tolerationSeconds
属性,设置为120,表示该pod
最多在node2
上运行120s,120s结束后,就会重新启动。如果不加tolerationSeconds
属性,则可以在node2
上长期运行。如下图所示。
# pod 的 spec 下面配置容忍
tolerations:
- key: memory # 污点的 key
value: low # 污点的 value
offect: NoExecute # 污点产生的影响
operator: Equal # 表是 value 与污点的 value 要相等,也可以设置为 Exists 表示存在 key 即可,此时可以不用配置 value
tolerationSeconds: 120 属性,则该 pod 还能继续在该节点运行 120 秒
4 亲和力和反亲和力
亲和力就是将几个强相关的容器部署到指定的节点上。就比如说有两个服务,他们之间需要经常进行通信操作,那么就可以将这两个服务部署到同一个节点上。而相对的反亲和力就是将容器尽量部署到不同的节点上。比如有两个都比较重要的服务,那么尽量就不要将他们放在同一个节点上,避免当节点出现问题时,这两个重要的服务都挂掉了。
4.1 NodeAffinity
-节点亲和力
节点亲和力(NodeAffinity
):进行 pod 调度时,优先调度到符合条件的亲和力节点上。
(1)此处使用官方的一个配置模板进行演示。本文仍然使用nginx-deploy
做演示,将以下配置文件加入到了nginx-deploy
的配置中。
spec:
affinity:
nodeAffinity:
# 硬亲和力,即支持必须部署在指定的节点上,也支持必须不部署在指定的节点上
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
# 软亲和力:尽量部署在满足条件的节点上,或尽量不要部署在被匹配的节点上
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1 # 权重为1
preference:
matchExpressions:
- key: label-1
operator: In # 匹配类型
values:
- key-1
- weight: 50 # 权重为50
preference:
matchExpressions:
- key: label-2
operator: In # 若把这里改为NotIn,则就是不匹配label-2=key2的节点
values:
- key-2
(2)给node1
和node2
打上标签。进行测试,会发现在添加了亲和力配置后的nginx-deploy
都部署到了node2
上面,这是因为在node1,node2
节点都部署了硬亲和力的情况下,标签为label-2=key-2
的node2
节点有更高的权重。
kubectl label no node1 label-1=key-1
kubectl label no node2 label-2=key-2
(3)匹配类型。
In
:部署在满足条件的节点上。NotIn
:匹配不在条件中的节点,实现节点反亲和性。Exists
:只要存在 key 名字就可以,不关心值是什么。DoesNotExist
:匹配指定 key 名不存在的节点,实现节点反亲和性。Gt
:value 为数值,且节点上的值小于指定的条件。Lt
:value 为数值,且节点上的值大于指定条件。
4.2 PodAffinity
-pod
亲和力
Pod
亲和力:将与指定 pod
亲和力相匹配的 pod
部署在同一节点。
Pod
反亲和力:根据策略尽量部署或不部署到一块。
(1)首先创建一个带有pod
亲和力和反亲和力的yaml
文件,其配置文件如下。该文件就是使该容器与具有security=S1
的pod
亲和,与security=S2
的pod
反亲和。
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity: # 亲和力
requiredDuringSchedulingIgnoredDuringExecution: # 硬亲和力
- labelSelector:
matchExpressions:
- key: security # 节点中的pod需要有 security=S1的标签
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone # 节点必须带有该标签
podAntiAffinity: # 反亲和力
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security # 节点中的pod需要有 security=S2的标签
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone # 节点必须带有该标签
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:2.0
(2)给node1
和node2
分别打上需要的标签。然后再给node1
节点中的任意一个pod
打上security=S1
标签。然后给node2
中的pod
打上security=S1
标签。
kubectl label no node1 topology.kubernetes.io/zone=V
kubectl label no node1 topology.kubernetes.io/zone=R
(3)创建该容器,进行观察会发现该容器被挂载到node1
节点。因为node1
其中有亲和力标签的pod
,而node2
具有反亲和力的pod
。
(4)将node1
节点的topology.kubernetes.io/zone
标签进行删除。会发现由于node2
节点具有反亲和力,而node1
节点又缺少了标签,所以不会被分配到任意节点。
kubectl label no node1 topology.kubernetes.io/zone-
更多推荐
所有评论(0)