【容器应用系列教程】Kubernetes调度系统

一、基于nodeName调度

指定在哪个node节点上,创建Pod

1.查看所有节点

[root@k8s-master ~]# kubectl get node
NAME                   STATUS   ROLES                  AGE   VERSION
k8s-master.linux.com   Ready    control-plane,master   8d    v1.20.7
k8s-node01.linux.com   Ready    <none>                 8d    v1.20.7
k8s-node02.linux.com   Ready    <none>                 8d    v1.20.7

2.基于nodeName调度

[root@k8s-master test]# vim test1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test1-nginx
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test1-nginx
  template:
    metadata:
      labels:
        app: test1-nginx
    spec:
      nodeName: k8s-node02.linux.com	#指定所有Pod都运行在node02上
      containers:
      - name: test1-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
[root@k8s-master test]# kubectl create -f test1.yaml 
deployment.apps/test1-nginx created

3.查看Pod

可以看到所有Pod都跑在node02节点上

[root@k8s-master test]# kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE     IP                NODE                   NOMINATED NODE   READINESS GATES
test1-nginx-5bccbd59df-cfl6v   1/1     Running   0          2m29s   192.168.242.131   k8s-node02.linux.com   <none>           <none>
test1-nginx-5bccbd59df-r68jk   1/1     Running   0          2m29s   192.168.242.130   k8s-node02.linux.com   <none>           <none>

二、基于nodeSelector调度

1.查看所有节点的标签

[root@k8s-master test]# kubectl get node --show-labels
NAME                   STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master.linux.com   Ready    control-plane,master   8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master.linux.com,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
k8s-node01.linux.com   Ready    <none>                 8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01.linux.com,kubernetes.io/os=linux
k8s-node02.linux.com   Ready    <none>                 8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02.linux.com,kubernetes.io/os=linux

2.创建基于nodeSelector调度

[root@k8s-master test]# vim test2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test2-nginx
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test2-nginx
  template:
    metadata:
      labels:
        app: test2-nginx
    spec:
      nodeSelector:	#nodeSelector调度类型
            name: wsjj	#在有name=wsjj的标签机器上创建
      containers:
      - name: test2-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
[root@k8s-master test]# kubectl create -f test2.yaml 
deployment.apps/test1-nginx created

3.查看Pod

可以看到所有Pod都是处于pending等待调度状态
这是因为,在所有节点上,都没有找到name=wsjj标签的机器

[root@k8s-master test]# kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
test2-nginx-5f89c875cf-cfl6v   0/1     Pending   0          6s
test2-nginx-5f89c875cf-r68jk   0/1     Pending   0          6s

4.手动打标签

[root@k8s-master test]# kubectl label node k8s-node01.linux.com name=wsjj
node/k8s-node01.linux.com labeled

node01身上多了name=wsjj的标签

[root@k8s-master test]# kubectl get node --show-labels
NAME                   STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master.linux.com   Ready    control-plane,master   8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master.linux.com,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
k8s-node01.linux.com   Ready    <none>                 8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01.linux.com,kubernetes.io/os=linux,name=wsjj
k8s-node02.linux.com   Ready    <none>                 8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02.linux.com,kubernetes.io/os=linux

5.再次查看Pod

当有了标签后,Pod正常运行

[root@k8s-master test]# kubectl get pod -o wide
NAME                           READY   STATUS    RESTARTS   AGE    IP                NODE                   NOMINATED NODE   READINESS GATES
test2-nginx-5f89c875cf-cfl6v   1/1     Running   0          7m4s   192.168.201.194   k8s-node01.linux.com   <none>           <none>
test2-nginx-5f89c875cf-r68jk   1/1     Running   0          7m4s   192.168.201.195   k8s-node01.linux.com   <none>           <none>

6.删除标签

# kubectl label nodes <node_name> key- 
[root@k8s-master test]# kubectl label nodes k8s-node01.linux.com name-
node/k8s-node01.linux.com labeled

可以看到即使标签被删除了,旧的Pod不会被影响

[root@k8s-master test]# kubectl get pod -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP                NODE                   NOMINATED NODE   READINESS GATES
test2-nginx-5f89c875cf-cfl6v   1/1     Running   0          11m   192.168.201.194   k8s-node01.linux.com   <none>           <none>
test2-nginx-5f89c875cf-r68jk   1/1     Running   0          11m   192.168.201.195   k8s-node01.linux.com   <none>           <none>
[root@k8s-master test]# kubectl delete pod test2-nginx-5f89c875cf-cfl6v
pod "test2-nginx-5f89c875cf-cfl6v" deleted

