k8s 标签-2

目录

标签-2

上一篇笔记的结尾处我们简单提了一下标签,并通过标签将pod指定给了某个node,因为当时写的时候比较晚了,所以并没有一次性写完,这篇我们接着看标签

node的角色

在我们使用命令kubectl get nodes查看节点的时候,你会发现有一栏是ROLES,只有master是有的,其他节点都是none

bash 复制代码
[root@master k8s]# kubectl get nodes 
NAME     STATUS   ROLES           AGE    VERSION
master   Ready    control-plane   2d1h   v1.26.0
node1    Ready    <none>          2d1h   v1.26.0
node2    Ready    <none>          2d1h   v1.26.0

他默认就是这样显示的,当然,如果你使用的k8s集群版本是1.21或者1.22之前的版本,那么他先是的就是master,而不是control-plane,这个无关竟要,版本问题

现在node1和node2这一栏显示的空的,我们可以修改他吗?当然是可以的,没有任何的问题,修改他其实就是修改标签

bash 复制代码
# 我们先查看master节点,他既然有这个值,那么他肯定是有一些node节点没有的标签的
[root@master k8s]# kubectl get nodes/master --show-labels 
NAME     STATUS   ROLES           AGE    VERSION   LABELS
master   Ready    control-plane   2d1h   v1.26.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=

我们在标签栏位里面可以找到 node-role.kubernetes.io/control-plane=

你可以查看一下node节点的,是没有的,而且他这个好像是没有value的,只有key,那他好像就是读取的control-plane这个内容,那我么如果加上一个前缀跟他一样的,但是最后这里我们将他修改成其他值,我们来看看效果

bash 复制代码
# 我们同样不给他value
[root@master k8s]# kubectl label nodes master node-role.kubernetes.io/master=
node/master labeled
# 现在我们再来查看一下这个节点的角色
[root@master k8s]# kubectl get nodes/master 
NAME     STATUS   ROLES                  AGE    VERSION
master   Ready    control-plane,master   2d1h   v1.26.0

我们会发现他确实是把master加上去了,其实这个标签是很特殊的,它并不需要value,如果你想要给他value也是可以的,不会报错,但是他并不会使用你给的value来当他的角色

修改node节点的角色,将他的角色修改成他的主机名

bash 复制代码
# 我们已经知道他的规则了,那我们想要修改就非常的容易了
[root@master k8s]# kubectl label nodes node1 node-role.kubernetes.io/node1=
[root@master k8s]# kubectl label nodes node2 node-role.kubernetes.io/node2=

我们来验证一下

bash 复制代码
[root@master k8s]# kubectl get nodes
NAME     STATUS   ROLES                  AGE    VERSION
master   Ready    control-plane,master   2d1h   v1.26.0
node1    Ready    node1                  2d1h   v1.26.0
node2    Ready    node2                  2d1h   v1.26.0

没有任何的问题

标签的作用

我们之前是可以通过一些方法,将pod指定到节点上去创建,那么为什么要这么干呢,为什么不让他自己调度呢

我们可以这样设想一下,如果你用的是服务器搞的集群,并且服务器的配置还不太一样,比如有一台服务器他的CPU很强,算力很高,但是硬盘的读写速度不太行

另外一台服务器CPU没有那么好,但是硬盘用的NVMe的,读写速度那是相当的快,你现在需要创建一个pod,这个pod是跑数据库,只需要他读写速度快就好了,并不需要CPU有很强的算力,那我们能让他自己调度吗?显然是不太行的,所以我们需要指定他调度到那一台硬盘好的服务器上,那我们就可以给这两台服务器都打上标签,一台是高算力,一台是快IO对吧

那我们在以后去调度pod的时候是不是直接通过标签去选择就可以了呢,对吧

Cordon,Drain以及污点

Cordon--告警警戒

这个的意思就是,只要节点被打上这个标记了,那么他就不会参与到调度算法里面了,我们可以来看看,记住,他是不参与到调度算法里,如果这个节点已经存在pod,是没有影响的

