企业级容器技术 k8s 调度

本文详细介绍了Kubernetes中Pod的调度策略,包括节点选择、标签调度、亲和与反亲和、污点与容忍等机制,以及如何通过cordon、drain和delete操作管理节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最简单的方法: podName节点选择,直接选择一个节点,但是一般不推荐,如果直接指定了,那么就会优先于其他选择方法。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: myapp
    image: nginx
  nodeName: server3   ##直接选择server3的节点

但是这个方法也有一些限制:比如节点不存在,或者是这个节点资源满了,都会使pod调度失败。

使用标签进行调度

[kubeadm@server1 ~]$ kubectl get nodes --show-labels 
NAME      STATUS   ROLES    AGE   VERSION   LABELS
server1   Ready    master   14d   v1.17.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=server1,kubernetes.io/os=linux,node-role.kubernetes.io/master=
server3   Ready    <none>   14d   v1.17.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=server3,kubernetes.io/os=linux
server4   Ready    <none>   14d   v1.17.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=server4,kubernetes.io/os=linux

首先查看每个节点的标签,发现 在server3上有了一个ssd的标签,我们可以直接使用这个标签进行调度。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: myapp
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd   ##pod创建时根据这个标签来匹配节点。

亲和与反亲和

节点亲和
这个规则和上面两条规则相比是软性要求,所以在调度器无法满足要求时仍然可以调度这个pod
节点亲和分为必须满足和倾向满足。

apiVersion: v1
kind: Pod
metadata:
  name: node-affinity
spec:
  containers:
  - name: nginx
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution: ##这个是硬性要求
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In   ##这个参数In代表的就是要从下面的标签进行调度
            values:
              - ssd   ##调度到标签为ssd的节点
[kubeadm@server1 ~]$ kubectl get pod -o wide
NAME                                      READY   STATUS    RESTARTS   AGE     IP            NODE      NOMINATED NODE   READINESS GATES
node-affinity                             1/1     Running   0          2m28s   10.244.2.52   server3   <none>           <none>

如果pod创建完成后现在将调度的标签删除掉,这个pod不会进行节点转移。在之后重新创建才会调度到硬性要求的节点

apiVersion: v1
kind: Pod
metadata:
  name: node-affinity
spec:
  containers:
  - name: nginx
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:##硬性要求
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname ##用户名
            operator: NotIn  ##不能等于
            values:
              - server1
      preferredDuringSchedulingIgnoredDuringExecution:##软性要求
      - weight: 1 软性要求的权重
        preference:
          matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd

这样创建出来的pod必然不能在server1上,而软性要求可以添加多个,然后看哪个更亲和一些,那么就会部署到哪个节点之上。

pod亲和性
亲和性在pod之间,而不在节点之间,首先创建一个pod

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx

再创建一个需要和上面pod放在一个节点上的pod,这个pod我们不做过多的指定,给他一个要求,让他自己去寻找更亲和的pod上的节点。

apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  containers:
  - name: mysql
    image: mysql
    env:
    - name: "MYSQL_ROOT_PASSWORD"
      value: "passyt"
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:    
          matchExpressions:
              - key: app             ##这里让我们选择标签是nginx的pod
                operator: In
                values:
                - nginx
        topologyKey: "kubernetes.io/hostname"

这样两个pod就会在一个节点上,有了亲和还有反亲和,其中最大的区别就是podAffinity这个参数,podAffinity是亲和,podAntiAffinity是反亲和,设置了这个参数,两个就是排斥的。

污点和容忍

污点代表一个东西不好的地方,容忍是说即使有污点如果没有别的选择我也可以将就一下。
创建污点使用

[kubeadm@server1 test]$ kubectl taint nodes server3 key=value:NoSchedule##不能被调度,除了这个还有两个策略
node/server3 tainted
查询污点使用
[kubeadm@server1 test]$ kubectl describe nodes server3  |grep Taints
Taints:             key=value:NoSchedule
创建一个pod来进行测试
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx 

由于server3上打了一个污点,不进行调度,所以只有1和4上面创建pod。

[kubeadm@server1 test]$ kubectl get pod -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
web-server-86c57db685-8lc4w               1/1     Running   0          32s   10.244.3.57   server4   <none>           <none>
web-server-86c57db685-mtq9n               1/1     Running   0          32s   10.244.3.56   server4   <none>           <none>
web-server-86c57db685-n89kq               1/1     Running   0          32s   10.244.0.70   server1   <none>           <none>

重新设置一个污点
首先直接先使用上面文件创建pod,这时pod是平均调度的,
之后设置一个污点

[kubeadm@server1 test]$ kubectl taint node server3  key=v1:NoExecute  ##会踢出原有pod
node/server3 tainted

这个时候被踢出的pod会转移

在pod中设置容忍标签,结果可能会不太一样。
在容器中

  tolerations:
  - key: "key"         ##key value 设置的东西要一一对应
    operator: "Equal"
    value: "v1"
    effect: "NoExecute"

这样可以容忍就能实现正常调度。

暂时隔离cordon,drain和delete创建新的pod不会被调度到该节点,区别在于暴力程度不一样。

