Kubernetes调度之Pod亲和性

Kubernetes调度中的Pod亲和性

abstract.png

Pod亲和性

节点亲和性,是基于节点的标签对Pod进行调度。而Pod亲和性则可以实现基于已经在节点上运行Pod的标签来约束新Pod可以调度到的节点。具体地,如果X上已经运行了一个或多个满足规则Y的Pod,则这个新Pod也应该运行在X上。其中,X可以是节点、机架、可用性区域、地理区域等。可通过topologyKey字段定义拓扑域X,其取值是节点标签的键名Key;而Y则是Kubernetes尝试满足的规则。可以通过标签选择器的形式来定义。此外,Pod亲和性使用podAffinity字段,其下支持两种亲和性:

  • 「requiredDuringSchedulingIgnoredDuringExecution」:requiredDuringScheduling表明其是一个强制性的调度,调度器只有在规则被满足的时候才能执行调度;而IgnoredDuringExecution则表明其不会影响已在节点上运行的Pod

  • 「preferredDuringSchedulingIgnoredDuringExecution」:preferredDuringScheduling表明其是一个偏好性的调度,调度器会根据偏好优先选择满足对应规则的节点来调度Pod。但如果找不到满足规则的节点,调度器则会选择其他节点来调度Pod。而IgnoredDuringExecution则表明其不会影响已在节点上运行的Pod

强制性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的前端服务

# 应用的前端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-frontendspec:    # Pod副本数量  replicas: 2  selector:    matchLabels:      app: frontend  # Pod模板  template:    metadata:      # 标签信息: 应用的前端服务      labels:        app: frontend    spec:      # 容器信息      containers:      - name: my-app-frontend        image: jocatalin/kubernetes-bootcamp:v1

效果如下所示,可以看到前端服务运行了2个Pod。分别在my-k8s-cluster-multi-node-worker2、my-k8s-cluster-multi-node-worker3节点上

figure 1.jpeg

现在我们来部署应用的后端服务,这里我们期望后端服务的Pod能够运行在前端服务的Pod所在的节点上。这时就可以通过节点亲和性实现。具体地:

  • 首先,使用podAffinity来定义Pod亲和性规则,使用requiredDuringSchedulingIgnoredDuringExecution定义强制性的调度规则

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是前端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息,这里我们使用的是节点主机名。对于 此时即将被调度的新Pod 与 标签选择器所确定的Pod 来说,它们各自运行节点的主机名是相同的。即,后端服务的Pod 必须被调度到 与前端服务的Pod所在节点拥有相同主机名 的节点上

这样即可实现后端服务的Pod所在的节点上,一定存在前端服务的Pod

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 4  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:    # 亲和性      affinity:        # Pod亲和性规则        podAffinity:          # 强制性的调度规则, 但不会影响已在节点上运行的Pod          requiredDuringSchedulingIgnoredDuringExecution:          - topologyKey: kubernetes.io/hostname            # 标签选择器            labelSelector:              matchLabels:                app: frontend      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示。后端服务的5个Pod均运行在my-k8s-cluster-multi-node-worker2、my-k8s-cluster-multi-node-worker3节点上

figure 2.jpeg

偏好性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的前端服务

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 2  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示,可以看到后端服务运行了2个Pod。分别在my-k8s-cluster-multi-node-worker、my-k8s-cluster-multi-node-worker3节点上。而通过标签信息可知,这两个节点都位于上海

figure 3.jpeg

现在我们来部署应用的缓存服务,这里我们期望 缓存服务Pod所在的节点 能够尽可能与 前端服务Pod所在的节点 在通过一个地理区域,以减少网络通讯的延迟。

  • 首先,使用podAffinity来定义Pod亲和性规则,使用preferredDuringSchedulingIgnoredDuringExecution定义偏好性的调度规则。可通过权重值来定义对节点偏好,权重值越大优先级越高。其中,权重范围: 1~100

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是前端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息,这里我们使用的是节点的Region标签地理位置。此时即将被调度的新Pod 将会更倾向于调度到 与标签选择器所确定的Pod的所在节点 具有相同Region标签值的节点当中。即,缓存服务的Pod的所在节点 与 后端服务的Pod的所在节点 将会尽可能得位于同一个地理区域(具有相同Region标签值)

# 应用的缓存服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-redisspec:    # Pod副本数量  replicas: 4  selector:    matchLabels:      app: redis  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: redis    spec:    # 亲和性      affinity:        # Pod亲和性规则        podAffinity:          # 偏好性的调度规则, 但不会影响已在节点上运行的Pod          preferredDuringSchedulingIgnoredDuringExecution:          - weight: 70  # 权重范围: 1~100, 权重值越大, 优先级越高            podAffinityTerm:              topologyKey: Region              # 标签选择器              labelSelector:                matchLabels:                  app: backend                        # 容器信息      containers:      - name: my-app-redis        image: redis:3.2-alpine

效果如下所示。缓存服务的4个Pod均运行同样位于上海的节点上。需要注意的是,由于这里是偏好性调度。故如果当上海的节点由于某种原因导致无法调度Pod到其上运行,调度器选择其他地域的节点进行调度也是合法的、允许的。比如这里位于广州的节点

figure 4.jpeg

Pod反亲和性

