zoukankan      html  css  js  c++  java
  • k8s-高级调度方式-二十一

    两类:

    • 节点选择器:nodeSelector(给node打上标签,pod通过标签预选节点),nodeName
    • 节点亲和调度:nodeAffinity

    1、节点选择器(nodeSelector,nodeName)

    [root@master ~]# kubectl explain pods.spec.nodeSelector
    
    [root@master schedule]# pwd
    /root/manifests/schedule
    
    [root@master schedule]# vim pod-demo.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-demo
      namespace: default
      labels:
        app: myapp
        tier: frontend
      annotations: 
        mageedu.com/created-by: "cluster admin"
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
      nodeSelector:    #节点选择器
        disktype: ssd    #该pod运行在有disktype=ssd标签的node节点上
    [root@master schedule]# kubectl apply -f pod-demo.yaml 
    pod/pod-demo created
    
    [root@master schedule]# kubectl get pods -o wide
    NAME       READY   STATUS    RESTARTS   AGE     IP           NODE     NOMINATED NODE   READINESS GATES
    pod-demo   1/1     Running   0          8m13s   10.244.1.6   node01   <none>           <none>
    
    [root@master schedule]# kubectl get nodes --show-labels |grep node01
    node01   Ready    <none>   76d   v1.13.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=node01
    
    #可见新创建的pod已经运行在node01上了,因为node01上有disktype=ssd标签;

    接下来我们给node02打上标签,修改一下资源定义清单文件,再创建pod:

    将node02打上标签,pod资源清单里面的节点选择器里,改为和node02一样的标签;

    [root@master schedule]# kubectl delete -f pod-demo.yaml
    
    [root@master ~]# kubectl label nodes node02 disktype=harddisk
    node/node02 labeled
    
    [root@master schedule]# vim pod-demo.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-demo
      namespace: default
      labels:
        app: myapp
        tier: frontend
      annotations:
        mageedu.com/created-by: "cluster admin"
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
      nodeSelector:
        disktype: harddisk        
    
    [root@master schedule]# kubectl get nodes --show-labels |grep node02
    node02   Ready    <none>   76d   v1.13.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=harddisk,kubernetes.io/hostname=node02
    
    [root@master schedule]# kubectl get pods -o wide
    NAME       READY   STATUS    RESTARTS   AGE    IP           NODE     NOMINATED NODE   READINESS GATES
    pod-demo   1/1     Running   0          104s   10.244.2.5   node02   <none>           <none>

    可见pod已经运行在node02上了;

    2、节点亲和度调度

    [root@master scheduler]# kubectl explain pods.spec.affinity
    [root@master scheduler]# kubectl explain pods.spec.affinity.nodeAffinity
    preferredDuringSchedulingIgnoredDuringExecution:软亲和,
    requiredDuringSchedulingIgnoredDuringExecution:硬亲和,表示必须满足
    [root@master ~]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
    
    #硬亲和性
    [root@master schedule]# vim pod-nodeaffinity-demo.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-node-affinity-demo
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: zone
                operator: In
                values:
                - foo
                - bar
    
    [root@master schedule]# kubectl apply -f pod-nodeaffinity-demo.yaml 
    pod/pod-node-affinity-demo created
    
    [root@master schedule]# kubectl get pods    
    NAME                     READY   STATUS    RESTARTS   AGE
    pod-node-affinity-demo   0/1     Pending   0          76s
     #此时pod是Pending, 是因为没有节点满足条件;

    下面我们再创建一个软亲和性的pod:

    #软亲和性,就算没有符合条件的节点,也会找一个勉强运行;
    
    [root@master schedule]# kubectl delete -f pod-nodeaffinity-demo.yaml 
    pod "pod-node-affinity-demo" deleted
    
    [root@master schedule]# vim pod-nodeaffinity-demo2.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-node-affinity-demo2
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
      affinity:
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - preference:
              matchExpressions:
              - key: zone
                operator: In
                values:
                - foo
                - bar
            weight: 60
    
    [root@master schedule]# kubectl apply -f pod-nodeaffinity-demo2.yaml 
    pod/pod-node-affinity-demo2 created
    
    [root@master schedule]# kubectl get pods    #可见pod已经运行了
    NAME                      READY   STATUS    RESTARTS   AGE
    pod-node-affinity-demo2   1/1     Running   0          74s
    
    pod-node-affinity-demo-2 运行起来了,因为这个pod我们是定义的软亲和性,即使没有符合条件的及诶单,也会找个节点让Pod运行起来

     

    3、pod亲和性调度

    比如在机房中,我们可以将一个机柜中的机器都打上标签,让pod调度的时候,对此机柜有亲和性;

    或者将机柜中某几台机器打上标签,让pod调度的时候,对这几个机器有亲和性;

    #查看资源定义清单字段
    [root@master ~]# kubectl explain pods.spec.affinity.podAffinity
    FIELDS:
       preferredDuringSchedulingIgnoredDuringExecution    <[]Object>  #软亲和
      requiredDuringSchedulingIgnoredDuringExecution    <[]Object>  #硬亲和
    
    [root@master ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
    FIELDS:
       labelSelector    <Object>  #表示选定一组资源,(跟哪些pod进行亲和);
       namespaces    <[]string>  #指定Pod属于哪个名称空间中,一般不跨名称空间去引用
       topologyKey    <string> -required-  #定义键(要亲和的关键字)

    pod硬亲和性调度:

    [root@master ~]# kubectl get nodes --show-labels
    NAME     STATUS   ROLES    AGE   VERSION   LABELS
    master   Ready    master   77d   v1.13.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=master,node-role.kubernetes.io/master=
    node01   Ready    <none>   77d   v1.13.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/hostname=node01
    node02   Ready    <none>   76d   v1.13.1   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=harddisk,kubernetes.io/hostname=node02
    
    #资源定义清单
    [root@master schedule]# vim pod-requieed-affinity-demo.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-first
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-second
      namespace: default
      labels:
        app: backend
        tier: db
    spec:
      containers:
      - name: busybox    #前面的-号表示这是一个列表格式的,也可以用中括号表示
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ["sh","-c","sleep 3600"]
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:    #硬亲和性
          - labelSelector:
              matchExpressions:
              - {key: app,operator: In,values: ["myapp"]}   #意思是当前这个pod要跟一个有着标签app=myapp(要和上面pod-first的metadata里面的标签一致)的pod在一起
            topologyKey: kubernetes.io/hostname    #匹配的节点key是kubernetes.io/hostname
    
    #创建
    [root@master schedule]# kubectl apply -f pod-requieed-affinity-demo.yaml 
    pod/pod-first created
    pod/pod-second created
    
    [root@master schedule]# kubectl get pods -o wide
    NAME         READY   STATUS    RESTARTS   AGE     IP            NODE     NOMINATED NODE   READINESS GATES
    pod-first    1/1     Running   0          3m25s   10.244.2.9    node02   <none>           <none>
    pod-second   1/1     Running   0          3m25s   10.244.2.10   node02   <none>           <none>
    
    #可以看到我们的两个pod都运行在同一个节点了,这是因为pod-second会和pod-first运行在同一个节点上,pod-second依赖于pod-first;

    4、pod反亲和性调度

    [root@master ~]# kubectl explain pods.spec.affinity.podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector
    FIELDS:
       matchExpressions    <[]Object>
       matchLabels    <map[string]string>
    
    [root@master schedule]# kubectl delete -f pod-requieed-affinity-demo.yaml    #删掉刚才的pod
    
    #资源定义清单
    [root@master schedule]# vim pod-requieed-Anti-affinity-demo.yaml 
    
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-first
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-second
      namespace: default
      labels:
        app: backend
        tier: db
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ["sh","-c","sleep 3600"]
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - {key: app,operator: In,values: ["myapp"]}
            topologyKey: kubernetes.io/hostname
    
    #创建
    [root@master schedule]# kubectl apply -f  pod-requieed-Anti-affinity-demo.yaml 
    pod/pod-first created
    pod/pod-second created
    
    [root@master schedule]# kubectl get pods -o wide
    NAME         READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    pod-first    1/1     Running   0          53s   10.244.1.7    node01   <none>           <none>
    pod-second   1/1     Running   0          53s   10.244.2.11   node02   <none>           <none>
    
    #可见pod-first和pod-second就不会被调度到同一个节点上;

    下面可以给两个节点打相同的标签,因为pod调度策略是podAntiAffinity反亲和性,所以pod-first和pod-second不能同时运行在标有zone标签的节点上;

    最终出现的情况就是有一个pod-first能成功运行,而另外一个pod-second因为是反亲和的,没有节点可以运行而处于pending状态;

    #打标,相同的标签
    [root@master ~]# kubectl label nodes node01 zone=foo
    node/node01 labeled
    [root@master ~]# kubectl label nodes node02 zone=foo
    
    [root@master schedule]# kubectl delete -f  pod-requieed-Anti-affinity-demo.yaml    #删掉pod
    
    #资源定义定义清单
    [root@master schedule]# vim pod-requieed-Anti-affinity-demo.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-first
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
    ---
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-second
      namespace: default
      labels:
        app: backend
        tier: db
    spec:
      containers:
      - name: busybox
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command: ["sh","-c","sleep 3600"]
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - {key: app,operator: In,values: ["myapp"]}
            topologyKey: zone            #节点标签改为zone
    
    #创建
    [root@master schedule]# kubectl apply -f  pod-requieed-Anti-affinity-demo.yaml 
    pod/pod-first created
    pod/pod-second created
    
    [root@master schedule]# kubectl get pods -o wide
    NAME         READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    pod-first    1/1     Running   0          4s    10.244.2.12   node02   <none>           <none>
    pod-second   0/1     Pending   0          4s    <none>        <none>   <none>           <none>
    
    #可见pod-first能成功运行,而pod-second因为是反亲和的,没有节点可以运行而处于pending状态;

    5、污点调度

    污点调度是让节点来选择哪些pod能运行在其上面,污点(taints)用在节点上,容忍度(Tolerations )用在pod上;

    污点定义:

    [root@master ~]# kubectl explain nodes.spec.taints    #taints:定义节点的污点
    FIELDS:
       effect    <string> -required-   #表示当pod不能容忍节点上污点时的行为是什么,主要有以下三种行为:
       {NoSchedule:仅影响调度过程,不影响现存pod。没调度过来的就调度不过来了。如果对节点新加了污点,那么对节点上现存的Pod没有影响。
        NoExecute:既影响调度过程,也影响现存Pod,没调度过来的就调度不过来了,如果对节点新加了污点,那么对现存的pod对象将会被驱逐
        PreferNoSchedule:不能容忍就不能调度过来,但是实在没办法也是能调度过来的。对节点新加了污点,那么对节点上现存的pod没有影响。}
       key    <string> -required-
       timeAdded    <string>
       value    <string>
    
    #查看节点的污点
    [root@master ~]# kubectl describe node node01 |grep Taints
    Taints:             <none>
    [root@master ~]# kubectl describe node node02 |grep Taints
    Taints:             <none>
    
    #查看pod的容忍度
    [root@master ~]# kubectl describe pods kube-apiserver-master -n kube-system |grep Tolerations
    Tolerations:       :NoExecute
    
    [root@master ~]# kubectl taint -h | grep -A 1 Usage     #给节点打污点的方式
    Usage:
      kubectl taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_N [options]
    
    污点和容忍度都是自定义的键值对形式;
    下面给node1打上污点node-type=production:NoSchedule:
    [root@master ~]# kubectl taint node node01 node-type=production:NoSchedule
    node/node01 tainted
    
    #pod资源定义清单,此文件没有定义容忍度,但是node01有污点,pod应该都会运行在node02上;
    [root@master schedule]# vim deploy-demo.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deploy
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
          release: canary
      template:
        metadata:
          labels:
            app: myapp
            release: canary
        spec:
          containers:
          - name: myapp
            image: ikubernetes/myapp:v2
            ports:
            - name: http
              containerPort: 80
    
    #创建
    [root@master schedule]# kubectl apply -f deploy-demo.yaml 
    deployment.apps/myapp-deploy created
    
    #可见pod都运行在了node02上
    [root@master schedule]# kubectl get pods -o wide
    NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    myapp-deploy-6b56d98b6b-52hth   1/1     Running   0          9s    10.244.2.15   node02   <none>           <none>
    myapp-deploy-6b56d98b6b-dr224   1/1     Running   0          9s    10.244.2.14   node02   <none>           <none>
    myapp-deploy-6b56d98b6b-z278x   1/1     Running   0          9s    10.244.2.13   node02   <none>           <none>

    容忍度定义:

    [root@master ~]# kubectl explain pods.spec.tolerations
    FIELDS:
       effect    <string>
       key    <string>
       operator    <string>    #两个值:Exists表示只要节点有这个污点的key,pod都能容忍,值是什么都行;Equal表示只要节点必须精确匹配污点的key和value才能容忍;
       tolerationSeconds    <integer>      #表示宽限多长时间pod才会被驱逐
       value    <string>
    
    [root@master ~]# kubectl taint node node02 node-type=dev:NoExecute    #给node02打上另一个标签
    node/node02 tainted
    
    [root@master schedule]# kubectl delete -f deploy-demo.yaml
    
    #资源定义清单
    [root@master schedule]# vim deploy-demo.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deploy
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
          release: canary
      template:
        metadata:
          labels:
            app: myapp
            release: canary
        spec:
          containers:
          - name: myapp
            image: ikubernetes/myapp:v2
            ports:
            - name: http
              containerPort: 80
          tolerations:
          - key: "node-type"
            operator: "Equal"    #要精确匹配污点键值
            value: "production"
            effect: "NoSchedule"
    
    #创建pod
    [root@master schedule]# kubectl apply -f deploy-demo.yaml 
    deployment.apps/myapp-deploy created
    
    [root@master schedule]# kubectl get pods -o wide
    NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    myapp-deploy-779c578779-5vkbw   1/1     Running   0          12s   10.244.1.12   node01   <none>           <none>
    myapp-deploy-779c578779-bh9td   1/1     Running   0          12s   10.244.1.11   node01   <none>           <none>
    myapp-deploy-779c578779-dn52p   1/1     Running   0          12s   10.244.1.13   node01   <none>           <none>
    
    #可见pod都运行在了node01上,因为我们设置了pod能容忍node01的污点;

    下面我们把operator: "Equal"改成operator: "Exists"

    Exists表示只要节点有这个污点的key,pod都能容忍,值是什么都行;

    [root@master schedule]# kubectl delete -f deploy-demo.yaml
    
    [root@master schedule]# vim deploy-demo.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deploy
      namespace: default
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: myapp
          release: canary
      template:
        metadata:
          labels:
            app: myapp
            release: canary
        spec:
          containers:
          - name: myapp
            image: ikubernetes/myapp:v2
            ports:
            - name: http
              containerPort: 80
          tolerations:
          - key: "node-type"
            operator: "Exists"  
            value: ""
            effect: ""       #不设置行为
    
    #创建
    [root@master schedule]# kubectl apply -f deploy-demo.yaml 
    deployment.apps/myapp-deploy create
    
    [root@master schedule]# kubectl get pods -o wide
    NAME                            READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
    myapp-deploy-69b95476c8-bfpgj   1/1     Running   0          13s   10.244.2.20   node02   <none>           <none>
    myapp-deploy-69b95476c8-fhwbd   1/1     Running   0          13s   10.244.1.17   node01   <none>           <none>
    myapp-deploy-69b95476c8-tzzlx   1/1     Running   0          13s   10.244.2.19   node02   <none>           <none>
    
    #可见,node01  node02上面都有pod了;
     effect:不设置表示什么行为都能容忍;

    最后可以去除节点上的污点:

    #去除污点命令,删除指定key上所有的effect
    [root@master ~]# kubectl taint node node02 node-type-
    node/node02 untainted
    [root@master ~]# kubectl taint node node01 node-type-
    node/node01 untainted

     

  • 相关阅读:
    PHP 使用 GET 传递数组变量
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 数据交换
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 景点游览
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
    Java实现 蓝桥杯 算法训练 二进制数数
  • 原文地址:https://www.cnblogs.com/weiyiming007/p/10573379.html
Copyright © 2011-2022 走看看