Kubernetes亲和性调度在生产测试环境中的应用

阿凡达2018-07-06 09:50

本文中的案例是基于docker & kubernetes的测试环境部署,但kubernetes的特性分析是通用的,无国界的~


什么样的场景让我们想起了kubernetes亲和性调度?

通常产品线上和线下环境部署会存在一定的差异性,比如由于资源环境的限制没办法做到所有的应用都在不同的机器上搭建一套主备环境

但新增的、承担了重要业务逻辑的模块,主备切换的稳定性测试又是十分必要的环节。

在我所在的容器服务项目组(NCE-一个致力于Docker技术开发并大力实践容器化部署的高颜值开发团队)经历了控制云服务容器化部署kubernetes化调度历程后,显然环境的主备搭建要通过kubernetes的特性来实现。

Kubernetes的亲和性调度就顺理成章的成为了首选


什么是Kubernetes的亲和性调度?

使用过kubernetes的同学应该听说过nodeSelector,从名字可以看出这个特性是副本的节点选择器。

这里拿官网的例子说明:

  1. 通过给node打标签的方式,给node赋予专属特性 "disktype=ssd"

    kubectl label nodes <node-name> <label-key>=<label-value>
    例:
    kubectl label nodes kubernetes-foo-node-1.c.a-robinson.internal disktype=ssd
    
  2. 通过在pod模板中配置nodeSelector属性,调度到disktype为ssd类型的node

  3. apiVersion: v1 kind: Pod metadata: name: nginx labels: env: test spec: containers: - name: nginx image: nginx imagePullPolicy: IfNotPresent nodeSelector: disktype: ssd

那么亲和性(affinity)调度是怎么实现的pod自定义调度呢,它与nodeSelector有何不同?


1.Affinity种类

Affinity的概念是从kubernetes 1.2 开始引入,1.6上面作为beta feature,从时间节点上看应该使用起来优于nodeSelector,但前提依然是通过为node打标签来标记node,只是pod的模板部分使用了新的匹配方式。

下面介绍下affinity特性:

种类扩充:

  • Node affinity
  • Node anti-affinity (反亲和性,遇到这个条件就别调度了)
  • Pod affinity
  • Pod anti-affinity

条件匹配表达式扩充

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Exists:某个 label 存在
  • DoesNotExist: 某个 label 不存在
  • Gt:label 的值大于某个值(字符串比较)
  • Lt:label 的值小于某个值(字符串比较)

条件匹配支持hard/soft两种模式

  • Node affinity
    • requiredDuringSchedulingIgnoredDuringExecution(hard模式)
    • preferredDuringSchedulingIgnoredDuringExecution(soft模式)


  • Pod affinity

    • requiredDuringSchedulingIgnoredDuringExecution(hard模式)
    • preferredDuringSchedulingIgnoredDuringExecution(soft模式)

    两种模式的命名从字面上理解分为两个部分

    hard模式:

    1. requiredDuringScheduling 调度期间必须满足node affinity的表达式匹配才可以
    2. IgnoredDuringExecution 当pod调度成功后,如果node标签被更改至不满足pod模板中的要求,依然让pod正常运行在此node上。

    soft模式

    1. preferredDuringScheduling 调度期间优先满足node affinity的表达式匹配,若不满足则有调度器分配(这也是称为soft原因,不行就服从安排)
    2. 同上hard模式


2.Node Affinity应用

需求:搭建应用主备测试环境,并且要求两个相同的应用部署到同一个测试环境中的不同的机器上

在了解了affinity的特性之后,我们通过选用以下的模型来完成应用的主备搭建:

  • 表达式:Node affinity & Pod anti-affinity
  • 规则:In:label 的值在某个列表中
  • 模式:requiredDuringSchedulingIgnoredDuringExecution(hard模式)

2.1 首先给测试环境控制云节点打标签

我们为ci环境的两台控制云机器打上了ci1、ci2的group标签,同时环境标签env都为ci 

2.2 为应用副本配置node affinity & pod anti-affinity

预期实现:

  • node affinity: 调度到ci1或者ci2机器上
  • pod anti-affinity:如果node上已经有相同应用则调度到其他机器(ci1、ci2的另一台)

截取该应用副本部分的配置如下,另外副本个数要调整为2

        "affinity": {
          "nodeAffinity": {
            "requiredDuringSchedulingIgnoredDuringExecution": {
              "nodeSelectorTerms": [
                {
                  "matchExpressions": [
                    {
                      "key": "group",
                      "operator": "In",
                      "values": [
                        "ci1",
                        "ci2"
                      ]
                    }
                  ]
                }
              ]
            }
          },
          "podAntiAffinity": {
            "requiredDuringSchedulingIgnoredDuringExecution": [
              {
                "labelSelector": {
                  "matchExpressions": [
                    {
                      "key": "nce-app",
                      "operator": "In",
                      "values": [
                        "nce-hermes"
                      ]
                    }
                  ]
                },
                "topologyKey": "kubernetes.io/hostname"
              }
            ]
          }
        },

这样做来实现主备环境搭建还有这样几个好处:

  • 同一份配置管理应用
  • 一次更新依次部署两个节点上的应用

大家也可以自己试下这个方法来部署docker测试环境~


网易云容器服务为用户提供了无服务器容器,让企业能够快速部署业务,轻松运维服务。容器服务支持弹性伸缩、垂直扩容、灰度升级、服务发现、服务编排、错误恢复及性能监测等功能。

本文来自网易实践者社区,经作者张雨授权发布。