bash 复制代码
# 我们先查看一下node的状态
[root@master k8s]# kubectl get nodes
NAME     STATUS   ROLES                  AGE    VERSION
master   Ready    control-plane,master   2d2h   v1.26.0
node1    Ready    node1                  2d2h   v1.26.0
node2    Ready    node2                  2d2h   v1.26.0

一切都是正常的,现在我们来给node1加一个cordon,然后再查看

bash 复制代码
[root@master k8s]# kubectl cordon node1 
node/node1 cordoned
[root@master k8s]# kubectl get nodes
NAME     STATUS                     ROLES                  AGE    VERSION
master   Ready                      control-plane,master   2d2h   v1.26.0
node1    Ready,SchedulingDisabled   node1                  2d2h   v1.26.0
node2    Ready                      node2                  2d2h   v1.26.0

现在我们可以看见,node1的状态是Ready,但是后面还有一个参数,是不能被调度,那我们现在来创建pod,看看是否真的真的不会在node1上创建出来

bash 复制代码
[root@master k8s]# kubectl run pod01 --image=nginx --image-pull-policy=IfNotPresent 
pod/pod01 created
[root@master k8s]# kubectl run pod02 --image=nginx --image-pull-policy=IfNotPresent 
pod/pod02 created
[root@master k8s]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
pod01   1/1     Running   0          15s   10.244.104.59   node2   <none>           <none>
pod02   1/1     Running   0          10s   10.244.104.60   node2   <none>           <none>

我们创建了2个pod,他确实都是在node2上起的,你还可以继续创建更多pod他也只会在node2上

好的,我们现在知道了他不会在node1上创建了,那我们如果在node2上也加一个cordon呢,那pod是在哪呢?master上吗?

bash 复制代码
[root@master k8s]# kubectl cordon node2 
node/node2 cordoned
[root@master k8s]# kubectl run pod03 --image=nginx --image-pull-policy=IfNotPresent 
pod/pod03 created
[root@master k8s]# kubectl get pods 
NAME    READY   STATUS    RESTARTS   AGE
pod01   1/1     Running   0          95s
pod02   1/1     Running   0          90s
pod03   0/1     Pending   0          4s

我们可以看到,他现在的状态是pending,他既没有创建到node1,也没到node2上,那master上没有做cordon,他为什么没有在master上创建呢?这个问题留着,等会就知道了

我们取消cordon

bash 复制代码
[root@master k8s]# kubectl uncordon node1 
node/node1 uncordoned
[root@master k8s]# kubectl uncordon node2
node/node2 uncordoned

Drain

他跟Cordon的共同点是,只要加上了这个操作,那么他们都是不可被调度的,不同点是Drain他会比Dordon多一个动作,Dordon对于已经存在的pod是不会驱逐的,但是Drain对于已经存在的pod是会进行驱逐的

我们来做个实验看看

bash 复制代码
# 我们先跑2个pod,让他自己调度,不出意外应该是一个在node1,一个在node2
[root@master k8s]# kubectl run pod01 --image=nginx --image-pull-policy=IfNotPresent
pod/pod01 created
[root@master k8s]# kubectl run pod02 --image=nginx --image-pull-policy=IfNotPresent
pod/pod02 created
[root@master k8s]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod01   1/1     Running   0          10s   10.244.104.61    node2   <none>           <none>
pod02   1/1     Running   0          6s    10.244.166.166   node1   <none>           <none>

现在每个节点上都被调度了一个pod,那我们现在给node1加上Cordon,给node2加上Drain,来看看他们的区别

bash 复制代码
[root@master k8s]# kubectl cordon node1
node/node1 cordoned
[root@master k8s]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE    IP               NODE    NOMINATED NODE   READINESS GATES
pod01   1/1     Running   0          2m1s   10.244.104.61    node2   <none>           <none>
pod02   1/1     Running   0          117s   10.244.166.166   node1   <none>           <none>

在node1上加上cordon之后pod是没有任何的变化的

