2017年1月29日星期日

OpenShift_049:Master 节点是如何调度 Node 节点的?

1. 默认的调度算法
步骤如下:
1.1 按顺序执行 predicates functions 过滤 node 节点
具体顺序如下:
(1) 匹配 pod node selector
如果 pod node selector 为空,那么表示匹配所有 node 节点。
(2) 有足够的资源运行 pod
如果 project 或 pod 没有定义 default resource limits,那么表示匹配所有 node 节点。
(3) pod 定义的端口在 node 上可以获得
pod 中定义的端口会映射到 node 的 TCP 活 UDP 端口。
(4) 有足够的 host volume
pod 中定义的 PVC 会请求 node 的文件系统,确保有足够的空间。
(5) 匹配 region label

符合以上要求(必须每一项都返回 true)的 node 节点,进入下一步。

1.2 按顺序执行 priorities functions 过滤 node 节点
合格的 node 节点将被打分,分数乘以权重 weight,最后得分范围是从 0 到 10,数字越高的 node 节点表示越有可能被调度。
具体顺序如下:
(1) 运行 pod 数量少的 node,得分高。
(2) 没有运行同一个 service 的 pod 的 node,得分高。
(3) 有不同 zone label 的 node,得分高。

1.3 选择最合适的 node 节点
计算最终的分数,总分数是累加(各项得分 * 各项权重)。
按照得分排序,分数高的 node 节点将被调度,分数相同的 node 节点,将随机选择一个。
另外,从 1.1 和 1.2 可以看出,node 和 pod 的 label 对 node 的选择影响很大。

说明:如果始终没有合格的 node 节点,pod 依然会创建,但是会一直处于 Pending 状态,直到等到一个合格的 node 节点。



2. region 和 zone 

2.1 zone
一个 zone 代表一组 node 集合,这些 node 共享相同的物理基础架构,比如机架、电源、网络、交换机,或者就是整个数据中心。
如果基础架构出现故障,会导致 zone 中的所有 node 都失败,进而运行其上的 pod 也都失败。
默认情况下,zone 是反亲和的:serviceAntiAffinity。这样设置的目的是让来自同一个 service 的 pod 运行在不同的 zone 中,防止因为某个 zone 的失败导致该应用 pod 全部失败。

2.2 region
一个 region 代表一组 node 集合,这些 node 是为了特别的用途而保留的,比如为了某个用户,为了某些关键服务,为了某些特别的硬件。
默认情况下,region 是亲和的:serviceAffinity。这样设置的目的是让来自同一个 service 的 pod 运行在同一个 region 中,以减少网络传输和网络延迟。

通常来说,同一个 region 包括不同的 zone,可以理解为一个地区有多个数据中心,防止因为单点物理故障,导致所有的 node 失败。

3. 多 master 环境 region 和 zone 的建议设置
oc label node master1.paascloud.example.com region=infra zone=east
oc label node master2.paascloud.example.com region=infra zone=west
oc label node node1.paascloud.example.com region=primary zone=east
oc label node node2.paascloud.example.com region=primary zone=north
oc label node node3.paascloud.example.com region=backup zone=west
oc label node node4.paascloud.example.com region=backup zone=south

4. 调度的配置文件
cat /etc/origin/master/scheduler.json
{
   "apiVersion": "v1",
   "kind": "Policy",
   "predicates": [
       {
           "name": "NoDiskConflict"
       },
       {
           "name": "NoVolumeZoneConflict"
       },
       {
           "name": "MaxEBSVolumeCount"
       },
       {
           "name": "MaxGCEPDVolumeCount"
       },
       {
           "name": "GeneralPredicates"
       },
       {
           "name": "PodToleratesNodeTaints"
       },
       {
           "name": "CheckNodeMemoryPressure"
       },
       {
           "name": "CheckNodeDiskPressure"
       },
       {
           "name": "MatchInterPodAffinity"
       },
       {
           "argument": {
               "serviceAffinity": {
                   "labels": [
                       "region"
                   ]
               }
           },
           "name": "Region"
       }
   ],
   "priorities": [
       {
           "name": "LeastRequestedPriority",
           "weight": 1
       },
       {
           "name": "BalancedResourceAllocation",
           "weight": 1
       },
       {
           "name": "SelectorSpreadPriority",
           "weight": 1
       },
       {
           "name": "NodePreferAvoidPodsPriority",
           "weight": 10000
       },
       {
           "name": "NodeAffinityPriority",
           "weight": 1
       },
       {
           "name": "TaintTolerationPriority",
           "weight": 1
       },
       {
           "name": "InterPodAffinityPriority",
           "weight": 1
       },
       {
           "argument": {
               "serviceAntiAffinity": {
                   "label": "zone"
               }
           },
           "name": "Zone",
           "weight": 2
       }
   ]
}

5. 查看默认的 node selector
cat /etc/origin/master/master-config.yaml | grep defaultNodeSelector

6. 修改 Project 的 openshift.io/node-selector
oc edit -o json namespace default
输出如下:
{
    "kind": "Namespace",
    "apiVersion": "v1",
    "metadata": {
        "name": "default",
        "selfLink": "/api/v1/namespaces/default",
        "uid": "505e20bc-dee6-11e6-9eb6-080027fc450b",
        "resourceVersion": "875",
        "creationTimestamp": "2017-01-20T07:59:05Z",
        "annotations": {
            "openshift.io/node-selector": "",
            "openshift.io/sa.initialized-roles": "true",
            "openshift.io/sa.scc.mcs": "s0:c6,c0",
            "openshift.io/sa.scc.supplemental-groups": "1000030000/10000",
            "openshift.io/sa.scc.uid-range": "1000030000/10000"
        }
    },
    "spec": {
        "finalizers": [
            "kubernetes",
            "openshift.io/origin"
        ]
    },
    "status": {
        "phase": "Active"
    }
}

也可以用命令行
oc annotate namespace applications openshift.io/node-selector='app=yes' --overwrite
oc annotate namespace applications openshift.io/node-selector- --overwrite

参考文献:
1. https://my.oschina.net/jxcdwangtao/blog/824965
2. https://github.com/kubernetes/kubernetes/blob/3fd14d97fb13ba2849e0c908aaff18efcece70c1/pkg/api/types.go#L2146

没有评论: