Notice: Constant WP_DEBUG already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 12

Notice: Constant WP_DEBUG_LOG already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 13

Notice: Constant WP_DEBUG_DISPLAY already defined in /var/www/html/wordpress/wp-content/plugins/changyan/sohuchangyan.php on line 14
【转载】Kubernetes 1.6新特性系列 | 高级调度 – zoues

LOADING

Follow me

【转载】Kubernetes 1.6新特性系列 | 高级调度
四月 23, 2017|DockerPaaS

【转载】Kubernetes 1.6新特性系列 | 高级调度

【转载】Kubernetes 1.6新特性系列 | 高级调度

作者注:这是深入Kubernetes 1.6特性系列的第四篇。


导读:

Kubernetes 1.6高级调度的新特性主要集中在四个方面:

  • Node的亲和性和反亲和性(Affinity/Anti-Affinity)

  • Node的污点和容忍(Taints and Tolerations)

  • Pod的亲和性和反亲和性(Affinity/Anti-Affinity)

  • 自定义调度器

1

    简介   

Kubernetes的调度器在大多数情况下能过运行的很好,例如:它能够将Pod调度到有充足资源的Node上;它能够将一组Pod(ReplicaSet, StatefulSet,等)均匀的调度到不同的Node上;它尽力平衡各个节点的资源使用率等。

但有些时候您会想控制您的Pod如何调度,例如:可能您想让一些Pod被确定调度到某些使用特殊硬件的节点上,或者您想让交互频繁的服务一起调度,或者您想让一些Node只给特定的一些用户提供服务等等。最终,您对于应用程序调度和部署的需求永远要比Kubernetes提供的多。因此,Kubernetes 1.6提供了四个高级高级调度功能:节点亲和性和反亲和性污点和容忍Pod亲和性/反亲和性自定义调度。这四个特性在Kubernetes 1.6版本中都是beta版。

2

Node亲和性/反亲和性

Node亲和性/反亲和性是在Node上设置如何被Scheduler选择的规则一种方式。此功能是自Kubernetes 1.0版本以来在Kubernetes中的nodeSelector的功能的通用化。规则是使用在Pod中指定和选择器上自定义的标签等用户熟悉的概念定义的,并且他们是必需的或者首选的,这取决于您希望调度程序强制执行他们的严格程度。

A

必需的规则(Required)

只有满足必需的规则的Pod才会被调度到特定的Node上。如果没有Node匹配条件(加上所有其他所有正常的条件,例如为Pod请求提供足够的可用资源),否则Pod不会被调度。必需满足的规则在nodeAffinityrequiredDuringSchedulingIgnoredDuringExecution字段中指定。

例如,如果我们要求在多可用区域(Multiple Zones)的us-central1-a(GCE)区域中的节点上进行调度,则可以将以下的关联规则指定为Pod规范(Spec)的一部分:

affinity:   nodeAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:      nodeSelectorTerms:        - matchExpressions:          - key: "failure-domain.beta.kubernetes.io/zone"
           operator: In            values: ["us-central1-a"]

"IgnoredDuringExecution"意味着如果Node上的标签发生更改,并且亲和性的规则不再满足时选择忽略。这个在未来会计划实现。

"requiredDuringSchedulingRequiredDuringExecution"意味着一旦他们不满足节点亲和性规则,将从Node上驱逐不再匹配规则的Pod

B

首选的规则(Preferred)

首选规则意味着如果节点与规则匹配,则将优先选择它们,并且仅当没有优选节点可用时才选择非优选节点。您可以选择使用首选规则,而不是通过必需规则强制将Pod部署到GCEus-central1-a区域中的节点上。使用首选规则,则需指定preferredDuringSchedulingIgnoredDuringExecution

affinity:
 nodeAffinity:
   preferredDuringSchedulingIgnoredDuringExecution:
     nodeSelectorTerms:        - matchExpressions:          - key: "failure-domain.beta.kubernetes.io/zone"            operator: In            values: ["us-central1-a"]

Node的反亲和性能够使用负操作符(NotIn, DoesNotExist等)来表示。下面的例子说明了如何禁止您的Pod被调度到us-central1-a的区域中:

