研发工程师玩转Kubernetes——Node亲和性requiredDuringSchedulingIgnoredDuringExecution几种边界实验

2023-07-10 14:08:48 浏览数 (2)

在《研发工程师玩转Kubernetes——使用Node特性定向调度Pod》中,我们提到requiredDuringSchedulingIgnoredDuringExecution只有在规则被满足的时候才能执行调度。本节我们将测试几种边界情况,看看Kubernetes的行为。

没有满足的条件

假设我们测试的Node都没有Label:not_exist=“”,于是我们在清单中要求必须有这个Label,来测试这个边界。

代码语言:javascript复制
# nginx_deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: not_exist
                operator: In
                values:
                - ""
      containers:
      - name: nginx-container
        image: nginx
        ports:
        - containerPort: 80

执行下面的指令

代码语言:javascript复制
kubectl create -f nginx_deployment.yaml

deployment.apps/nginx-deployment created

观察

Pod的情况

代码语言:javascript复制
kubectl get pod --watch -o wide
代码语言:javascript复制
NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-6b5d69bc9d-94vgl   0/1     Pending   0          0s    <none>   <none>   <none>           <none>
nginx-deployment-6b5d69bc9d-94vgl   0/1     Pending   0          0s    <none>   <none>   <none>           <none>

Deployment的情况

代码语言:javascript复制
kubectl get deployments.apps --watch -o wide
代码语言:javascript复制
NAME               READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS        IMAGES   SELECTOR
nginx-deployment   0/1     1            0           59s   nginx-container   nginx    app=nginx

可以看到Pod一直处于Pending状态,也没调度到任何Node上。

多个nodeSelectorTerms

为了进行这个测试,我们给UbuntuB和UbunutC设置对应的Label。

代码语言:javascript复制
kubectl label nodes ubuntub name:ubuntub

node/ubuntub labeled

代码语言:javascript复制
kubectl label nodes ubuntuc name=ubuntuc

node/ubuntuc labeled

我们使用下面指令查看下修改后的Labels。

代码语言:javascript复制
kubectl get nodes --show-labels     
代码语言:javascript复制
NAME      STATUS   ROLES    AGE   VERSION   LABELS
ubuntud   Ready    <none>   21h   v1.26.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=ubuntud,kubernetes.io/os=linux,microk8s.io/cluster=true,node.kubernetes.io/microk8s-worker=microk8s-worker
ubuntuc   Ready    <none>   21h   v1.26.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=ubuntuc,kubernetes.io/os=linux,microk8s.io/cluster=true,name=ubuntuc,node.kubernetes.io/microk8s-worker=microk8s-worker
ubuntub   Ready    <none>   21h   v1.26.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=ubuntub,kubernetes.io/os=linux,microk8s.io/cluster=true,name=ubuntub,node.kubernetes.io/microk8s-worker=microk8s-worker
ubuntue   Ready    <none>   21h   v1.26.4   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=ubuntue,kubernetes.io/os=linux,microk8s.io/cluster=true,node.kubernetes.io/microk8s-worker=microk8s-worker
ubuntua   Ready    <none>   21h   v1.27.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=ubuntua,kubernetes.io/os=linux,microk8s.io/cluster=true,node.kubernetes.io/microk8s-controlplane=microk8s-controlplane

然后清单改成多个nodeSelectorTerms

代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: name
                operator: In
                values:
                - "ubuntub"
            - matchExpressions:
              - key: name
                operator: In
                values:
                - "ubuntuc"
      containers:
      - name: nginx-container
        image: nginx
        ports:
        - containerPort: 80

调用下面指令创建Deployment

代码语言:javascript复制
kubectl create -f nginx_deployment.yaml 

deployment.apps/nginx-deployment created

观察

代码语言:javascript复制
kubectl get pod --watch -o wide
代码语言:javascript复制
NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-58d4498bdd-s5fvd   0/1     Pending   0          0s    <none>   <none>   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   0/1     Pending   0          0s    <none>   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   0/1     ContainerCreating   0          0s    <none>   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   0/1     ContainerCreating   0          0s    <none>   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   1/1     Running             0          4s    10.1.43.212   ubuntuc   <none>           <none>
代码语言:javascript复制
kubectl get deployments.apps --watch -o wide
代码语言:javascript复制
NAME               READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS        IMAGES   SELECTOR
nginx-deployment   0/1     0            0           0s    nginx-container   nginx    app=nginx
nginx-deployment   0/1     0            0           0s    nginx-container   nginx    app=nginx
nginx-deployment   0/1     0            0           0s    nginx-container   nginx    app=nginx
nginx-deployment   0/1     1            0           0s    nginx-container   nginx    app=nginx
nginx-deployment   1/1     1            1           4s    nginx-container   nginx    app=nginx

