前言

在刚开始接触到K8S的时候,曾经遇到了一个卡住我两天的一个问题,情况就是我要创建一个三节点的zookeeper,但是创建后发现只有两个节点能够正常调度,有一个节点总是无法调度,如下图所示:

当时一直通过日志想了解到底是哪里的问题,结果后来经高人指点才知道是K8S的亲和性以及污点造成的。具体的原因是zookeeper的yaml文件中由于亲和性的配置,导致zookeeper的实例一个节点上只能有一个,而5台机器的K8S集群,有三台机器被打上了污点,导致无法被调度,这就造成了三个zookeeper实例只能调度两个,总有一个节点无法调度。

亲和性后续的文章我们再来讲解,今天的文章来说说K8S的污点(taint)以及与之对应的例外配置容忍(tolerations)。

正文

回到今天的文章的标题,结合当前的学区的招生简章,来详细说明下K8S中的污点和容忍相关的知识,方便大家理解。

学区招生简章

当K8S这个学区(集群)刚建立的时候,几所学校(节点)开始对外招生(应用实例),开始的时候人少的时候一切安好,没有任何问题,也没有任何限制措施,大家根据自己的喜好来挑选学校。但是时间长了之后,就会出现学校学生不均衡的问题,很多学校尤其是好学校(例如K8S主节点)招生明显超过了自身的负载,严重影响教学质量。那有什么办法能解决学生分配的问题呢?

此时,K8S学区就开始考虑针对不同的学校进行不同的招生策略,主要由下面三种方式:

  • 只出不进:这种情况下,学校不招收新的学生,已经在学校的学生则继续在学校学习知道毕业。

  • 全部清除:这种情况比较极端,新的学生不招收,旧的学生也全部遣散,一般情况下是学校进入维修模式(服务器出问题)或者将资源留给特别的学生,比如说学校附近有学区房的学生(例如K8S的系统资源)

  • 尽量不进:这种情况下,学校原则上是尽量不招新生了,但是如果特殊情况下必须要进这所学校,也可以接收新生。

污点详解

上面就是现实情况下的学校招生简章,对应到K8S中就是今天讲的主要内容:污点(taint)

污点这个名字起得很有特点,开始我也不是很理解,后来想一下,其实可以这么理解,污点就算是节点上的一个标签,应用的pod在部署的时候会对节点进行政审,如果某些污点不满足需求的话,那么就无法部署在该节点。

针对学区招生简章三种方式映射到K8S的污点就分为如下三种模式:

  • 只出不进-NoSchedule:如果Node上有NoSchedule污点,而Pod上不带相应容忍,Kubernetes就不会调度Pod到这台Node上。

  • 全部清除-NoExecute:如果Node上有NoExecute污点,这时已经在Node上运行的Pod会从Node上驱逐掉,没有运行在Node的Pod不能被调度到这个Node上。

  • 尽量不进-PreferNoSchedule:如果Node上有PreferNoShedule污点,Kubernetes会尽量不调度Pod到这个Node上。

污点组成: key、value及一个effect三个元素

格式如下:

<key>=<value>:<effect>

下面来看一下master节点上NoSchedule的例子:

最后再来看看操作taint相关的命令:

# 设置污点,能达到上面图片的那个效果
kubectl taint nodes k8s-server5 node-role.kubernetes.io/master=:NoSchedule

# 查看污点状况
kubectl describe node k8s-server5|grep Taints

# 删除污点(两种方式皆可)
kubectl taint node k8s-server5 key:NoSchedule-

kubectl taint node master1 node-role.kubernetes.io/master:NoSchedule-

另外K8S针对node状态预置了代表node问题的污点,node控制器当某种条件成立的时候会自动的给node打上污点。下面是其中内置的污点(准确的是污点的key):

# node不是ready状态。对应于node的condition ready=false.
node.kubernetes.io/not-ready

# node controller与node失联了。对应于node的condition ready=unknown
node.kubernetes.io/unreachable

# node磁盘空间不足
node.kubernetes.io/out-of-disk

# :node的网络中断
node.kubernetes.io/network-unavailable

# node不可调度状态
node.kubernets.io/unschedulable

# kubelet是由外部云提供商提供的时候,刚开始的时候会打上这个污点来标记还未被使用。当cloud-controller-manager控制器初始化完这个node,kubelet会自动移除这个污点
node.cloudprovider.kubernetes.io/uninitalized

学区房

上面说了学区的招生简章,但是如果在这个简章下还想进相应的学校,那就需要一定的条件了,那这个条件大家肯定都很熟悉,没错就是学区房了。只要有了学区房,就可以无视学校的招生限制而直接入学了。

容忍

在K8S中,学区房对应的其实就是容忍(tolerations)。通过在创建pod的时候设置容忍,可以绕过匹配污点的限制而在该node上进行pod的部署。

Pod对象的容忍度可通过其spec.tolerations字段进行添加,根据使用的操作符不同,主要有两种可用的形式:一种是与污点信息完全匹配的等值(Equal)关系;另一种是判断污点信息存在性(Exists)的匹配方式。

下面看看几种tolerations方式配置的例子:

# 等值判断,key、value以及effect信息需要完全匹配
tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

# 存在性判断,key存在且effect相同,忽略value值的判断
tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 3600

# 不指定key值时,表示容忍所有的污点key(master节点也会部署)
tolerations:
- operator: "Exists"

# 不指定effect值时,表示容忍所有的污点effect
tolerations:
- key: "key"
  operator: "Exists"

最后Kubernetes的核心组件通常都要容忍部分污点,以确保其相应的控制器能够无视此类污点而在节点上部署相应的关键性Pod对象,例如kube-proxy等kube-system空间下的Pod。

下图就是某核心Pod的tolerations配置:

总结

本文主要讲述了Taint(污点)和 Toleration(容忍)相关的定义以及用法,从上文可以看出这两个功能的目的是优化pod在集群间的调度。

这跟节点亲和性类似,只不过它们作用的方式相反,具有taint的node和待部署的pod之间是互斥关系,可以通过toleration可以改变taint对Pod部署的影响。

而具有节点亲和性关系的node和逮捕书的pod之间是相吸的关系。这两者相互配合共同完善了Pod的调度机制,也满足了在不同场景下Pod的调度需求。

最后,如果想一起入门学习K8S的小伙伴,欢迎点赞转发加关注,下次学习不迷路,我们在K8S的路上共同前进!

最后挂个公众号二维码,公众号的文章是最新的,CSDN的会有些滞后,想追更的朋友欢迎大家关注公众号,谢谢大家支持。 

公众号地址:

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