容器技术

[转]kubernetes 亲和性调度详解

2020-09-14  本文已影响0人  贺大伟

感谢作者,原文链接:https://www.shuzhiduo.com/A/o75NZ1rj5W/

文章目录

1 概述:

2 场景一:调度到一组具有相同特性的主机上(label+nodeSelector)

3 场景二:部署的应用不想调度到某些节点上(nodeaffinity)

4 场景三:部署的应用关联性很强,需要尽量在一个节点上

5 场景四:部署应用需要互斥,不能同时运行在一台主机上,会冲突

6 高级特性Taints and tolerations

概述:

默认情况下创建pod调度是根据kubernetes scheduler默认的调度规则去进行调度的,但有些时候,有些应用有一些特殊的需求比如指定部署到对应的节点、多个pod之间需要部署在不同一个节点,需要互斥、pod和pod间相互交流比较频繁需要跑在同一个节点,需要亲和。这时就需要灵活配置scheduler来实现了。

场景一:调度到一组具有相同特性的主机上(label+nodeSelector)

比如在整个kubernetes集群内,有一组配置比较好的服务器,然后有一些特殊的应用需要对硬件配置有需求,需要被调度到这些服务器上,这时可以通过kubernetes的label+nodeSelector去实现,实际上在kubernetes里面label是一个非常灵活的概念,kubernetes内不同资源对象之间的关联就是通过label的方式去进行的。

我们给那些配置高的节点打上个label

给高配置的host打上一个label Configuration=hight(这里以rke-node2为例)

kubectl label node rke-node2 Configuration=hight

在show labels可以看见我们刚刚打上去的label

创建pod使用nodeSelector调度到指定label的节点上

mysql-deployment.yaml

apiVersion: apps/v1beta1

kind: Deployment

metadata:

name: mysql-2

spec:

selector:

  matchLabels:

    app: mysql

template:

  metadata:

    labels:

      app: mysql

  spec:

    containers:

    - image: mysql:5.6

      name: mysql

      env:

      - name: MYSQL_ROOT_PASSWORD

        value: password

      ports:

      - containerPort: 3306

        name: mysql

    nodeSelector:

      Configuration: hight

配置nodeSelector调度到Configuration:hight的host上

创建deployment

kubectl apply -f mysql-deployment.yaml

查看pod被调度到label为 Configuration: hight的host上了

场景二:部署的应用不想调度到某些节点上(nodeaffinity)

比如在一个kubernetes集群内,需要将应用部署到指定标签的机器上,但如果没有的话这类机器的话,就按正常调度规则进行调度。这时通过nodeSelector就无法实现这个需求了,在kubernetes内可以通过nodeaffinity的方式的去实现。

nodeaffinity和nodeSelecotr非常类似,都是node层面的调度策略的配置,但区别是nodeSelect功能比较单一,只能根据label选择对应的主机,而nodeaffinity更加灵活,nodeaffinity有两种调度类型requiredDuringSchedulingIgnoredDuringExecution(硬要求)和preferredDuringSchedulingIgnoredDuringExecution(软要求),两种类型区别在于,硬要求要求调度时必须满足设置的调度规则,否则抛异常调度失败,而软要求,只是调度时优先考虑设置的调度规则,当达不到设置的规则时,则按kube-scheduler默认的调度策略进行调度。nodeaffinity还支持多种规则匹配条件的配置如

In:label 的值在列表内

NotIn:label 的值不在列表内

Gt:label 的值大于设置的值

Lt:label 的值小于设置的值

Exists:设置的label 存在

DoesNotExist:设置的 label 不存在

apiVersion: apps/v1beta1

kind: Deployment

metadata:

name: mysql-2

spec:

selector:

  matchLabels:

    app: mysql

template:

  metadata:

    labels:

      app: mysql

  spec:

    containers:

    - image: mysql:5.6

      name: mysql

      env:

      - name: MYSQL_ROOT_PASSWORD

        value: password

      ports:

      - containerPort: 3306

        name: mysql

    affinity:

      nodeAffinity:

        requiredDuringSchedulingIgnoredDuringExecution:

          nodeSelectorTerms:

          - matchExpressions:

            - key: kubernetes.io/hostname

              operator: NotIn

              values:

              - rke-node3

              - rke-node4

        preferredDuringSchedulingIgnoredDuringExecution:

        - weight: 1

          preference:

            matchExpressions:

            - key: disk_type

              operator: In

              values:

              - ssd

如上所例,要求pod不能被调度到rke-node3和rke-node4上,但如果有满足dis_type=ssd的label的节点则优先选择。

如果在 nodeAffinity 类型中指定了多个 nodeSelectorTerms,那么 pod 将会被调度到只要满足其中一个 nodeSelectorTerms 的 node 上。