cordon

cordon停止调度,使用后不会被调度到该节点,但是原有pod不受影响。

[kubeadm@server1 test]$ kubectl cordon server3
node/server3 cordoned
[kubeadm@server1 test]$ kubectl get nodes 
NAME      STATUS                     ROLES    AGE   VERSION
server1   Ready                      master   15d   v1.17.3
server3   Ready,SchedulingDisabled   <none>   15d   v1.17.3
server4   Ready                      <none>   15d   v1.17.3
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
nfs-client-provisioner-6bc469c54d-wqrr8   1/1     Running   3          42h   10.244.3.60   server4   <none>           <none>
web-server-86c57db685-cnxg9               1/1     Running   0          10s   10.244.2.56   server3   <none>           <none>
web-server-86c57db685-czv7f               1/1     Running   0          10s   10.244.0.77   server1   <none>           <none>
web-server-86c57db685-kv22c               1/1     Running   0          10s   10.244.3.66   server4   <none>           <none>

上面是已经完成调度的,server3上虽然已经不参加调度,但是已经运行的pod并不受到影响,这个时候我们对集群进行扩容。

[kubeadm@server1 test]$ kubectl get pod -o wide
NAME                                      READY   STATUS    RESTARTS   AGE    IP            NODE      NOMINATED NODE   READINESS GATES
nfs-client-provisioner-6bc469c54d-wqrr8   1/1     Running   3          42h    10.244.3.60   server4   <none>           <none>
web-server-86c57db685-cnxg9               1/1     Running   0          105s   10.244.2.56   server3   <none>           <none>
web-server-86c57db685-czv7f               1/1     Running   0          105s   10.244.0.77   server1   <none>           <none>
web-server-86c57db685-f7jgc               1/1     Running   0          3s     10.244.3.67   server4   <none>           <none>
web-server-86c57db685-kv22c               1/1     Running   0          105s   10.244.3.66   server4   <none>           <none>
web-server-86c57db685-lrrpl               1/1     Running   0          3s     10.244.3.68   server4   <none>           <none>
web-server-86c57db685-wd7mq               1/1     Running   0          3s     10.244.0.78   server1   <none>           <none>

这时可以发现,其调度只在1和4上。
去除这个调度选项直接使用命令去除。

[kubeadm@server1 test]$ kubectl uncordon server3
node/server3 uncordoned

drain

使用drain会首先将节点上的pod踢出,之后在其他节点重新进行创建。

[kubeadm@server1 test]$ kubectl drain server3
node/server3 cordoned
evicting pod "web-server-86c57db685-cnxg9"
pod/web-server-86c57db685-cnxg9 evicted
node/server3 evicted
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
nfs-client-provisioner-6bc469c54d-wqrr8   1/1     Running   3          42h   10.244.3.60   server4   <none>           <none>
web-server-86c57db685-c6pmf               1/1     Running   0          19s   10.244.3.69   server4   <none>           <none>
web-server-86c57db685-czv7f               1/1     Running   0          13m   10.244.0.77   server1   <none>           <none>
web-server-86c57db685-f7jgc               1/1     Running   0          12m   10.244.3.67   server4   <none>           <none>
web-server-86c57db685-kv22c               1/1     Running   0          13m   10.244.3.66   server4   <none>           <none>
web-server-86c57db685-lrrpl               1/1     Running   0          12m   10.244.3.68   server4   <none>           <none>
web-server-86c57db685-wd7mq               1/1     Running   0          12m   10.244.0.78   server1   <none>           <none>

将这个节点恢复过来同样使用命令

[kubeadm@server1 test]$ kubectl uncordon server3

delete

使用delete是最暴力的,过程是:首先将节点上的所有pod踢出,之后在控制节点直接将其删除,脱离节点的控制,如果要恢复那么就要进入节点重新启动kubelet服务。

[kubeadm@server1 test]$ kubectl get pod -o wide
NAME                                      READY   STATUS    RESTARTS   AGE   IP            NODE      NOMINATED NODE   READINESS GATES
nfs-client-provisioner-6bc469c54d-4w9rl   1/1     Running   0          12s   10.244.2.61   server3   <none>           <none>
web-server-86c57db685-6fkkj               1/1     Running   0          12s   10.244.2.59   server3   <none>           <none>
web-server-86c57db685-czv7f               1/1     Running   0          24m   10.244.0.77   server1   <none>           <none>
web-server-86c57db685-f25rt               1/1     Running   0          12s   10.244.2.58   server3   <none>           <none>
web-server-86c57db685-k46tf               1/1     Running   0          12s   10.244.2.57   server3   <none>           <none>
web-server-86c57db685-vtwwd               1/1     Running   0          12s   10.244.2.60   server3   <none>           <none>
web-server-86c57db685-wd7mq               1/1     Running   0          22m   10.244.0.78   server1   <none>           <none>

本来在4上的pod全部转移到了3上
恢复节点,进入对应的node中,启动服务

[root@server4 ~]# systemctl restart kubelet.service 

但是这个节点重新启动后并不会重新进行调度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值