bash 复制代码
# 现在我们给node2加上Drain
# 注意,一定加加上--ignore-daemonsets 和--force
[root@master k8s]# kubectl drain node2 --ignore-daemonsets=true --force
node/node2 cordoned
Warning: ignoring DaemonSet-managed Pods: calico-system/calico-node-9f7ck, calico-system/csi-node-driver-hzj2r, kube-system/kube-proxy-xmxpj; deleting Pods that declare no controller: default/pod01
evicting pod tigera-operator/tigera-operator-cfc98749c-nzvs8
evicting pod default/pod01
pod/tigera-operator-cfc98749c-nzvs8 evicted
pod/pod01 evicted
node/node2 drained

现在我们再来查看一下pod

bash 复制代码
[root@master k8s]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
pod02   1/1     Running   0          32m
[root@master k8s]#

现在我们发现pod01已经没有了,想要取消的话直接使用取消Cordon的命令,原因是Drain的过程是先给节点打上Cordon,然后开始驱逐,所以它也是有Cordon这一步动作的,所以是可以直接用Cordon命令取消的

驱逐演示

刚刚使用pod他是直接将pod给删掉了,并没有在其他的地方把这个pod搞起来,驱逐难道不是应该给他换个地方吗?这其实是因为pod的原因,我们可以使用deployment控制器来实现这个效果,控制器现在只需要了解一下就行了,后面会说到,大概就是你给这个控制器一个你想要的规模数量,比如我想要5个pod,那么他会保持你的pod在5个,多了删,少了补

bash 复制代码
# 生产yaml文件
[root@master k8s]# kubectl create deployment web01 --image=nginx --dry-run=client -o yaml > depolyment.yaml
yaml 复制代码
metadata:
  creationTimestamp: null
  labels:
    app: web01
  name: web01
spec:
  replicas: 5
  selector:
    matchLabels:
      app: web01
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web01
    spec:
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources: {}
status: {}
bash 复制代码
# 我们使用这个文件来创建控制器,然后在给node2加上Drain
[root@master k8s]# kubectl get pods -owide
NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
web01-854bdfcbd8-6j958   1/1     Running   0          29s   10.244.104.12    node2   <none>           <none>
web01-854bdfcbd8-dlx6r   1/1     Running   0          29s   10.244.104.10    node2   <none>           <none>
web01-854bdfcbd8-mcc9q   1/1     Running   0          29s   10.244.166.170   node1   <none>           <none>
web01-854bdfcbd8-rd8sv   1/1     Running   0          29s   10.244.104.11    node2   <none>           <none>
web01-854bdfcbd8-v2tfn   1/1     Running   0          29s   10.244.166.169   node1   <none>           <none>
# 加上Drain
[root@master k8s]# kubectl drain node2 --ignore-daemonsets --force
[root@master k8s]# kubectl get pods -owide
NAME                     READY   STATUS    RESTARTS   AGE    IP               NODE    NOMINATED NODE   READINESS GATES
web01-854bdfcbd8-6mmcx   1/1     Running   0          15s    10.244.166.173   node1   <none>           <none>
web01-854bdfcbd8-cdkmw   1/1     Running   0          15s    10.244.166.172   node1   <none>           <none>
web01-854bdfcbd8-j82mv   1/1     Running   0          15s    10.244.166.171   node1   <none>           <none>
web01-854bdfcbd8-mcc9q   1/1     Running   0          102s   10.244.166.170   node1   <none>           <none>
web01-854bdfcbd8-v2tfn   1/1     Running   0          102s   10.244.166.169   node1   <none>           <none>

现在我们可以看到之前在node2上的pod现在全部都被干掉了,然后又重新被调度到了node1上,这个就是驱逐

污点

pod为什么不会宁愿是pending他都不会调度到master上呢?因为master上默认就是有污点的,我们来看看

bash 复制代码
[root@master k8s]# kubectl describe node master |grep Taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

我们现在可以看到,他这个有显示Taints里面有个NoSchedule,就是不被调度,这样一切就都解释的通了,这也就是为什么master上默认不会运行业务pod

我们再来看看node1上有没有这个

