美文网首页容器技术
[转]kubernetes 亲和性调度详解

[转]kubernetes 亲和性调度详解

作者: 贺大伟 | 来源:发表于2020-09-14 10:44 被阅读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"

    相关文章

      网友评论

        本文标题:[转]kubernetes 亲和性调度详解

        本文链接:https://www.haomeiwen.com/subject/bxnaektx.html