可以看到Node的requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions之间是取或的关系,即只要满足其中一个条件就可以被调度到。

为了再次验证,我们可以让UbuntC驱逐这个Pod。

代码语言:javascript复制
 kubectl taint node ubuntuc node_type=worker:NoExecute

node/ubuntuc tainted

再观察

代码语言:javascript复制
kubectl get pod --watch -o wide
代码语言:javascript复制
NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-58d4498bdd-s5fvd   1/1     Running             0          8m28s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   1/1     Terminating         0          8m28s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   1/1     Terminating         0          8m28s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     Pending             0          1s      <none>        <none>    <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     Pending             0          1s      <none>        ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     ContainerCreating   0          1s      <none>        ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   1/1     Terminating         0          8m29s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     ContainerCreating   0          1s      <none>        ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   0/1     Terminating         0          8m30s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   0/1     Terminating         0          8m30s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-s5fvd   0/1     Terminating         0          8m30s   10.1.43.212   ubuntuc   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   1/1     Running             0          4s      10.1.209.132   ubuntub   <none>           <none>

可以看到Pod被调度到另外一个匹配的条件对应的Node(UbuntuB)上。

被彻底驱逐

再让UbuntuB驱逐这个Pod,这样没有哪个Node可以符合条件。

代码语言:javascript复制
kubectl taint node ubuntub node_type=worker:NoExecute

node/ubuntub tainted

再观察

代码语言:javascript复制
kubectl get pod --watch -o wide
代码语言:javascript复制
NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-58d4498bdd-kc2fz   1/1     Terminating         0          3m30s   10.1.209.132   ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   1/1     Terminating         0          3m30s   10.1.209.132   ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-wjkbx   0/1     Pending             0          0s      <none>         <none>    <none>           <none>
nginx-deployment-58d4498bdd-wjkbx   0/1     Pending             0          0s      <none>         <none>    <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   1/1     Terminating         0          3m30s   10.1.209.132   ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     Terminating         0          3m31s   10.1.209.132   ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     Terminating         0          3m31s   10.1.209.132   ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-kc2fz   0/1     Terminating         0          3m32s   10.1.209.132   ubuntub   <none>           <none>

因为被驱逐,老的Pod被终止,而新的Pod因为哪个Node可以被匹配到,而变成pending状态。

取消Label

接上上步,我们使用下面指令取消UbuntuB对Pod的驱逐

代码语言:javascript复制
kubectl taint node ubuntub node_type=worker:NoExecute-

node/ubuntub untainted

可以看到Deployment将Pod调度到UbuntuB上

代码语言:javascript复制
NAME                                READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
nginx-deployment-58d4498bdd-wjkbx   0/1     ContainerCreating   0          5m20s   <none>         ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-wjkbx   0/1     ContainerCreating   0          5m20s   <none>         ubuntub   <none>           <none>
nginx-deployment-58d4498bdd-wjkbx   1/1     Running             0          5m23s   10.1.209.133   ubuntub   <none>           <none>

然后我们使用下面指令取消UbuntuB的Label:name=unbuntb

代码语言:javascript复制
kubectl label nodes ubuntub name- 

这次Deployment不会驱逐该Pod

代码语言:javascript复制
 kubectl get pod  -o wide 
代码语言:javascript复制
NAME                                READY   STATUS    RESTARTS   AGE   IP             NODE      NOMINATED NODE   READINESS GATES
nginx-deployment-58d4498bdd-wjkbx   1/1     Running   0          11m   10.1.209.133   ubuntub   <none>           <none>

总结

  • requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions之间是取或的关系,即只要满足其中一个条件就可以被调度到。
  • 没有匹配的条件,Pod会被创建,但是处于Pending状态,不会被部署到任何一个Node上。
  • 如果Pod已经在Node上运行,此时删除Node匹配上的Label,Deployment不会终止该Pod。

0 人点赞