而Pod反亲和性,同样也是基于已经在节点上运行Pod的标签来约束新Pod可以调度到的节点。只不过其与Pod亲和性恰恰相反。即,如果X上已经运行了一个或多个满足规则Y的Pod,则这个新Pod不应该运行在X上。此外,Pod反亲和性使用podAntiAffinity字段,其下同样支持两种反亲和性:requiredDuringSchedulingIgnoredDuringExecution 强制性调度、preferredDuringSchedulingIgnoredDuringExecution 偏好性调度

强制性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的后端服务。这里为了便于后续演示,我们规定后端服务的Pod只允许运行在上海的节点上

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 5  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:    # 配置节点选择器, 要求K8s只将该Pod部署到包含标签Region=ShangHai的节点上      nodeSelector:        Region: ShangHai      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示,可以看到后端服务运行了5个Pod。分别运行在位于上海的my-k8s-cluster-multi-node-worker、my-k8s-cluster-multi-node-worker3、my-k8s-cluster-multi-node-worker5节点上

figure 5.jpeg

现在我们来部署应用的前端服务,同时基于某种特殊原因的考量,我们期望该应用的前、后端服务的Pod分别运行在不同区域。即前端服务的Pod的运行在位于上海的节点,则我们希望后端服务的Pod运行在除上海之外的节点当中。这时就可以通过节点反亲和性实现。具体地:

  • 首先,使用podAntiAffinity来定义Pod反亲和性规则,使用requiredDuringSchedulingIgnoredDuringExecution定义强制性的调度规则

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是后端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息,这里我们使用的是节点的Region标签地理位置。对于 此时即将被调度的新Pod 与 标签选择器所确定的Pod 来说,它们各自运行节点的地理位置是不同的。即,后端服务的Pod 必须被调度到 与前端服务的Pod所在节点拥有不同地理位置 的节点上

# 应用的前端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-frontendspec:    # Pod副本数量  replicas: 5  selector:    matchLabels:      app: frontend  # Pod模板  template:    metadata:      # 标签信息: 应用的前端服务      labels:        app: frontend    spec:    # 亲和性      affinity:        # Pod反亲和性规则        podAntiAffinity:          # 强制性的调度规则, 但不会影响已在节点上运行的Pod          requiredDuringSchedulingIgnoredDuringExecution:          - topologyKey: Region            # 标签选择器            labelSelector:              matchLabels:                app: backend      # 容器信息      containers:      - name: my-app-frontend        image: jocatalin/kubernetes-bootcamp:v1

效果如下所示。前端服务的5个Pod均运行在位于广州的my-k8s-cluster-multi-node-worker2、my-k8s-cluster-multi-node-worker4节点上

figure 6.jpeg

偏好性调度

这里提供了一个存在5个工作节点的K8s集群,然后我们使用Deployment部署了应用的后端服务

# 应用的后端服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-backendspec:    # Pod副本数量  replicas: 2  selector:    matchLabels:      app: backend  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: backend    spec:      # 容器信息      containers:      - name: my-app-backend        image: tutum/dnsutils        command:        - sleep        - infinity

效果如下所示,可以看到前端服务运行了2个Pod。分别在my-k8s-cluster-multi-node-worker、my-k8s-cluster-multi-node-worker4节点上

figure 7.jpeg

现在我们来部署应用的缓存服务,这里由于后端服务、缓存服务都非常占用资源。故我们提出下述调度要求

  1. 缓存服务Pod所在的节点 能够尽可能与 前端服务Pod所在的节点 不是同一个节点

  1. 缓存服务Pod所在的节点 能够尽可能与 前端服务Pod所在的节点 不在同一个地理区域

  1. 上诉2点均为偏好性要求,且第1点优先级是最高的

  • 首先,使用podAntiAffinity来定义Pod反亲和性规则,使用preferredDuringSchedulingIgnoredDuringExecution定义偏好性的调度规则。可通过权重值来定义偏好,权重值越大优先级越高。其中,权重范围: 1~100

  • 然后,使用标签选择器来确定Pod的范围,这里我们显然选择的是前端服务的Pod

  • 最后,使用topologyKey来定义拓扑域信息。这里我们分别使用了节点主机名、地理位置。以此实现即将被调度的新Pod 将会更倾向于调度到 与标签选择器所确定的Pod的所在节点 具有不同节点 或 不同地理区域的节点上

# 应用的缓存服务apiVersion: apps/v1kind: Deploymentmetadata:    name: my-app-redisspec:    # Pod副本数量  replicas: 4  selector:    matchLabels:      app: redis  # Pod模板  template:    metadata:      # 标签信息: 应用的后端服务      labels:        app: redis    spec:    # 亲和性      affinity:        # Pod反亲和性规则        podAntiAffinity:          # 偏好性的调度规则, 但不会影响已在节点上运行的Pod          preferredDuringSchedulingIgnoredDuringExecution:          - weight: 100  # 权重范围: 1~100, 权重值越大, 优先级越高            podAffinityTerm:              topologyKey: kubernetes.io/hostname              # 标签选择器              labelSelector:                matchLabels:                  app: backend          - weight: 1  # 权重范围: 1~100, 权重值越大, 优先级越高            podAffinityTerm:              topologyKey: Region              # 标签选择器              labelSelector:                matchLabels:                  app: backend                        # 容器信息      containers:      - name: my-app-redis        image: redis:3.2-alpine

效果如下所示。缓存服务的4个Pod均运行在与后端服务Pod所在节点不同的节点上。但这里由于是偏好性调度,当最终结果未满足两个服务运行在不同的地理位置时,即调度器选择相同地理位置的节点进行调度也是合法的、允许的

figure 8.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤舞飘伶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值