affinity:
 nodeAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:

     nodeSelectorTerms:      - matchExpressions:        - key: "failur-domain.beta.kubernetes.io/zone"          operator: NotIn          values: ["us-central1-a"]

可以使用的操作符有:In, NotIn, Exists, DoesNotExist, Gt, 和Lt

这个特性还有一些另外的使用场景,比如需要在调度上严格区别Node上的硬件架构操作系统版本,或者专用的硬件等。

Node的亲和性和反亲和性在Kubernetes 1.6版本中是Beta版。

3

污点和容忍(Taints and Tolerations)

此功能允许您标记一个Node(“受污染”,“有污点”),以便没有Pod可以被调度到此节点上,除非Pod明确地“容忍”污点。标记的是Node而不是Pod(如节点的亲和性和反亲和性),对于集群中大多数Pod应该避免调度到特定的节点上的功能特别有用,例如,您可能希望主节点(Master)标记为仅可调度Kubernetes系统组件,或将一组节点专用于特定的用户组,或者让常规的Pod远离具有特殊硬件的Node,以便为有特殊硬件需求的Pod留出空间。

使用kubectl命令可以设置节点的“污点”,例如:

kubectl taint nodes node1 key=value:NoSchedule

创建一个污点并标记到Node,那些没有设置容忍的Pod(通过key-value方式设置NoSchedule,这是其中一个选项)不能调度到该Node上。其他污点的选项是PerferredNoSchedule,这是NoSchedule首选版本;还有NoExecute,这个选项意味着在当Node被标记有污点时,该Node上运行的任何没有设置容忍的Pod都将被驱逐。容忍将被添加到PodSpec中,看起来像这样:

tolerations:    - key: "key"     operator: "Equal"     value: "value"     effect: "NoSchedule"

除了将污点和容忍(Taints and Tolerations)特性在Kubernetes 1.6中移至Beta版外,我们还引入了一个使用污点和容忍的Alpha的特性:允许用户自定义一个Pod被绑定到Node上后遇到了诸如网络分区的问题时的行为(可能Pod希望长时间允许在这个Node上,或者网络分区会很快恢复),而不是现在默认的等待五分钟超时。更详细的信息,请参阅文档

4

Pod的亲和性和反亲和性

Node的亲和性和反亲和性允许您基于节点的标签来限制Pod的调度行为。但是,如果您想要指定Pod的亲和关系时这种方法就无法奏效了。例如,如何实现在一个服务或者相关的服务中聚合Pod或将Pod均匀分布?为此,您可以使用Pod的亲和性和反亲和性特性,它在Kubernetes 1.6中也是Beta版。

我们来看一个例子。假设您在服务S1中有个前端应用,它经常与服务S2的后端应用进行通信。因此,您希望这两个服务共同位于同一个云提供商的区域中,但您不需要手动选择区域(如果有些区域暂时不可用),希望将Pod重新调度到另一个(单个的)区域。您可以像这样指定Pod的亲和性和反亲和性规则(假设您将该服务的Pod命名为*”service=S2″,另外一个服务的Pod“service=S1″):

affinity:
 podAffinity:
   requiredDuringSchedulingIgnoredDuringExecution:
   - labelSelector:
     matchExpressions:      - key: service        operator: In        values: [“S1”]    topologyKey: failure-domain.beta.kubernetes.io/zone

如同Node的亲和性和反亲和性,也有一个preferredDuringSchedulingIgnoredDuringExecution变量。

Pod的亲和性和反亲和性非常灵活。想象一下,您已经分析了您的服务的性能,发现来自服务S1的容器会干扰运行在同一Node上的服务S2的容器,这可能是由于缓存干扰效应或者网络连接饱和引起,或者也许是由于安全性问题,您不会想要S1S2的容器共享一个Node。要实现这些规则,只需对上述代码段进行两次更改即可将podAffinity更改为podAntiAffinity”,并将topologyKey更改为kubernetes.io/hostname*即可。

5

自定义调度器

如果Kubernetes Scheduler的这些特性没能足够满足您控制负载的需求,您可以在将任意子集的Pod的调度任务交给您自己的自定义调度器,自定义的调度器可以跟默认的调度器(Kubernetes Scheduler)一起运行,或者替代默认的调度器。多调度器(Multiple schedulers)Kubernetes 1.6中是Beta版。