如果在 nodeSelectorTerms 中指定了多个 matchExpressions,那么 pod 将会被调度到 满足所有 matchExpressions 的 node 上。

场景三:部署的应用关联性很强,需要尽量在一个节点上

比如在kubernetes集群,有些pod和pod之间的交互很频繁,这时就需要将它们尽可能的调度到一台主机上,通过pod与pod之间的关系来选择调度,这时候我们就可以使用podaffinity。根nodeaffinity一样,podaffinity也有两种调度类型requiredDuringSchedulingIgnoredDuringExecution(硬要求)和preferredDuringSchedulingIgnoredDuringExecution(软要求),多种规则匹配条件配置。

例 部署一个nginx和mysql因为nginx和mysql之间的交互很频繁,所以尽量将他们部署在一个host上。

先启动一个nginx。

apiVersion: v1

kind: Pod

metadata:

  name: nginx

  labels:

    app: nginx

spec:

  containers:

  - name: nginx

    image: nginx

启动mysql

apiVersion: v1

kind: Pod

metadata:

  name: mysql

  labels:

    app: mysql

spec:

  containers:

  - name: mysql

    image: nginx

    env:

    - name: "MYSQL_ROOT_PASSWORD"

      value: "123456"

  affinity:

    podAffinity:

      requiredDuringSchedulingIgnoredDuringExecution:

      - labelSelector:

          matchExpressions:

          - key: app

            operator: In

            values:

            - nginx

        topologyKey: kubernetes.io/hostname

topologyKey可以设置成如下几种类型

kubernetes.io/hostname#Node

failure-domain.beta.kubernetes.io/zone#Zone

failure-domain.beta.kubernetes.io/region #Region

可以设置node上的label的值来表示node的name,zone,region等信息,pod的规则中指定topologykey的值表示指定topology范围内的node上运行的pod满足指定规则

这里我们配置podaffinity,mysql会调度到有app:nginx这个label的pod的host上,所以你部署出来的mysql会调度到有nginx的pod上,因为默认部署出来的nginx就自带app:nginx这个label。

场景四:部署应用需要互斥,不能同时运行在一台主机上,会冲突

我们继续以我们刚刚的nginx+mysql这个应用组合为例,现在我们修改mysql的podaffinity为podAntiAffinity

apiVersion: v1

kind: Pod

metadata:

  name: mysql

  labels:

    app: mysql

spec:

  containers:

  - name: mysql

    image: nginx

    env:

    - name: "MYSQL_ROOT_PASSWORD"

      value: "123456"

  affinity:

    podAntiAffinity:

      requiredDuringSchedulingIgnoredDuringExecution:

      - labelSelector:

          matchExpressions:

          - key: app

            operator: In

            values:

            - nginx

        topologyKey: kubernetes.io/hostname

将podaffinity改为podAntiAffinity这样调度mysql这个pod时会避开有label为app:nginx的pod的主机

高级特性Taints and tolerations

Taints其实根nodeaffinity正好相反,nodeaffinity是将设置策略的pod调度到期望的节点上,而taints正好相反,如果一个节点被标记为taints,除非pod配置了tolerations,否则是不会被允许调度过来在生产环境中我们一般会将master节点配置Taints,因为master只跑kubernetes 系统组件,如果跑了用户应用pod容易把资源耗尽,造成master节点崩溃,当然后期如果要添加额外的系统组件,这时就可以通过给对应的pod配置toleration。

设置rke-node2不能被调度

kubectl taint nodes rke-node2 key=value:NoSchedule

value可以配置多个值如

NoSchedule:不能调度,当之前调度的不管。

PreferNoSchedule:尽量不调度上去,其实就是Noschedule软策略版。

NoExecute:不能调度,但之前已经调度上去的也会自动迁移走。

NoSchedule更像执行kubectl cordon xxx

NoExecute更想执行kubectl cordon xxx+kubectl drain

取消taints

kubectl taint nodes rke-node2 key-

如何让pod调度到配置了taints主机上?

通过配置tolerations,可以让pod调度到配置了taints的机器上

apiVersion: apps/v1beta1

kind: Deployment

metadata:

name: mysql-2

spec:

selector:

  matchLabels:

    app: mysql

template:

  metadata:

    labels:

      app: mysql

  spec:

    containers:

    - image: mysql:5.6

      name: mysql

      env:

      - name: MYSQL_ROOT_PASSWORD

        value: password

      ports:

      - containerPort: 3306

        name: mysql

    tolerations:

    - key: "key"

      operator: "Equal"

      value: "value"

      effect: "NoSchedule"

上一篇下一篇

猜你喜欢

热点阅读