K8S pod 亲和与反亲和 (podAffinity与podAntiAffinity)

目录

1、 简介:

2、配置须知:

示例:

一、创建前端nginx容器

二、创建后端容器,与nginx容器做软亲和

三、创建后端容器,与nginx容器做硬亲和


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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值