在默认的情况下,每个新的Pod都使用默认的调度器进行调度。但是如果您提供了自定义调度器的名称,默认的调度器会忽略Pod的调度请求,允许您的自定义调度器对Pod进行调度。看看下面的例子:

在Pod的规范(Spec)中制定调度器的名字:

apiVersion: v1
kind
: Pod
metadata
:  
 name
: nginx    
 labels
:    
   app: nginx
spec
:
 schedulerName: my-scheduler  containers:  - name: nginx    image: nginx:1.10

如果我们在没有部署自定义调度器的情况下创建了这个Pod,结果会是默认的调度器将忽略这个Pod,它将处于Pending状态。因此,我们需要一个自定义调度程序来查找和调度其schedulerName字段为my-schedulerPod

自定义调度语言可以用任何语言编写,调度策略根据需要可以简单也可以复杂。这是一个非常简单的例子,它使用Bash编写,它可以为Pod随机分配一个Node。请注意,您需要让它与kubectl proxy一起运行:

#!/bin/bash
SERVER='localhost:8001' # Proxy address for apiServer
while
true;
do

   # Get all pods, and pod's properties    for PODNAME in $(kubectl --server $SERVER get pods -o json
           |
jq '.items[]
           | select(.spec.schedulerName == "my-scheduler")
           | select(.spec.nodeName == null)
           | .metadata.name'
| tr -d '"');
   do
       # Get all nodes        NODES=($(kubectl --server $SERVER get nodes -o json
               |
jq '.items[].metadata.name'
               |
tr -d '"')
)        NUMNODES=${#NODES[@]}
       
       # Choose a node randomly        CHOSEN=${NODES[$[ $RANDOM % $NUMNODES ]]}
       
       # Bind a pod($PODNAME) to a node($CHOSEN)        curl --header "Content-Type:application/json"               --request POST
            --data
           '
{
                "apiVersion":"v1",
                "kind": "Binding",
                "metadata": {
                    "name": "'$PODNAME'"
                },
                "target": {
                    "apiVersion": "v1",
                    "kind": "Node",
                    "name": "'$CHOSEN'"
                }
            }'

            http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/        echo "Assigned $PODNAME to $CHOSEN"    done    sleep 1
done

Kubernetes 1.6release notes关于这个特性有更多的介绍,包括您已经使用了这些(其中一个或者多个)特性的Alpha版本改如何进行配置的细节(这些事必需的,因为对于这些特性,从AlphaBeta的转变是突破性的)。

6
致谢

本文描述的这些新特性和功能,包括AlphaBeta版本,都是社区的工程师的努力,他们来自Google, Huawei, IBM, Rad Hat等公司,在此表示感谢。

7
加入我们

通过每周的社区会议发出您的声音:

非常感谢您所做的贡献!

作者:

–Ian Lewis, Developer Advocate, and David Oppenheimer, Software Engineer, Google

8
加入容器时代

容器时代公众号的目的是希望能够传播容器技术和理念,让更多的人能够享受到这场技术革命带来的好处。虽然我们不是大牛,对容器技术生态的了解和认识也还不够深刻,但是我们乐于分享,乐于交流。不管读者的你是学生,还是工程师,甚至都不是,我们都欢迎你加入进来,可以一起写文章、翻译文章,也可以一起分享经验、聊聊踩过的那些坑!为此特意建立了一个微信群,长按识别下方二维码加入,我们以梦为马,一起前行!

(微信群已满,请添加k8stimes或者扫下面二维码添加好友,小助手会将您拉入群聊)

Kubernetes 1.6新特性系列 | 高级调度

还可以关注我们的公众号,Kubernetes最新最热的姿势都在这里:

Kubernetes 1.6新特性系列 | 高级调度

9
架构真经

《架构真经:互联网技术架构的设计原则(原书第2版)》即将震撼上市,关注容器时代公众号可以有机会获得亲笔签名图书,赶快关注!!

Kubernetes 1.6新特性系列 | 高级调度

版权声明:任何转载需全文转载并保留来源(微信公众号容器时代),同时转载容器时代的二维码,否则视作侵权。

no comments
Share