Pod调度策略
- 一.污点-Taint
- 二.容忍度-Tolerations
- 三.Pod常见状态和重启策略
- 1.Pod常见状态
- 2.Pod的重启策略
- 2.1测试Always重启策略
- 2.2测试Never重启策略
- 2.3测试OnFailure重启策略(生产环境中常用)
一.污点-Taint
在 Kubernetes 中,污点(Taint)是一种标记,用于标识一个Node节点上的某些资源或条件不可用或不可接受。当一个节点被标记了污点后,只有那些能够容忍该污点的 Pod 才能被调度到该节点上。
污点常用与以下场景:
- 将某些节点标记为“故障”,以防止新的 Pod 被调度到这些节点上;
- 将某些节点标记为“高负载”,以防止过多的 Pod 被调度到这些节点上,导致节点过载;
- 将某些节点标记为“专用”,以保证只有特定的 Pod 能够被调度到这些节点上。
pod亲和性是pod属性;但是污点是节点的属性
,污点定义在k8s集群的节点上的一个字段。
# 查看控住节点定义的污点
[root@master1]# kubectl describe nodes master1 | grep Taints
Taints: node-role.kubernetes.io/control-plane:NoSchedule# 两个工作节点是没有定义污点
[root@node1]# kubectl describe nodes node1 | grep Taints
Taints: <none>[root@node2]# kubectl describe nodes node2 | grep Taints
Taints: <none>
1.查看定义taint的信息
# 查看帮助命令
[root@master1]# kubectl explain node.spec
······taints <[]Object>If specified, the node's taints.
[root@master1]# kubectl explain node.spec.taints
KIND: Node
VERSION: v1
RESOURCE: taints <[]Object>
DESCRIPTION:If specified, the node's taints.The node this Taint is attached to has the "effect" on any pod that doesnot tolerate the Taint.FIELDS:effect <string> -required-Required. The effect of the taint on pods that do not tolerate the taint.Valid effects are NoSchedule, PreferNoSchedule and NoExecute.Possible enum values:- `"NoExecute"` Evict any already-running pods that do not tolerate thetaint. Currently enforced by NodeController.- `"NoSchedule"` Do not allow new pods to schedule onto the node unlessthey tolerate the taint, but allow all pods submitted to Kubelet withoutgoing through the scheduler to start, and allow all already-running pods tocontinue running. Enforced by the scheduler.- `"PreferNoSchedule"` Like TaintEffectNoSchedule, but the scheduler triesnot to schedule new pods onto the node, rather than prohibiting new podsfrom scheduling onto the node entirely. Enforced by the scheduler.key <string> -required-Required. The taint key to be applied to a node.timeAdded <string>TimeAdded represents the time at which the taint was added. It is onlywritten for NoExecute taints.value <string>The taint value corresponding to the taint key.
污点排斥等级:
NoSchedule
:表示Pod不会被调度到具有该污点的节点上,不影响已经存在的PodPreferNoSchedule
:表示调度器会尽量避免将Pod调度到具有该污点的节点上。(但是Pod没有定义容忍度,依然会被调度到这两个节点上)NoExecute
:既影响Pod调度过程,又影响现存Pod对象,如果现存Pod不能容忍节点加的污点,那么这个Pod就会被驱逐
2.定义污点
kubectl taint nodes node1 node-type=dev:NoSchedule
3.查看污点
kubectl describe nodes node1 | grep Taint
4.删除污点
kubectl taint nodes node1 node-type=dev:NoSchedule-
二.容忍度-Tolerations
当我们节点定义污点后,如果我们不定义对应的容忍度,那么Pod将不会调度到此Node节点。
方便下面实验,我把所有node节点全部定义上污点
kubectl taint nodes node1 node-type=dev:NoSchedule
kubectl taint nodes node2 node-type=dev:NoSchedule
查看容忍度的帮助:
kubectl explain pod.spec.tolerations
1.定义Pod容忍度,容忍node-type=dev
,且排斥等级等于NoExecute
,使用了operator=Equal
这三点必须同时能满足。
cat pod1.yml
---
apiVersion: v1
kind: Pod
metadata:name: pod1namespace: defaultlabels:app: nginxenv: devspec:tolerations:- effect: "NoExecute" # 指定排斥等级key: "node-type" # 污点keyoperator: "Equal" # Equal表示等于value: "dev" # 污点valuetolerationSeconds: 3600 # 删除Pod前等待时间,默认30scontainers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
执行文件
kubectl apply -f pod1.yaml
查看状态,因为没有任何节点满足该Pod容忍,所以该Pod处于Pending状态
kubectl get pods pod1NAME READY STATUS RESTARTS AGE
pod1 0/1 Pending 0 10m
2.定义Pod容忍度,将排斥等级改为 NoSchedule,这样我们污点key,value,排斥等级都满足了,Pod才会调度 Pod资源清单文件如下:
cat pod2.yml
---
apiVersion: v1
kind: Pod
metadata:name: pod2namespace: defaultlabels:app: nginxenv: devspec:tolerations:- effect: "NoSchedule" # 指定排斥等级key: "node-type" # 污点keyoperator: "Equal" # Equal表示等于value: "dev" # 污点valuecontainers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
执行文件
kubectl apply -f pod2.yaml
查看状态,Pod成功调度,且状态为 Running
kubectl get pods pod2NAME READY STATUS RESTARTS AGE
pod2 1/1 Running 0 5m32s
3.定义Pod容忍度,将 operator=Exists表示满足其中一项即可容忍,下面Pod没有定义key,value,表示没有key,value方面限制,容忍排斥等级=NoSchedule的节点。
cat pod3.yml
---
apiVersion: v1
kind: Pod
metadata:name: pod3namespace: defaultlabels:app: nginxenv: devspec:tolerations:- effect: "NoSchedule" # 指定排斥等级 operator: "Exists" # Exists表示满足一项即可containers:- name: nginximage: nginximagePullPolicy: IfNotPresentports:- containerPort: 80
执行文件
kubectl apply -f pod3.yaml
查看状态,Pod调度成功,且状态为Running
kubectl get pods pod-3NAME READY STATUS RESTARTS AGE
pod3 1/1 Running 0 5m16s
三.Pod常见状态和重启策略
1.Pod常见状态
第一阶段:
- 挂起(Pending):
- 正在创建Pod,但是Pod中的容器还没有全部被创建完成,处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载、镜像是否可以下载、调度是否正常等;
- 我们在请求创建pod时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件,已经创建了pod但是没有适合它运行的节点叫做挂起,调度没有完成。
- 失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止。
- 未知(Unknown):未知状态,所谓pod是什么状态是apiserver和运行在pod节点的kubelet进行通信获取状态信息的,如果节点之上的kubelet本身出故障,那么apiserver就连不上kubelet,得不到信息了,就会看Unknown,通常是由于与pod所在的node节点通信错误。
- Error 状态:Pod 启动过程中发生了错误
- 成功(Succeeded):Pod中的所有容器都被成功终止,即pod里所有的containers均已terminated。
第二阶段:
- Unschedulable:Pod不能被调度, scheduler没有匹配到合适的node节点PodScheduled:pod正处于调度中,在scheduler刚开始调度的时候,还没有将pod分配到指定的node,在筛选出合适的节点后就会更新etcd数据,将pod分配到指定的node
- Initialized:所有pod中的初始化容器已经完成了
- ImagePullBackOff:Pod所在的node节点下载镜像失败
- Running:Pod内部的容器已经被创建并且启动。
扩展:还有其他状态,如下:
- Evicted状态:出现这种情况,多见于系统内存或硬盘资源不足,可df-h查看docker存储所在目录的资源使用情况,如果百分比大于85%,就要及时清理下资源,尤其是一些大文件、docker镜像。
- CrashLoopBackOff:容器曾经启动了,但可能又异常退出了。如pod一直在重启
2.Pod的重启策略
Pod的重启策略(RestartPolicy)应用于Pod内的所有容器,当某个容器异常退出或者健康检查失败时,kubelet将根据 重启策略来进行相应的操作。
Pod 的 spec 中包含一个 restartPolicy 字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
- Always:只要容器异常退出,kubelet就会自动重启该容器。(这个是默认的重启策略)
- OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。(生产环境中常用)
- Never:不论容器运行状态如何,kubelet都不会重启该容器。
2.1测试Always重启策略
[root@master1]# vim pod.yaml
apiVersion: v1
kind: Pod
metadata:name: demo-podnamespace: defaultlabels:app: myapp
spec:restartPolicy: Alwayscontainers:- name: tomcatports:- containerPort: 8080image: tomcat:latestimagePullPolicy: IfNotPresent[root@master1]# kubectl apply -f pod.yaml
pod/demo-pod created
[root@master1]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 1/1 Running 0 10s 10.244.169.153 node2 <none> <none># 动态显示pod状态信息
[root@master1]# kubectl get pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 1/1 Running 0 22s 10.244.169.153 node2 <none> <none># 另起一个终端会话,进入pod内部容器,正常停止 tomcat 容器服务。-c 指定容器名称。
[root@master1]# kubectl exec -it demo-pod -c tomcat -- /bin/bash
root@demo-pod:/usr/local/tomcat# ls
root@demo-pod:/usr/local/tomcat# bin/shutdown.sh
可以看到容器服务停止后被重启了一次,Pod又恢复正常
# 非正常停止容器里的tomcat服务
[root@master1]# kubectl exec -it demo-pod -c tomcat -- bash
root@demo-pod:/usr/local/tomcat# ps -ef | grep tomcat
root@demo-pod:/usr/local/tomcat# kill 1
容器被终止,再一次重启,重启次数加一
2.2测试Never重启策略
# 修改 pod.yaml,把 Always 改为 Never
[root@master1]# kubectl delete pods demo-pod
pod "demo-pod" deleted
[root@master1]# kubectl apply -f pod.yaml
pod/demo-pod created
[root@master1]# kubectl get pods -o wide -w# 在另一个终端进入容器,正常停止服务
[root@master1]# kubectl exec -it demo-pod -c tomcat-pod-java -- /bin/bash
root@demo-pod:/usr/local/tomcat# bin/shutdown.sh
查看Pod状态,发现正常停止tomcat服务,Pod正常运行,但是容器没有重启
# 非正常停止容器里的tomcat服务
[root@master1]# kubectl delete pods demo-pod
pod "demo-pod" deleted
[root@master1]# kubectl apply -f pod.yaml
pod/demo-pod created
[root@master1]# kubectl get pods -o wide -w# 在另一终端进入容器内容
[root@master1]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
root@demo-pod:/usr/local/tomcat# kill 1
看到容器的状态时Pod的状态是Error,并且没有重启,说明重启策略是Never,那么Pod里容器服务无论如何终止,都不会重启
2.3测试OnFailure重启策略(生产环境中常用)
# 修改 pod.yaml 文件,把 Never 改为 OnFailure
[root@master1]# kubectl delete pods demo-pod
pod "demo-pod" deleted
[root@-master1]# kubectl apply -f pod.yaml
pod/demo-pod created
[root@master1]# kubectl get pods -o wide -w# 在另一终端进入容器内部,正常停止服务
[root@master1]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
root@demo-pod:/usr/local/tomcat# bin/shutdown.sh
发现正常通知容器,退出码时0,容器不会重启
# 非正常停止容器里的tomcat服务
[root@master1]# kubectl delete pods demo-pod
pod "demo-pod" deleted
[root@master1]# kubectl apply -f pod.yaml
pod/demo-pod created
[root@master1]# kubectl get pods -o wide -w# 在另一终端进入容器内部
[root@master1]# kubectl exec -it demo-pod -c tomcat-pod-java -- bash
root@demo-pod:/usr/local/tomcat# kill 1
看到非正常停止的pod里的容器,容器退出码不是0,容器会被重启。