k8s-标签/亲和性/污点和容忍度
什么是标签?
标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够表示对象的特殊特点,就是一眼就看出了这个Pod是干什么的,标签可以用来划分特定的对象(比如版本,服务类型等),标签可以在创建一个对象的时候直接定义,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的。创建标签之后也可以方便我们对资源进行分组管理。如果对pod打标签,之后就可以使用标签来查看、删除指定的pod。
在k8s中,大部分资源都可以打标签。
给pod资源打标签
#查看pod资源标签
[root@master01 ~]# kubectl get pod -o wide --show-labels NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS busybox 1/1 Running 0 33h 172.16.196.134 node01 <none> <none> run=busybox
#对已经存在的pod打标签
[root@master01 ~]# kubectl label pod -n default busybox hwf=123
pod/busybox labeled
#查看资源标签
#列出默认名称空间下标签值是的pod,不显示标签
[root@master01 ~]# kubectl get pod -l hwf
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 33h
#列出默认名称空间下标签key是的pod,不显示标签
[root@master01 ~]# kubectl get pod -L 123
NAME READY STATUS RESTARTS AGE 123
busybox 1/1 Running 0 33h
#给node打工作标签
[root@master01 ~]# kubectl label node node01 node-role.kubernetes.io/node01= node/node01 labeled [root@master01 ~]# kubectl get node NAME STATUS ROLES AGE VERSION master01 Ready control-plane,master 2d9h v1.21.3 master02 Ready control-plane,master 2d9h v1.21.3 node01 Ready node01 2d9h v1.21.3 node02 NotReady <none> 2d9h v1.21.3
#删除node标签
[root@master01 ~]# kubectl label node node01 node-role.kubernetes.io/node01-
node/node01 labeled
node节点选择器
我们在创建pod资源的时候,pod会根据schduler进行调度,那么默认会调度到随机的一个工作节点,如果我们想要pod调度到指定节点或者调度到一些具有相同特点的node节点,怎么办呢?
可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点
1、nodeName:
指定pod节点运行在哪个具体node上
[root@master1 ~]# cat pod-node.yaml apiVersion: v1 kind: Pod metadata: name: demo-pod namespace: default labels: app: myapp env: dev spec: nodeName: node1 containers: - name: tomcat-pod-java ports: - containerPort: 8080 image: tomcat:8.5-jre8-alpine imagePullPolicy: IfNotPresent - name: busybox image: busybox:latest command: - "/bin/sh" - "-c" - "sleep 3600"
2、nodeSelector:[这种方法你node上要有对应的标签,标签选择器里填写]
指定pod调度到具有哪些标签的node节点上
[root@master1 ~]# cat pod-1.yaml apiVersion: v1 kind: Pod metadata: name: demo-pod-1 namespace: default labels: app: myapp env: dev spec: nodeSelector: disk: ceph containers: - name: tomcat-pod-java ports: - containerPort: 8080 image: tomcat:8.5-jre8-alpine imagePullPolicy: IfNotPresent
亲和性
node节点亲和性
基于node节点所打的标签,把pod调度到node上
node节点亲和性调度:nodeAffinity
space: affinity: #亲和性 nodeAffinity: <Object> #node亲和性 preferredDuringSchedulingIgnoredDuringExecution: <[]Object> #表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性 requiredDuringSchedulingIgnoredDuringExecution: <Object> #表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性 nodeSelectorTerms: #node 标签 - matchExpressions: <[]Object> #匹配表达式的 - key: hwf <string> -required- #检查label operator: <string> -required- #做等值选则还是不等值选则 values: <[]string> #给定值 - 123 - xx - matchFields: <[]Object> #匹配字段的 - key: <string> -required- values: <[]string>
例1:使用requiredDuringSchedulingIgnoredDuringExecution硬亲和性
[root@master1 ~]# cat pod-nodeaffinity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-node-affinity-demo namespace: default labels: app: myapp tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: zone operator: In values: - foo - bar
我们检查当前节点中有任意一个节点拥有zone标签的值是foo或者bar,就可以把pod调度到这个node节点的foo或者bar标签上的节点上
[root@master1 ~]# kubectl apply -f pod-nodeaffinity-demo.yaml [root@master1 ~]# kubectl get pods -o wide | grep pod-node pod-node-affinity-demo 0/1 Pending 0 xianchaonode1
status的状态是pending,上面说明没有完成调度,因为没有一个拥有zone的标签的值是foo或者bar,而且使用的是硬亲和性,必须满足条件才能完成调度
[root@master1 ~]# kubectl label nodes xianchaonode1 zone=foo
给这个xianchaonode1节点打上标签zone=foo,在查看
[root@xianchaomaster1 ~]#kubectl get pods -o wide 显示如下: pod-node-affinity-demo 1/1 Running 0 xianchaonode1
例2:使用preferredDuringSchedulingIgnoredDuringExecution软亲和性
[root@xianchaomaster1 ~]# cat pod-nodeaffinity-demo-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-node-affinity-demo-2
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: zone1
operator: In
values:
- foo1
- bar1
weight: 60
[root@xianchaomaster1 ~]# kubectl apply -f pod-nodeaffinity-demo-2.yaml
[root@xianchaomaster1 ~]# kubectl get pods -o wide |grep demo-2
pod-node-affinity-demo-2 1/1 Running 0 xianchaonode1
上面说明软亲和性是可以运行这个pod的,尽管没有运行这个pod的节点定义的zone1标签
Node节点亲和性针对的是pod和node的关系,Pod调度到node节点的时候匹配的条件
Pod节点亲和性
第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。
- 节点名称
- 节点标签
pod自身的亲和性调度有两种表示形式:
- podaffinity:pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;
例1:pod节点亲和性
定义两个pod,第一个pod做为基准,第二个pod跟着它走
[root@xianchaomaster1 ~]# cat pod-required-affinity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-first labels: app2: myapp2 tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: backend tier: db spec: containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app2, operator: In, values: ["myapp2"]} topologyKey: kubernetes.io/hostname
topologyKey: kubernetes.io/hostname
- 不写具体表示第一个pod调度到哪个节点,第二个pod跟着调度到相同节点
- 节点名称
- 节点标签
#上面表示创建的pod必须与拥有app=myapp标签的pod在一个节点上
[root@master1 ~]# kubectl apply -f pod-required-affinity-demo.yaml kubectl get pods -o wide 显示如下: pod-first running node1 pod-second running node1
- podunaffinity:pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。
例2:pod节点反亲和性
定义两个pod,第一个pod做为基准,第二个pod跟它调度节点相反
[root@master1 ~]# cat pod-required-anti-affinity-demo.yaml apiVersion: v1 kind: Pod metadata: name: pod-first labels: app1: myapp1 tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: backend tier: db spec: containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app1, operator: In, values: ["myapp1"]} topologyKey: kubernetes.io/hostname
显示两个pod不在一个node节点上,这就是pod节点反亲和性
[root@master1 ~]# kubectl apply -f pod-required-anti-affinity-demo.yaml [root@master1 ~]# kubectl get pods -o wide 显 pod-first running node1 pod-second running node2
例3:换一个topologykey,换成node标签【使用这种有可能一个对于pod创建先后顺序有要求】
[root@master1 ~]# kubectl label nodes xianchaonode2 zone=foo [root@master1 ~]# kubectl label nodes xianchaonode1 zone=foo --overwrite
[root@xianchaomaster1]# cat pod-first-required-anti-affinity-demo-1.yaml apiVersion: v1 kind: Pod metadata: name: pod-first labels: app3: myapp3 tier: frontend spec: containers: - name: myapp image: ikubernetes/myapp:v1 --- apiVersion: v1 kind: Pod metadata: name: pod-second labels: app: backend tier: db spec: containers: - name: busybox image: busybox:latest imagePullPolicy: IfNotPresent command: ["sh","-c","sleep 3600"] affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - {key: app3 ,operator: In, values: ["myapp3"]} topologyKey: zone
[root@master1 ~]#kubectl get pods -o wide 显示如下: pod-first running xianchaonode1 pod-second pending <none>
第二个节点现是pending,因为两个节点是同一个位置,现在没有不是同一个位置的了,而且我们要求反亲和性,所以就会处于pending状态,如果在反亲和性这个位置把required改成
污点、容忍度
给了节点选则的主动权,我们给节点打一个污点,不容忍的pod就运行不上来,污点就是定义在节点上的键值属性数据,可以定决定拒绝那些pod;
taints是键值数据,用在节点上,定义污点;
tolerations是键值数据,用在pod上,定义容忍度,能容忍哪些污点
pod亲和性是pod属性;但是污点是节点的属性,污点定义在nodeSelector上
#查看节点的污点
[root@master01 ~]# kubectl describe nodes master01 |grep Taints:
Taints: node-role.kubernetes.io/master:NoSchedule
Taint 给某个node节点设置污点
Taint 排斥效果
- NoSchedule: 仅影响调度过程,对现存的pod对象不产生影响;但容忍的pod同时也能够被分配到集群中的其它节点
- NoExecute: 即影响调度过程,也影响现在的Pod对象;不容忍的Pod对象将被驱逐
- PreferNoSchedule: 最好别调度过来,实在没地方了来这里也行
添加污点 Kubectl taint node node1 item-name=assistant:NoExecute Kubectl taint node node2 item-name=sca:NoExecute Kubectl taint node node3 item-name=xx:NoExecute
删除污点 kubectl taint node node1 item-name- Kubectl taint node node2 item-name- Kubectl taint node node3 item-name-
Pod容忍度
你只要pod上配置的策略和节点上的策略一致就能容忍你
[root@xianchaomaster1 ~]# kubectl explain node.spec.taints KIND: Node VERSION: v1 RESOURCE: taints <[]Object> DESCRIPTION: If specified, the node's taints. The node this Taint is attached to has the "effect" on any pod that does not tolerate the Taint. FIELDS: effect <string> -required- key <string> -required- timeAdded <string> value <string>
taints的effect用来定义对pod对象的排斥等级(效果):
- NoSchedule: 仅影响调度过程,对现存的pod对象不产生影响;但容忍的pod同时也能够被分配到集群中的其它节点
- NoExecute: 即影响调度过程,也影响现在的Pod对象;不容忍的Pod对象将被驱逐
- PreferNoSchedule: 最好别调度过来,实在没地方了来这里也行
#两个值:Exists表示只要节点有这个污点的key,pod都能容忍,值是什么都行;Equal表示只要节点必须精确匹配污点的key和value才能容忍;
写法一:Equal等值,必须所有都匹配pod才会创建
tolerations: #Pod容忍度 - key: "node-type" #key值 operator: "Equal" #等值关系,等于 value: "production" #node-type/production:NoSchedule effect: "NoExecute" #策略 tolerationSeconds: 3600 #表示可以多存活3600秒,一般不用
写法二:Exists表示只要节点有这个污点的key,pod都能容忍,值是什么都行;
tolerations: #Pod容忍度 - key: "node-type" #key值 operator: "Exists" #非等值关系 value: "" #node-type/production:NoSchedule effect: "NoExecute" #策略
写法三:Exists表示只要节点有这个污点的key,pod都能容忍,值是什么都行;
tolerations: #Pod容忍度 - key: "node-type" #key值 operator: "Exists" #非等值关系 value: "" #node-type/production:NoSchedule effect: "" #策略

评论