K8S pod 亲和与反亲和 (podAffinity与podAntiAffinity)
K8S pod 亲和与反亲和 (podAffinity与podAntiAffinity)
目录
1、 简介:
前面介绍过node的亲和与反亲和,主要是用于node与pod之间的关联关系
而pod的亲和与反亲和主要是用于各个pod之间关联关系,具体关系如下:
pod亲和与反亲和可以基于已经在node节点上运行的pod的标签来约束新创建的pod可以调度到的目的节点(注:不是基于node的标签,而是使用已经运行在node节点上的pod的标签匹配)
pod亲和使用场景:当A和B两个pod需要互相调用时候,最好是在同一个node节点上运行,这样网络开销就会比较小,这时就可以使用pod亲和通过A pod的标签方式来把B pod调度到同一个节点运行,这就是亲和,相反如果部署一个集群服务,为了集群高可用,反而不希望pod调度到同一个node上就是反亲和
因为pod是有namespace限定的,因此作用于pod标签的标签选择符必须指定选择算符应用在哪个命名空间
2、配置须知:
pod亲和:podAffinity
pod反亲和:podAntiAffinity
pod亲和与反亲和的合法操作符(operator):In 、NotIn 、Exists、 DoesNotExist
pod的亲和与反亲和配置在两个字段中
1、硬亲和:requiredDuringSchedulinglgnoredDuringExecution
2、软亲和:prequiredDuringSchedulinglgnoredDuringExecution
不管是硬亲和还是软亲和,topologykey字段都不能为空
对于requiredDuringSchedulinglgnoredDuringExecution要求的pod反亲和性,准入控制器LimitPodHardAntiAffinityTopology被引入以确保topologyKey只能是kubernetes.io/hostname (K8S集群节点名称), 如果希望topologyKey 也可用于其它定制拓扑逻辑,可以更改准入控制器或者禁用。 除上述情况外,topologyKey不一定非得是kubernetes.io/hostname,它也可以是任何合法的标签
示例:
示例:在myserver namespace中部署一个nginx服务,nginx pod 将用于后续的pod亲和及反亲和测试,pod的label如下
app: python-nginx-selector
project: python
一、创建前端nginx容器
1、编写yaml文件
root@master1:/pod# cat nginx.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: python-nginx-deployment-label
name: python-nginx-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: python-nginx-selector
template:
metadata:
labels:
app: python-nginx-selector #标签:这是个是deployment控制器模板,这个模板会被这个deployment控制器下所有pod继承
project: python #标签:这是个是deployment控制器模板,这个模板会被这个deployment控制器下所有pod继承
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"
# resources:
# limits:
# cpu: 2
# memory: 2Gi
# requests:
# cpu: 500m
# memory: 1Gi
---
kind: Service
apiVersion: v1
metadata:
labels:
app: python-nginx-service-label
name: python-nginx-service
namespace: myserver
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的一个标签
2、创建资源
root@master1:/pod# kubectl apply -f nginx.yaml
3、查看资源
root@master1:/pod# kubectl get pod -n myserver -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
python-nginx-deployment-5c658bf86b-q4286 1/1 Running 0 6m55s 10.200.104.31 172.31.7.112 <none> <none>
二、创建后端容器,与nginx容器做软亲和
软亲和是优先完成匹配条件调度,但如果无法满足匹配条件kubelet也能自行调度
1、创建资源文件
root@master1:/pod# cat podaffinity-preferredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: myserver-tomcat-app2-deployment-label
name: myserver-tomcat-app2-deployment
namespace: myserver
spec:
replicas: 1
selector:
matchLabels:
app: myserver-tomcat-app2-selector
template:
metadata:
labels:
app: myserver-tomcat-app2-selector
spec:
containers:
- name: myserver-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: #软亲和,能匹配成功就调度到一个topology,匹配不成功会由kubernetes自行调度。
- weight: 100
podAffinityTerm: #亲和标签
labelSelector: #标签选择
matchExpressions: #正则匹配
- key: project #指定key是project
operator: In #In表示key值在下面列表中
values:
- python #值是python,查验pod列表中有没有这个键值,而nginx容器标签中有指定这对键值
topologyKey: kubernetes.io/hostname
namespaces:
- myserver
2、创建资源
root@master1:/pod# kubectl apply -f podaffinity-preferredDuring.yaml
3、查看资源,可以看见两个pod都调度到了同一个node,因为能匹配到标签
可以看见nginx容器中定义了project:python标签,后端容器的标签正好可以匹配到这对标签,完成pod亲和
4、测试无法匹配到条件时,调度结果
修改后端服务的标签值,把原本的python改成pythonx, 这样一来就无法实现pod亲和了
创建修改后的后端服务
root@master1:/pod# kubectl apply -f podaffinity-preferredDuring.yaml
查看资源,可以看见被调度到了另一个node上了
总结:在软亲和的情况下,新建的pod如果匹配到了另一个pod标签,就调度到同一个节点运行
如果无法匹配就根据kubelet随机调度到其它节点运行,并不强制
三、创建后端容器,与nginx容器做硬亲和
当pod之间的关联性比较强,强依赖的情况下,如果都运行在同一个节点上,性能就会强些
1、前端服务不变,重新创建后端服务
1、创建资源文件
root@master1:/pod# cat podaffinity-requiredDuring.yaml
kind: Deployment
#apiVersion: extensions/v1beta1
apiVersion: apps/v1
metadata:
labels:
app: myserver-tomcat-app2-deployment-label
name: myserver-tomcat-app2-deployment
namespace: myserver
spec:
replicas: 2
selector:
matchLabels:
app: myserver-tomcat-app2-selector
template:
metadata:
labels:
app: myserver-tomcat-app2-selector
spec:
containers:
- name: myserver-tomcat-app2-container
image: tomcat:7.0.94-alpine
imagePullPolicy: IfNotPresent
#imagePullPolicy: Always
ports:
- containerPort: 8080
protocol: TCP
name: http
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: #硬亲和
- labelSelector:
matchExpressions: #正则匹配
- key: project
operator: In
values:
- python
topologyKey: "kubernetes.io/hostname"
namespaces:
- myserver
2、创建资源
root@master1:/pod# kubectl apply -f podaffinity-requiredDuring.yaml
查看资源,新建的两个副本pod与前端服务都调度在同一个node节点
2、测试无法匹配到条件时,调度结果
先删除原本的后端服务
root@master1:/pod# kubectl delete -f podaffinity-requiredDuring.yaml
修改后端服务yaml文件,把匹配值python改成pythonx,再重新创建后端服务
重新创建
root@master1:/pod# kubectl apply -f podaffinity-requiredDuring.yaml
查看资源,显示创建失败,因为要根据亲和做标签匹配,但是无法找到符合的标签
总结: 使用pod硬亲和时,新建的pod必须要匹配到设置了相同标签的pod,从而调度到这个pod的节点上运行,否正无法被调度
反亲和的使用场景与亲和相反,需要把不同关系只需把yaml文件中podAffinity字符改成podAntiAffinity即可
更多推荐
所有评论(0)