[root@k8s-master test]# kubectl get pod -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP                NODE                   NOMINATED NODE   READINESS GATES
test2-nginx-5f89c875cf-7d9tj   0/1     Pending   0          17s   <none>            <none>                 <none>           <none>
test2-nginx-5f89c875cf-r68jk   1/1     Running   0          12m   192.168.201.195   k8s-node01.linux.com   <none>           <none>

7.修改标签的值

# kubectl label nodes <node_name> key=value --overwrite

三、基于nodeAffinity节点亲缘性

使用nodeAffinity可以在部署Pod时,将Pod调度运行到符合特定条件或不符合特定条件的节点

1.nodeAffinity调度策略

requiredDuringSchedulingIgnoredDuringExecution

  • 表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。
  • IgnoreDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,pod也会继续运行。

requiredDuringSchedulingRequiredDuringExecution

  • 表示pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试
  • RequiredDuringExecution表示pod部署之后运行的时候,如果节点标签发生了变化,不再满足pod指定的条件,则重新选择符合要求的节点

preferredDuringSchedulingIgnoredDuringExecution

  • 表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署

preferredDuringSchedulingRequiredDuringExecution

  • 表示优先部署到满足条件的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署。
  • RequiredDuringExecution表示如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点。

2.案例1:基于nodeAffinity节点亲缘性调度

node02打标记

[root@k8s-master test]# kubectl label node k8s-node02.linux.com yewu=dev
node/k8s-node02.linux.com labeled
[root@k8s-master test]# kubectl get node --show-labels
NAME                   STATUS   ROLES                  AGE   VERSION   LABELS
k8s-master.linux.com   Ready    control-plane,master   8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master.linux.com,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
k8s-node01.linux.com   Ready    <none>                 8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01.linux.com,kubernetes.io/os=linux
k8s-node02.linux.com   Ready    <none>                 8d    v1.20.7   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02.linux.com,kubernetes.io/os=linux,yewu=dev

创建Deployment测试

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test3-nginx
  namespace: default
  labels:
    app: test3-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test3-nginx
  template:
    metadata:
      labels:
        app: test3-nginx
    spec:
      affinity:
        nodeAffinity:	#类型
          requiredDuringSchedulingIgnoredDuringExecution:	#指定策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: yewu	#键
                operator: NotIn	#表示label的值不在某个列表中,类似取反
                values:
                - dev	#值
      containers:
      - name: test3-nginx
        image: nginx
        ports:
        - containerPort: 80
  • 支持的操作符:
  • In: label的值在某个列表中
  • NotInlabel的值不在某个列表中
  • Exists:某个label存在
  • DoesNotExist:某个label不存在
  • Gtlabel的值大于某个值(字符串比较)
  • Ltlabel的值小于某个值(字符串比较)
[root@k8s-master test]# kubectl create -f test3.yml
deployment.apps/test3-nginx created

查看结果

由于取反的原因,node02身上有符合要求的标签,所以取反到node01身上创建

[root@k8s-master test]# kubectl get pod -o wide
NAME                           READY   STATUS    RESTARTS   AGE     IP                NODE                   NOMINATED NODE   READINESS GATES
test3-nginx-654cf47554-bzbh4   1/1     Running   0          2m34s   192.168.201.195   k8s-node01.linux.com   <none>           <none>
test3-nginx-654cf47554-cwggc   1/1     Running   0          2m34s   192.168.201.196   k8s-node01.linux.com   <none>           <none>

3.案例2:基于nodeAffinity节点亲缘性调度

[root@k8s-master test]# vim test4.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test4-nginx
  namespace: default
  labels:
    app: test4-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test4-nginx
  template:
    metadata:
      labels:
        app: test4-nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                - key: kubernetes.io/os
                  operator: In
                  values:
                    - linux
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 1
              preference:
                matchExpressions:
                  - key: yewu
                    operator: In
                    values:
                     - dev
      containers:
      - name: test4-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
[root@k8s-master test]# kubectl create -f test4.yml
deployment.apps/test4-nginx created

查看Pod

本案例中同时设置了requiredDuringSchedulingIgnoredDuringExecutionpreferredDuringSchedulingIgnoredDuringExecution两种策略,表示的意思为将Pod要调度到具有kubernetes.io/os=linux这个标签的节点时,在满足该条件的情况下,preferredDuringSchedulingIgnoredDuringExecution表示的意思是优先将其调度到同时具有yewu=dev的节点上

[root@k8s-master test]# kubectl get pods -o wide
NAME                           READY   STATUS    RESTARTS   AGE    IP                NODE                   NOMINATED NODE   READINESS GATES
test4-nginx-5bf9894f8c-87wsf   1/1     Running   0          2m3s   192.168.242.132   k8s-node02.linux.com   <none>           <none>
test4-nginx-5bf9894f8c-nznnn   1/1     Running   0          2m3s   192.168.242.131   k8s-node02.linux.com   <none>           <none>