bash 复制代码
[root@master k8s]# kubectl describe node master |grep Taint
Taints:             node-role.kubernetes.io/control-plane:NoSchedule

注意了,你如果查到的node1是这样的,说明你之前做的Cordon没有取消,一定要取消掉,还原他的默认调度策略

bash 复制代码
# 取消完之后他就应该是这样的,污点显示none,没有任何的污点
[root@master k8s]# kubectl describe node node1 |grep Taint
Taints:             <none>

我们来给node1也加上一个污点,让他不被调度

bash 复制代码
# 注意,打污点的时候也是key:value的形式,但是key是什么并不重要,重要的value
[root@master k8s]# kubectl taint node node1 wudian:NoSchedule
node/node1 tainted

这样污点就被打上了,刚刚说过了,污点的key并不重要,随意是什么都可以的

现在来创建pod,他是一定会在node2上创建pod的,因为master和node1都有污点,我们来看看

bash 复制代码
[root@master k8s]# kubectl run taint-pod2 --image=nginx --image-pull-policy=IfNotPresent
pod/taint-pod2 created
[root@master k8s]# kubectl run taint-pod3 --image=nginx --image-pull-policy=IfNotPresent
pod/taint-pod3 created
[root@master k8s]# kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
taint-pod    1/1     Running   0          22s   10.244.104.62    node2   <none>           <none>
taint-pod2   1/1     Running   0          8s    10.244.104.63    node2   <none>           <none>
taint-pod3   1/1     Running   0          4s    10.244.104.1     node2   <none>           <none>

可以看到,确实所有的pod都被调度到了node2上

污点的删除也很简单,只需要在key后面加上-就可以了

bash 复制代码
[root@master k8s]# kubectl taint node node1 wudian-
node/node1 untainted

也是可以把master上的污点给他删除掉的,删除之后后面再创建pod他就会往master上进行调度了

污点的Cordon的区别

看到这里,也许没有搞清楚污点和Cordon他们的区别在哪,不都是不能被调度吗。为什么要搞这么多一样的功能呢?其实他们是有其别的,你看,污点这个名字,是不是就像你读书的时候学校给你的处分啊,难道说学校给你处分之后,你就不能来学校读书了吗?当然是可以的啊,这个Cordon就像是你在学校搞了很严重的事情,现在老师让你回家反省一周,你能回去一天就来学校吗?肯定不行啊,这个也就是他们的区别

如果节点存在污点,但是我指定了污点容忍,这个节点也会参与到调度中来,那么他依旧是可以被创建出来的,但是你这个节点有Cordon,不管你怎么指定,他都是pending状态的

bash 复制代码
# 实践是检验真理的唯一标准,上操作,还记得我们之前使用标签指定pod在哪个节点上创建吧。
# 我们给node1指定一个标签,同样给他一个NoSchedule的污点,再通过yaml文件来指定污点容忍,以及节点选择
[root@master k8s]# kubectl label nodes node1 cloud=666
node/node1 labeled
[root@master k8s]# kubectl taint node node1 cloud=666:NoSchedule
node/node1 tainted

现在我们已经操作好了,他既有标签,也有污点,直接只用yaml文件来创建pod

yaml 复制代码
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod01
  name: pod01
spec:
  containers:
  - image: nginx

    imagePullPolicy: IfNotPresent
    name: pod01
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
# 在这里加上的是节点选择器
  nodeSelector:
          cloud: "666"
# 这里加上的污点容忍,key=value:effect 这个要跟之前定义的污点一样
  tolerations:
  - key: "cloud"
    operator: "Equal"
    value: "666"
    effect: "NoSchedule"
status: {}

使用这个yaml文件来看看效果

bash 复制代码
[root@master k8s]# kubectl apply -f label1.yml 
pod/pod01 created
[root@master k8s]# kubectl get pods -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod01   1/1     Running   0          5s    10.244.166.168   node1   <none>           <none>

我们可以看到,虽然node1有污点,但是这个pod有污点容忍,他一样可以被调度到node1上