本章概述
- node Affinity与anti-affinity(node亲和与反亲和)
- pod Affinity与pod antiaffinity(pod亲和与反亲和)
- 污点与容忍
- kubernetes pod驱逐
12.1 node Affinity与anti-affinity(node亲和与反亲和)
12.1.1 nodeSelector
nodeSelector 基于node标签选择器,将pod调度的指定的目的节点上。
官网链接:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/
可用于基于服务类型干预Pod调度结果,如对磁盘I/O要求高的pod调度到SSD节点,对内存要求比较高的pod调度的内存较高的节点。
也可以用于区分不同项目的pod,如将node添加不同项目的标签,然后区分调度。
查看默认标签
kubectl describe node 172.31.7.111
也可以使用命令:kubectl get node --show-labels 查看所有node的标签
如果需要查看某个node的标签,需要在node后加上node ip地址。即:kubectl get node 172.31.7.111 --show-labels
为了便于演示,为node节点打标签
指定172.31.7.111属于magedu项目,且硬盘为ssd
指定172.31.7.112属于magedu项目,且硬盘为hdd
为节点172.31.7.111打标签
kubectl label node 172.31.7.111 project=magedu
kubectl label node 172.31.7.111 disktype=ssd
查看标签:
kubectl describe node 172.31.7.111
为节点172.31.7.112打标签
kubectl label node 172.31.7.112 project=magedu
kubectl label node 172.31.7.112 disktype=hdd
查看标签
如果node节点打错标签,如何删除标签:
kubectl label node 172.31.7.112 disktype- #只需要在标签的key值后加上“-”即可
再次查看标签,可以看到172.31.7.111节点的disktype标签被删除
示例:将pod调度到目的node节点,yaml文件中指定的key和value必须精确匹配(通过指定标签,该pod一定会被调度到172.31.7.112上)
vim case1-nodeSelector.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
memory: "512Mi"
requests:
cpu: 500m
memory: "512Mi"
nodeSelector: #指定标签选择器,作用于整个pod,对pod中所有容器都生效
project: magedu #指定项目为magedu
disktype: hdd #指定磁盘类型为hdd
创建pod
kubectl apply -f case1-nodeSelector.yaml
查看pod,pod所在物理机节点为172.31.7.112
12.1.2 nodeName
通过nodename调度pod,将pod调度到指定的node上
如果目标node宕机,则会调度失败,使用场景较少
示例:通过指定nodename,将pod调度到172.31.7.113上
vim case2-nodename.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
nodeName: 172.31.7.113 #指定nodename为172.31.7.113
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
resources:
limits:
cpu: 1
memory: "512Mi"
requests:
cpu: 500m
memory: "512Mi"
创建pod
kubectl apply -f case2-nodename.yaml
查看pod
pod被调度到172.31.7.113上
12.1.3 node affinity(节点亲和)
affinity是Kubernetes 1.2版本后引入的新特性,类似于nodeSelector,允许使用者指定一些Pod在Node间调度的约束。
目前支持两种形式:
requiredDuringSchedulingIgnoredDuringExecution #必须满足pod调度匹配条件,如果不满足则不进行调度
preferredDuringSchedulingIgnoredDuringExecution #倾向满足pod调度匹配条件,不满足的情况下会调度的不符合条件的Node上
IgnoreDuringExecution表示如果在Pod运行期间Node的标签发生变化,导致亲和性策略不能满足,也会继续运行当前的Pod。
Affinity与anti-affinity的目的也是控制pod的调度结果,但是相对于nodeSelector,亲和与反亲和功能更加强大:
1、标签选择器不仅仅支持and,还支持In、NotIn、Exists、DoesNotExist、Gt、Lt。
In:标签的值存在匹配列表中(匹配成功就调度到目的node,实现node亲和)
NotIn:标签的值不存在指定的匹配列表中(不会调度到目的node,实现反亲和)
Gt:标签的值大于某个值(字符串)
Lt:标签的值小于某个值(字符串)
Exists:指定的标签存在
2、可以设置软匹配和硬匹配,在软匹配下,如果调度器无法匹配节点,仍然将pod调度到其它不符合条件的节点。
3、还可以对pod定义亲和策略,比如允许哪些pod可以或者不可以被调度至同一台node。
注意:
如果定义一个nodeSelectorTerms(条件)中通过一个matchExpressions基于列表指定了多个operator条件,则只要满足其中一个条件,就会被调度到相应的节点上,即or的关系,即如果nodeSelectorTerms下面有多个条件的话,只要满足任何一个条件就可以了,见12.1.3.1硬亲和示例1
如果定义一个nodeSelectorTerms中都通过一个matchExpressions(匹配表达式)指定key匹配多个条件,则所有的目的条件都必须满足才会调度到对应的节点,即and的关系,即果matchExpressions有多个选项的话,则必须同时满足所有这些条件才能正常调度,见12.1.3.2硬亲和示例2 。
12.1.3.1 硬亲和示例1
编辑yaml文件
vim case3-1.1-nodeAffinity-requiredDuring-matchExpressions.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #匹配条件1,多个values可以调度
- key: disktype
operator: In
values:
- hdd # 只有一个value是匹配成功也可以调度
- xxx
- matchExpressions: #匹配条件2,多个matchExpressions加上以及每个matchExpressions values只有其中一个value匹配成功就可以调度
- key: project
operator: In
values:
- mmm #即使这俩条件2的都匹配不上也可以调度
- nnn
以上示例中,有两个匹配表达式matchExpressions,每个匹配表达式中都有一个key值,只要满足其中一个匹配表达式matchExpressions即可匹配
由于yaml文件中指定disktype为hdd的条件,因此pod会被调度到172.31.7.112上
创建pod
kubectl apply -f case3-1.1-nodeAffinity-requiredDuring-matchExpressions.yaml
查看pod,被调度到172.31.7.112上
12.1.3.2 硬亲和示例2
编辑yaml文件
vim case3-1.2-nodeAffinity-requiredDuring-matchExpressions.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #硬亲和匹配条件1
- key: disktype
operator: In
values:
- ssd
- xxx #同个key的多个value只有有一个匹配成功就行
- key: project #硬亲和条件1和条件2必须同时满足,否则不调度
operator: In
values:
- magedu
以上示例中有一个匹配表达式matchExpressions,在该匹配表达式中有两个key值,这两个key都要满足才可以匹配
必须要满足属于magedu项目,且disktype为ssd才会被调度,因此pod会被调度到172.31.7.111上
创建pod
kubectl apply -f case3-1.2-nodeAffinity-requiredDuring-matchExpressions.yaml
查看pod,被调度到172.31.7.111上
12.1.3.3 软亲和示例1
编辑yaml文件
vim case3-2.1-nodeAffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80 #软亲和条件1,值越大优先级越高,越优先匹配调度,如果条件1匹配,则不会匹配后续的其他条件
preference:
matchExpressions:
- key: project
operator: In
values:
- magedu
- weight: 60 #软亲和条件2,在条件1不满足时匹配条件2
preference:
matchExpressions:
- key: disktype
operator: In
values:
- hdd
创建pod,查看pod调度结果(这时条件1为project=magedu,172.31.7.111和112都满足条件,pod被调度到172.31.7.112上)
更改软亲和条件1,查看调度结果(以下备注部分为修改内容)
- weight: 80
preference:
matchExpressions:
- key: project
operator: In
values:
- mageduxx #此处为修改内容
- weight: 60 #软亲和条件2,在条件1不满足时匹配条件2
preference:
matchExpressions:
- key: disktype
operator: In
values:
- hdd
创建pod,查看pod调度结果(这时172.31.7.112满足disktype为hdd的条件,pod被调度到172.31.7.112上)
更改软亲和条件1和条件2,查看调度结果(以下备注部分为修改内容)
- weight: 80
preference:
matchExpressions:
- key: project
operator: In
values:
- mageduxx #此处为修改内容(软亲和条件1)
- weight: 60 #软亲和条件2,在条件1不满足时匹配条件2
preference:
matchExpressions:
- key: disktype
operator: In
values:
- hddxx #此处为修改内容(软亲和条件2)
创建pod,查看pod调度结果(这时172.31.7.111和112都不满足条件,但由于是软亲和,不满足条件也会被调度,因此pod被调度到172.31.7.112上)
12.1.3.4 软亲和结合硬亲和示例
基于硬亲和和软亲和实现pod调度:
1.绝对不会调度在哪些node
2.倾向于调度到哪些node
示例:
vim case3-2.2-nodeAffinity-requiredDuring-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #硬亲和
nodeSelectorTerms:
- matchExpressions: #硬匹配条件1
- key: "kubernetes.io/role"
operator: NotIn #NotIn表示取反,不匹配
values:
- "master" #硬性匹配key 的值kubernetes.io/role不包含master的节点,即绝对不会调度到master节点(node反亲和)
preferredDuringSchedulingIgnoredDuringExecution: #软亲和
- weight: 80
preference:
matchExpressions:
- key: project
operator: In
values:
- magedu
- weight: 60
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
yaml文件指定硬亲和:pod被调度的node绝对不包括master节点
软亲和:pod被调度到node节点时,匹配条件被调度,不匹配也会被调度,保证pod可以被拉起
创建pod,查看pod调度结果(被调度到172.31.7.111上)
12.1.4 node 反亲和-nodeantiaffinity
编辑yaml文件
vim case3-3.1-nodeantiaffinity.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions: #匹配条件1
- key: disktype
operator: NotIn #调度的目的节点没有key为disktype且值为hdd的标签
values:
- hdd #绝对不会调度到含有label的key为disktype且值为hdd的hdd的节点,即会调度到没有key为disktype且值为hdd的hdd的节点
yaml文件指定反亲和:绝对不会调度到含有label的key为disktype且值为hdd的hdd的节点
创建pod,查看调度结果(172.31.7.111和113满足条件,pod被调度到172.31.7.111上)
12.2 pod Affinity与pod antiaffinity(pod亲和与反亲和)
12.2.1 Pod Affinity与anti-affinity简介
pod亲和和反亲和使用的场景不同:
pod亲和性:把tomcat和nginx pod运行在同一个物理机节点,避免跨主机调用,降低消耗
pod反亲和性:大数据或zookeeper等分布式集群需要独立部署的服务,调度到不同的节点,提升高可用
Pod亲和性与反亲和性可以基于已经在node节点上运行的Pod的标签来约束新创建的Pod可以调度到的目的节点,注意不是基于node上的标签而是使用的已经运行在node上的pod标签匹配。
其规则的格式为如果 node节点 A已经运行了一个或多个满足调度新创建的Pod B的规则,那么新的Pod B在亲和的条件下会调度到A节点之上,而在反亲和性的情况下则不会调度到A节点至上。
其规则表示一个具有可选的关联命名空间列表的LabelSelector,只所以Pod亲和与反亲和可以通过LabelSelector选择namespace,是因为Pod是命名空间限定的而node不属于任何nemespace所以node的亲和与反亲和不需要namespace,因此作用于Pod标签的标签选择算符必须指定选择算符应用在哪个命名空间。
从概念上讲,node节点是一个拓扑域(具有拓扑结构的域),比如k8s集群中的单台node节点、一个机架、云供应商可用区、云供应商地理区域等,可以使用topologyKey来定义亲和或者反亲和的颗粒度是node级别还是可用区级别,以便kubernetes调度系统用来识别并选择正确的目的拓扑域。
Pod 亲和性与反亲和性的合法操作符(operator)有 In、NotIn、Exists、DoesNotExist。
在Pod亲和性配置中,在requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution中,topologyKey不允许为空(Empty topologyKey is not allowed.)。
在Pod反亲和性中配置中,requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey也不可以为空(Empty topologyKey is not allowed.)。
对于requiredDuringSchedulingIgnoredDuringExecution要求的Pod反亲和性,准入控制器LimitPodHardAntiAffinityTopology被引入以确保topologyKey只能是 kubernetes.io/hostname,如果希望 topologyKey 也可用于其他定制拓扑逻辑,可以更改准入控制器或者禁用。
除上述情况外,topologyKey 可以是任何合法的标签键。
创建nginx pod用于后续pod亲和和反亲和测试
vim case4-4.1-nginx.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: python-nginx-deployment-label
name: python-nginx-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: python-nginx-selector
template:
metadata:
labels:
app: python-nginx-selector
project: python #配置标签,key为project,value为python,用于后续演示
spec:
containers:
- name: python-nginx-container
image: nginx:1.20.2-alpine
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
#imagePullPolicy: IfNotPresent
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
name: http
- containerPort: 443
protocol: TCP
name: https
env:
- name: "password"
value: "123456"
- name: "age"
value: "18"
---
kind: Service
apiVersion: v1
metadata:
labels:
app: python-nginx-service-label
name: python-nginx-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
nodePort: 30014
- name: https
port: 443
protocol: TCP
targetPort: 443
nodePort: 30453
selector:
app: python-nginx-selector
project: python #一个或多个selector,至少能匹配目标pod的一个标签
创建nginx pod
kubectl apply -f case4-4.1-nginx.yaml
pod被调度到172.31.7.112上
12.2.2 Pod Affinity(亲和)示例
1、pod软亲和示例:
vim case4-4.2-podaffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAffinity: #指定pod亲和
#requiredDuringSchedulingIgnoredDuringExecution:
preferredDuringSchedulingIgnoredDuringExecution: #配置软亲和
- weight: 100 #设置权重为100
podAffinityTerm: #配置pod亲和
labelSelector:
matchExpressions: #配置表达式
- key: project #匹配key值为project
operator: In
values: #匹配value值为python
- python
topologyKey: kubernetes.io/hostname #指定拓扑域,以hostname作为颗粒度,即新建pod与匹配条件的pod在同一台主机上
namespaces: #匹配在magedu这个namespace
- magedu
yaml文件指定创建的pod与匹配条件的pod在同一个主机,条件为:在magedu 这个namespace,且key值为project,value值为python的pod。
查看新建pod所在主机为172.31.7.112,与nginx pod在同一个主机
注意:如果目标主机资源不足,且配置软亲和,会将pod调度到其他不满足条件的node上。
2、pod硬亲和示例:
编辑yaml文件
vim case4-4.3-podaffinity-requiredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 3
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAffinity: #指定pod亲和
requiredDuringSchedulingIgnoredDuringExecution: #指定pod硬亲和
- labelSelector:
matchExpressions: #配置表达式
- key: project #匹配key值为project
operator: In
values: #匹配value值为python
- python
topologyKey: "kubernetes.io/hostname" #指定拓扑域,以hostname作为颗粒度,即新建pod与匹配条件的pod在同一台主机上
namespaces:
- magedu #匹配在magedu这个namespace
yaml文件指定新建的pod必须和匹配条件的pod在同一个主机
创建pod,查看pod调度情况(均和nginx pod在同一个主机)
注意:如果目标主机资源不足,且配置硬亲和,pod将不会被调度。
验证:
修改硬亲和条件:(以下备份部分为修改部分)
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #指定pod硬亲和
- labelSelector:
matchExpressions: #配置表达式
- key: project #匹配key值为project
operator: In
values: #匹配value值为python
- pythonxx #此处为修改内容(修改硬亲和条件)
topologyKey: "kubernetes.io/hostname" #指定拓扑域,以hostname作为颗粒度,即新建pod与匹配条件的pod在同一台主机上
namespaces:
- magedu #匹配在magedu这个namespace
创建pod,查看pod状态为pending
查看pod日志,信息提示不匹配亲和条件
kubectl describe pod magedu-tomcat-app2-deployment-7ff7c989c7-cdpfg -n magedu
12.2.3 pod 反亲和
1、pod硬反亲和示例
基于硬反亲和实现多个pod调度不在一个node,要求必须满足
示例:
vim case4-4.4-podAntiAffinity-requiredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAntiAffinity: #指定pod反亲和
requiredDuringSchedulingIgnoredDuringExecution: #指定硬亲和
- labelSelector:
matchExpressions:
- key: project
operator: In
values:
- python
topologyKey: "kubernetes.io/hostname"
namespaces:
- magedu
yaml文件指定新建pod和匹配条件的pod必须不在同一个主机,否则不会被调度
创建pod,查看pod(新建主机和nginx pod不在同一个主机,nginx pod在172.31.7.112上,新建pod在172.31.7.111上)
2、pod软反亲和示例
vim case4-4.5-podAntiAffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app2-deployment-label
name: magedu-tomcat-app2-deployment
namespace: magedu
spec:
replicas: 1
selector:
matchLabels:
app: magedu-tomcat-app2-selector
template:
metadata:
labels:
app: magedu-tomcat-app2-selector
spec:
containers:
- name: magedu-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: project
operator: In
values:
- python
topologyKey: kubernetes.io/hostname
namespaces:
- magedu
yaml文件指定新建pod和符合条件的pod能不在同一个主机就不在同一个主机,如果没有满足条件的主机,则也可以和符合条件的pod在同一个主机
创建pod,查看pod调度情况新建主机和nginx pod不在同一个主机,nginx pod在172.31.7.112上,新建pod在172.31.7.111上)
软硬亲和与反亲和总结:
硬亲和-绝对会在一起
硬反亲和-绝对不会在一起
软亲和-能在一起一起就在一起
软反亲和-能不在一起就不在一起,如果匹配失败也会在一起
12.3 污点与容忍
12.3.1 污点与容器简介
1、污点
污点(taints),用于node节点排斥 Pod调度,与亲和的作用是完全相反的,即taint的node和pod是排斥调度关系。
容忍(toleration),用于Pod容忍node节点的污点信息,即node有污点信息也会将新的pod调度到node。
官网链接:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/
污点的三种类型:
(1)NoSchedule: 表示k8s将不会将Pod调度到具有该污点的Node上
示例:
kubectl taint nodes 172.31.7.111 key1=value1:NoSchedule #设置污点
kubectl describe node 172.31.7.111 #查看污点
注意:此时创建pod,不会调度到该node上
kubectl taint node 172.31.7.111 key1:NoSchedule- #取消污点
查看污点信息,已经被取消
(2)PreferNoSchedule: 表示k8s将尽量避免将Pod调度到具有该污点的Node上
(3)NoExecute: 表示k8s将不会将Pod调度到具有该污点的Node上,同时会将Node上已经存在的Pod强制驱逐出去(使用场景:node节点下线)
示例:
kubectl taint nodes 172.31.7.111 key1=value1:NoExecute
12.3.2 tolerations容忍
定义 Pod 的容忍度,可以调度至含有污点的node。
基于operator的污点匹配:
如果operator是Exists,则容忍度不需要value而是直接匹配污点类型。
如果operator是Equal,则需要指定value并且value的值需要等于tolerations的key。
示例:提前在node打上污点,然后再配置容忍
(1)为172.31.7.111节点打上污点
kubectl taint nodes 172.31.7.111 key1=value1:NoSchedule #设置污点
(2)创建pod,配置容忍,可以将该pod调度至设置污点的node上
vim case5.1-taint-tolerations.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: magedu-tomcat-app1-deployment-label
name: magedu-tomcat-app1-deployment
namespace: magedu
spec:
replicas: 5 #创建5个副本,便于查看演示效果
selector:
matchLabels:
app: magedu-tomcat-app1-selector
template:
metadata:
labels:
app: magedu-tomcat-app1-selector
spec:
containers:
- name: magedu-tomcat-app1-container
#image: harbor.magedu.local/magedu/tomcat-app1:v7
image: tomcat:7.0.93-alpine
#command: ["/apps/tomcat/bin/run_tomcat.sh"]
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
protocol: TCP
name: http
tolerations: #指定pod容忍
- key: "key1" #容忍的key值为key1
operator: "Equal" #指定operator是Equal,必须匹配value
value: "value1" #指定容忍的value值为value1
effect: "NoSchedule" #指定污点类型
---
kind: Service
apiVersion: v1
metadata:
labels:
app: magedu-tomcat-app1-service-label
name: magedu-tomcat-app1-service
namespace: magedu
spec:
type: NodePort
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8080
#nodePort: 40003
selector:
app: magedu-tomcat-app1-selector
创建pod,查看调度结果,有pod被调度至172.31.7.111(已经被打上污点)上,说明容忍配置已经生效
12.4 kubernetes pod驱逐
12.4.1 驱逐简介
1、通过命令手动进行驱逐:
(1)通过打污点的方式驱逐容器
kubectl taint nodes 172.31.7.111 key1=value1:NoExecute #会将172.31.7.111上除了daemonset类型的其他容器驱逐至别的主机
注意:该命令执行完以后,会给node节点打上key1=value1:NoExecute的污点信息,并立即驱逐pod
取消key1=value1:NoExecute污点:
kubectl taint nodes 172.31.7.111 key1:NoExecute-
(2)通过kubectl drain命令驱逐容器
kubectl drain 172.31.7.111 --ignore-daemonsets 会将172.31.7.111上除了daemonset类型的其他容器驱逐至别的主机
注意:该命令执行完以后,会给node节点打上SchedulingDisabled的标签,并立即驱逐pod。
取消SchedulingDisabled标签:
kubectl uncordon 172.31.7.111
2、kubelet自动发起驱逐,回收资源
节点压力驱逐是由各kubelet进程主动终止Pod,以回收节点上的内存、磁盘空间等资源的过程,kubelet监控当前node节点的CPU、内存、磁盘空间和文件系统的inode等资源,当这些资源中的一个或者多个达到特定的消耗水平,kubelet就会主动地将节点上一个或者多个Pod强制驱逐,以防止当前node节点资源无法正常分配而引发的OOM。
官网链接:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/node-pressure-eviction/
k8s集群会预留一部分资源,当预留资源不足时,kubelet会自动发起驱逐,以下为默认的预留资源阈值,当资源小于阈值时会发起驱逐:
宿主机内存:
memory.available #node节点可用内存,默认 <100Mi
nodefs是节点的主要文件系统,用于保存本地磁盘卷、emptyDir、日志存储等数据,默认是/var/lib/kubelet/,或者是通过kubelet通过--root-dir所指定的磁盘挂载目录
nodefs.inodesFree #nodefs的可用inode,默认<5%
nodefs.available #nodefs的可用空间,默认<10%
imagefs是可选文件系统,用于给容器提供运行时存储容器镜像和容器可写层。
imagefs.inodesFree #imagefs的inode可用百分比
imagefs.available #imagefs的磁盘空间可用百分比,默认<15%
pid.available #可用pid百分比
小知识
kube-controller-manager实现eviction:node宕机后的驱逐
kubelet实现的eviction:基于node负载、资源利用率等进行pod驱逐。
驱逐(eviction,节点驱逐),用于当node节点资源不足的时候自动将pod进行强制驱逐,以保证当前node节点的正常运行。Kubernetes基于是QoS(服务质量等级)驱逐Pod , Qos等级包括目前包括以下三个:
(1)Guaranteed: limits和request的值相等,等级最高、最后被驱逐
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 500m
memory: 256Mi
(2)Burstable: limit和request不相等,等级折中、中间被驱逐
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 256m
memory: 128Mi
(3)BestEffort: 没有限制,即resources为空,等级最低、最先被驱逐
驱逐条件:
(1)eviction-signal:kubelet捕获node节点驱逐触发信号,进行判断是否驱逐,比如通过cgroupfs获取memory.available的值来进行下一步匹配。
(2)operator:操作符,通过操作符对比条件是否匹配资源量是否触发驱逐。
(3)quantity:使用量,即基于指定的资源使用值进行判断,如memory.available: 300Mi、nodefs.available: 10%等。
比如:nodefs.available\<10% #当node节点磁盘空间可用率低于10%就会触发驱逐信号
12.4.2 软驱逐
软驱逐不会立即驱逐pod,可以自定义宽限期,在条件持续到宽限期还没有恢复,kubelet再强制杀死pod并触发驱逐。
软驱逐条件:
eviction-soft: 软驱逐触发条件,比如memory.available < 1.5Gi,如果驱逐条件持续时长超过指定的宽限期,可以触发Pod驱逐。
eviction-soft-grace-period:软驱逐宽限期, 如 memory.available=1m30s,定义软驱逐条件在触发Pod驱逐之前必须保持多长时间。
eviction-max-pod-grace-period:终止pod的宽限期,即在满足软驱逐条件而终止Pod时使用的最大允许宽限期(以秒为单位)。
12.4.3 硬驱逐
硬驱逐条件没有宽限期,当达到硬驱逐条件时,kubelet 会强制立即杀死 pod并驱逐:
kubelet 具有以下默认硬驱逐条件(可以自行调整):
memory.available<100Mi
nodefs.available<10%
imagefs.available<15%
nodefs.inodesFree<5%(Linux 节点)
查看k8s集群硬驱逐配置方法:
查找kubelet service文件:
vim /etc/systemd/system/kubelet.service
查看kubelet配置文件:
vim /var/lib/kubelet/config.yaml
evictionHard:
imagefs.available: 15%
memory.available: 300Mi
nodefs.available: 10%
nodefs.inodesFree: 5%
一旦被驱逐,pod状态会显示如下状态:
文章评论