四、污点Taint、容忍Toleration

Tainttoleration相互配合,可以用来避免pod被分配到不合适的节点上。每个节点上都可以应用一个或多个taint,这表示对于那些不能容忍这些taintpod,是不会被该节点接受的。如果将toleration应用于pod上,则表示这些pod可以被调度到具有相应taint的节点上。

1.污点Taint管理操作

查看Taint污点

由于我是基于kubeadm部署的集群,集群会默认为Master节点配置一个污点,防止资源被调度到Master节点上。

[root@k8s-master test]# kubectl describe node k8s-master.linux.com | grep -i Taints
Taints:             node-role.kubernetes.io/master:NoSchedule

为节点添加Taint污点

# kubectl taint nodes <node_name> key=value:{NoSchedule|NoExecute|PreferNoSchedule}
  • 污点的影响策略:
  • NoSchedule
    • 新的不能容忍该污点的Pod不会再调度过来
    • 但已经运行在该节点上的Pod不会受影响
  • NoExecute
    • 新的不能容忍该污点的Pod不会再调度过来
    • 同时该节点上的所有Pod都会被驱逐
  • PreferNoSchedule
    • 尽量不向该节点调度

删除Taint污点

# kubectl taint node <node_name> key:{NoSchedule|NoExecute|PreferNoSchedule}-

3.示例:为node02添加Tatin污点,指定策略为NoExecute

[root@k8s-master ~]# kubectl taint nodes k8s-node02.linux.com AA=10:NoExecute

可以看到node02身上的所有Pod都被驱逐了

[root@k8s-master ~]# kubectl get pods -o wide
NAME                           READY   STATUS              RESTARTS   AGE   IP                NODE                   NOMINATED NODE   READINESS GATES
test-client                    1/1     Running             4          10d   10.88.0.9         k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-6x8mz   0/1     ContainerCreating   0          3s    <none>            k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-7wkhg   0/1     ContainerCreating   0          3s    <none>            k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-c8pf9   1/1     Running             0          10m   172.168.201.231   k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-fbfxp   1/1     Running             0          10m   172.168.201.230   k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-j4j62   1/1     Terminating         0          10m   172.168.242.138   k8s-node02.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-j4zkd   0/1     ContainerCreating   0          3s    <none>            k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-lfct5   1/1     Terminating         0          10m   172.168.242.139   k8s-node02.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-nnlml   1/1     Terminating         0          10m   172.168.242.135   k8s-node02.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-p4nrz   0/1     ContainerCreating   0          3s    <none>            k8s-node01.linux.com   <none>           <none>
test1-nginx-6fcf9564d5-t8jdc   1/1     Terminating         0          10m   172.168.242.134   k8s-node02.linux.com   <none>           <none>

删除污点

# kubectl taint node 节点名 键-
[root@k8s-master ~]# kubectl taint nodes k8s-node02.linux.com AA-

4.容忍Toleration

一般容忍Toleration和污点Taint是配合使用的
当用户想要在,存在Taint污点的Node节点上创建Pod的时候,就需要有容忍Toleration的存在

添加Tatin污点

[root@k8s-master ~]# kubectl taint nodes k8s-node02.linux.com AA=10:NoExecute

创建Pod配置容忍Toleration策略

[root@k8s-master test]# vim test5.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test5-nginx
  namespace: default
  labels:
    app: test5-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: test5-nginx
  template:
    metadata:
      labels:
        app: test5-nginx
    spec:
      containers:
      - name: test5-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

      tolerations:
        - key: "AA"
          operator: "Equal"   
          value: "10"
          effect: NoExecute
          tolerationSeconds: 30	#容忍时间可以不写
[root@k8s-master test]# kubectl create -f test5.yml
  • 配置项说明:
  • tolerations添加容忍策略
  • key指定所容忍的key,要与对应污点的key一致
  • value指定所容忍的value,要与对应污点的value一致
  • effect指定所容忍的策略,一定要与污点指定的策略一致
  • tolerationSeconds指定容忍的超时时间,到达该时间后,Pod将会被驱逐

容忍的匹配规则也可以写多个

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"

查看Pod

[root@k8s-master ]# kubectl get pods -o wide

NAME                           READY   STATUS    RESTARTS   AGE   IP                NODE                   NOMINATED NODE   READINESS GATES
test1-nginx-654d4cc68c-2mh68   1/1     Running   0          6s    172.168.242.149   k8s-node02.linux.com   <none>           <none>
test1-nginx-654d4cc68c-8z8kw   1/1     Running   0          6s    172.168.242.147   k8s-node02.linux.com   <none>           <none>

删除污点Taint

[root@k8s-master ~]# kubectl taint node k8s-node02.linux.com AA-