The Pod “nodeName” is invalid: metadata.name: Invalid value: “nodeName”: a DNS-1123 subdomain must consist of lower case alphanumeric characters, ‘-’ or ‘.’, and must start and end with an alphanumeric character (e.g. ‘example.com’, regex used for validation is ‘a-z0-9?(.a-z0-9?)*’)


* 发现报错。下面才是**正确的配置文件**(**因为kubernetes中的yaml配置文件要用小写,不能含有大写**):



apiVersion: v1
kind: Namespace
metadata:
name: test

apiVersion: v1
kind: Pod
metadata:
labels:
app: nodename-label
name: nodename
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
nodeName: k8s-slave01 #指定这个Pod调度到节点名称为k8s-slave01的节点上


* 再次运行即可:



[root@k8s-master ~]# kubectl apply -f nodeName.yaml
namespace/test unchanged
pod/nodename created


* 查看Pod列表,发现该Pod被调度到k8s-slave01上了:



[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nodename 1/1 Running 0 8s 10.244.1.20 k8s-slave01


###### nodeSelector定向调度


nodeSelector定向调度所指定的是一对标签label键值对,通过这个指定的label去匹配k8s节点,当k8s中的某个节点有这个label则会把Pod调度到这个节点上去。


* 给k8s-slave01打上标签:



kubectl label node k8s-slave01 role=user


* 给k8s-slave02打上标签:



kubectl label node k8s-slave02 role=admin


* 创建yaml文件



vim nodeselector.yaml


* 内容如下:



apiVersion: v1
kind: Namespace
metadata:
name: test

apiVersion: v1
kind: Pod
metadata:
labels:
app: nodeselector-label
name: nodeselector
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
nodeSelector: #筛选节点有role=admin这个标签,并调度到这个节点上
role: admin


* 运行这个配置文件:



kubectl apply -f nodeselector.yaml


* 再次查看一下:



[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nodeselector 1/1 Running 0 9s 10.244.2.26 k8s-slave02


###### 亲和性调度


* **亲和性调度可以说是nodeSelector的升级版**,区别如下:


	+ **nodeSelector的特点是不管存不存在符合条件的节点都会调度上去,这样就会导致调度上去的Pod无法使用。**
	+ **而亲和性调度的特点是如果存在符合条件的节点就会调度上去,如果不存在符合条件的节点的话也会调度到其他不符合条件的节点上去,这样就能保证Pod无论什么情况都能够正常运行。**
* 查看一下亲和性调度的种类:



[root@k8s-master ~]# kubectl explain pods.spec.affinity
KIND: Pod
VERSION: v1
RESOURCE: affinity
FIELDS:
nodeAffinity
Describes node affinity scheduling rules for the pod.

podAffinity
Describes pod affinity scheduling rules (e.g. co-locate this pod in the
same node, zone, etc. as some other pod(s)).

podAntiAffinity
Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
in the same node, zone, etc. as some other pod(s)).


###### nodeAffinity(requiredDuringSchedulingIgnoredDuringExecution硬限制类型)


**nodeAffinity:让Pod调度到符合标签的node节点上。(说白了就是靠近符合标签的node)**


* nodeAffinity的可配置项:



pod.spec.affinity.nodeAffinity
requiredDuringSchedulingIgnoredDuringExecution # Node节点必须满足指定的所有规则才可以,相当于硬限制
nodeSelectorTerms # 节点选择列表
matchFields # 按节点字段列出的节点选择器要求列表
matchExpressions # 按节点标签列出的节点选择器要求列表(推荐)
key # 键
values # 值
operator # 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, Lt
preferredDuringSchedulingIgnoredDuringExecution # 优先调度到满足指定的规则的Node,相当于软限制 (倾向)
preference # 一个节点选择器项,与相应的权重相关联
matchFields # 按节点字段列出的节点选择器要求列表
matchExpressions # 按节点标签列出的节点选择器要求列表(推荐)
key # 键
values # 值
operator # 关系符 支持In, NotIn, Exists, DoesNotExist, Gt(大于), Lt(小于)
weight # 倾向权重,在范围1-100(值越大,优先级越高)


* 关系符:



  • matchExpressions:
    • key: nodeenv # 匹配存在标签的key为nodeenv的节点
      operator: Exists
    • key: nodeenv # 匹配标签的key为nodeenv,且value是"xxx"或"yyy"的节点
      operator: In
      values: [“xxx”,“yyy”]
    • key: nodeenv # 匹配标签的key为nodeenv,且value大于"xxx"的节点
      operator: Gt
      values: “xxx”

* **我们已经给slave01和slave2分别打上role=user和role=admin标签**



[root@k8s-master ~]# kubectl get nodes -o wide --show-labels
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME LABELS
k8s-master Ready master 9d v1.17.4 192.168.184.100 CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://18.6.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master,kubernetes.io/os=linux,node-role.kubernetes.io/master=
k8s-slave01 Ready 9d v1.17.4 192.168.184.101 CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://18.6.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-slave01,kubernetes.io/os=linux,role=user
k8s-slave02 Ready 9d v1.17.4 192.168.184.102 CentOS Linux 7 (Core) 3.10.0-1160.el7.x86_64 docker://18.6.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-slave02,kubernetes.io/os=linux,role=admin


* 创建yaml文件



vim nodeaffinity-required.yaml


* 内容如下:



apiVersion: v1
kind: Namespace
metadata:
name: test

apiVersion: v1
kind: Pod
metadata:
labels:
app: nodeaffinity-required-label
name: nodeaffinity-required
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
affinity: # 亲和性配置
nodeAffinity: # node亲和性配置
requiredDuringSchedulingIgnoredDuringExecution: # Node节点必须满足指定的所有规则才可以,相当于硬规则,类似于定向调度
nodeSelectorTerms: # 节点选择列表
- matchExpressions:
- key: role # 匹配存在标签的key为role的节点,并且value是"user111"或"admin111"的节点
operator: In
values:
- “user111”
- “admin111”


* 执行配置文件:



[root@k8s-master ~]# kubectl apply -f nodeaffinity-required.yaml
namespace/test unchanged
pod/nodeaffinity-required created


* 下面可以看到3 node(s) didn’t match node selector(**调度失败**),因为上面的条件是调度到node节点含有role=user111或者role=admin111标签,而我们的slave01节点和slave02节点含有role=user和role=admin标签。



[root@k8s-master ~]# kubectl get pods -n test
NAME READY STATUS RESTARTS AGE
nodeaffinity-required 0/1 Pending 0 11s
[root@k8s-master ~]# kubectl describe pods nodeaffinity-required -n test
Name: nodeaffinity-required
Events:
Type Reason Age From Message


Warning FailedScheduling 27s (x2 over 27s) default-scheduler 0/3 nodes are available: 3 node(s) didn’t match node selector.


* 修改配置文件:



apiVersion: v1
kind: Namespace
metadata:
name: test

apiVersion: v1
kind: Pod
metadata:
labels:
app: nodeaffinity-required-label
name: nodeaffinity-required
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
affinity: # 亲和性配置
nodeAffinity: # node亲和性配置
requiredDuringSchedulingIgnoredDuringExecution: # Node节点必须满足指定的所有规则才可以,相当于硬规则,类似于定向调度
nodeSelectorTerms: # 节点选择列表
- matchExpressions:
- key: role # 匹配存在标签的key为role的节点,并且value是"user111"或"admin111"的节点
operator: In
values:
- “user”
- “admin666”


* 重新执行配置文件:



[root@k8s-master ~]# kubectl delete -f nodeaffinity-required.yaml

[root@k8s-master ~]# kubectl apply -f nodeaffinity-required.yaml


* **可以看到我们的Pod节点成功调度到slave01节点上了,因为我们上面定义的规则slave01是满足的。**



[root@k8s-master ~]# kubectl describe pods nodeaffinity-required -n test
Name: nodeaffinity-required
Events:
Type Reason Age From Message


Normal Scheduled 43s default-scheduler Successfully assigned test/nodeaffinity-required to k8s-slave01
Normal Pulled 42s kubelet, k8s-slave01 Container image “nginx:1.17” already present on machine
Normal Created 42s kubelet, k8s-slave01 Created container nginx-container
Normal Started 42s kubelet, k8s-slave01 Started container nginx-container


###### nodeAffinity(preferredDuringSchedulingIgnoredDuringExecution软限制类型)


* required(硬限制)和preferred(软限制)两种类型的区别就是:
	+ **required(硬限制):1种情况**
		- 1:**required(硬限制)如果找不到符合定义的条件的Pod或者node,则直接调度失败。**
	+ **preferred(软限制):3种情况**
		- 1:preferred(软限制)如果找不到符合定义的条件的Pod或者node,则也会将Pod调度到不符合条件的节点上。
		- 2:如果找到符合定义的条件的Pod或者node,并且只有一个Pod或者node满足条件,则直接调度上去。
		- 3:如果找到符合定义的条件的Pod或者node,并且如果定义了多个条件都是同时满足的话,就会通过weight(权值)进行筛选,挑选出Pod或者node满足的条件对应的weight值最大的那一个。


###### podAffinity


**podAffinity:让Pod调度到符合标签的Pod所在的node节点上。(说白了就是靠近符合标签的Pod)**


* podAffinity的可选配置项:



pod.spec.affinity.podAffinity
requiredDuringSchedulingIgnoredDuringExecution 硬限制
namespaces 指定参照pod的namespace
topologyKey 指定调度作用域
labelSelector 标签选择器
matchExpressions 按节点标签列出的节点选择器要求列表(推荐)
key 键
values 值
operator 关系符 支持In, NotIn, Exists, DoesNotExist.
matchLabels 指多个matchExpressions映射的内容
preferredDuringSchedulingIgnoredDuringExecution 软限制
podAffinityTerm 选项
namespaces
topologyKey
labelSelector
matchExpressions
key 键
values 值
operator
matchLabels
weight 倾向权重,在范围1-100(权值越大,优先级越高)


* **topologyKey用于指定调度的作用域,例如:**


	+ **如果指定为kubernetes.io/hostname,那就是以Node节点为区分范围。说白了就是调度到目标Pod相同的node节点上。(常用)**
	+ 如果指定为beta.kubernetes.io/os,则以**Node节点的操作系统**类型来区分。



> 
> 案例:创建一个targetPod,打上podrole: pod-admin标签,并且定向调度到slave02节点上,再创建一个新的Pod使用Pod亲和性调度匹配podrole标签值为user111或者pod-admin,符合上面的条件则调度到这个targetPod所在的node上。如果案例实验成功,则会出现podaffinity-required的Pod调度到了slave02上。
> 
> 
> 


* 创建yaml文件



vim podaffinity-required.yaml


* 内容如下:



apiVersion: v1
kind: Namespace
metadata:
name: test

apiVersion: v1
kind: Pod
metadata:
labels:
podrole: pod-admin
name: targetpod
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
nodeName: k8s-slave02

apiVersion: v1
kind: Pod
metadata:
labels:
app: podaffinity-required-label
name: podaffinity-required
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
affinity: # 亲和性配置
podAffinity: # Pod亲和性
requiredDuringSchedulingIgnoredDuringExecution: # 硬限制
- labelSelector:
matchExpressions:
- key: podrole
operator: In
values:
- “user111”
- “pod-admin”
topologyKey: kubernetes.io/hostname
namespaces:
- “test” #参照(target)Pod所在的namespace


* 执行配置文件:



[root@k8s-master ~]# kubectl apply -f podaffinity-required.yaml
namespace/test unchanged
pod/targetpod unchanged
pod/podaffinity-required created


* 查看Pod:(成功)



[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podaffinity-required 1/1 Running 0 23s 10.244.2.28 k8s-slave02
targetpod 1/1 Running 0 2m9s 10.244.2.27 k8s-slave02


###### podAntiAffinity


**podAntiAffinity:让Pod调度到不符合标签的Pod所在的node节点上。(说白了就是远离符合标签的Pod)**



> 
> 案例:创建一个targetPod,打上podrole: pod-admin标签,并且定向调度到slave02节点上,再创建一个新的Pod使用Pod的反亲和性调度匹配podrole标签值为user111或者pod-admin,符合上面的条件则调度到这个targetPod相反(不同)的node上。如果案例实验成功,则会出现podaffinity-required的Pod调度到了slave01上。
> 
> 
> 


* 创建yaml文件



vim podantiaffinity-required.yaml


* 内容如下:



apiVersion: v1
kind: Namespace
metadata:
name: test

apiVersion: v1
kind: Pod
metadata:
labels:
podrole: pod-admin
name: targetpod
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
nodeName: k8s-slave02

apiVersion: v1
kind: Pod
metadata:
labels:
app: podantiaffinity-required-label
name: podantiaffinity-required
namespace: test
spec:
containers:
- image: nginx:1.17
name: nginx-container
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
affinity: # 亲和性配置
podAntiAffinity: # Pod的反亲和性
requiredDuringSchedulingIgnoredDuringExecution: # 硬限制
- labelSelector:
matchExpressions:
- key: podrole
operator: In
values:
- “user111”
- “pod-admin”
topologyKey: kubernetes.io/hostname
namespaces:
- “test” #参照(target)Pod所在的namespace


* 执行配置文件:



[root@k8s-master ~]# kubectl apply -f podantiaffinity-required.yaml
namespace/test created
pod/targetpod created
pod/podantiaffinity-required created


* 查看Pod:(成功)



[root@k8s-master ~]# kubectl get pods -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podantiaffinity-required 1/1 Running 0 33s 10.244.1.23 k8s-slave01
targetpod 1/1 Running 0 33s 10.244.2.31 k8s-slave02


###### 污点、容忍调度


###### Taints


* 污点与亲和性调度有什么区别?


	+ **亲和性调度的作用范围可以是node和Pod。而污点的作用范围只能是node**,**我们只能通过给node打上污点(和label不同,污点是taint)**
	+ **污点说白了就是node的一种驱赶策略。除了PreferNoSchedule类型,其他类型的情况下,Pod如果想要调度到有污点的node上,需要进行容忍这个污点,否则Pod将无法调度上去。**
* 污点的格式为:key=value:effect ,key=value是污点标签,effect是污点的类型。污点有三种类型,分为三个等级,第1级最友好,第3级最不友好。
* + 1(最低级):PreferNoSchedule:kubernetes将尽量避免把Pod调度到具有该污点的Node上,除非没有其他节点可以调度。
* + 2(中等):NoSchedule:kubernetes将不会把Pod调度到具有该污点的Node上,但是不会影响当前Node上已经存在的Pod。
* + 3(最高级):NoExecute:kubernetes将不会把Pod调度到具有该污点的Node上,同时也会将Node上已经存在的Pod驱逐。



> 
> 设置污点:
> 
> 
> 


格式:



kubectl taint node node节点名称 key=value:effect



> 
> 去除污点:
> 
> 
> 


格式:



kubectl taint node node节点名称 key:effect-



> 
> 去除所有污点:
> 
> 
> 



kubectl taint node node节点名称 key-



> 
> 查看指定节点上的污点:
> 
> 
> 



kubectl describe node node节点名称



> 
> 案例要求:
> 
> 
> 1:关闭slave02服务器,只保留master和slave01服务器。
> 
> 
> 2:给slave01打上PreferNoSchedule污点(taintkey=taintvalue),再创建一个Pod或者Pod控制器,查看pod调度情况。
> 
> 
> 3:取消slave01的污点,再给slave01打上NoSchedule污点(taintkey=taintvalue),再创建一个Pod或者Pod控制器,查看pod调度情况。
> 
> 
> 4:取消slave01的污点,再给slave01打上NoExecute污点(taintkey=taintvalue),再创建一个Pod或者Pod控制器,查看pod调度情况。
> 
> 
> 


* 创建一个命名空间:



kubectl create ns dev


* 给k8s-slave01打上污点(PreferNoSchedule):



kubectl taint node k8s-slave01 taintkey=taintvalue:PreferNoSchedule


* 运行一个Pod控制器(自动会产生Pod并调度到节点上):



[root@k8s-master ~]# kubectl run pod1 --image=nginx:1.17 -n dev
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/pod1 created


* 查看Pod调度情况:


![img](https://img-blog.csdnimg.cn/img_convert/3c88efcb14c6de4564645cb61420a0db.png)
![img](https://img-blog.csdnimg.cn/img_convert/a1fd981a46835c593d6f5288cd505dcd.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

打上污点(PreferNoSchedule):



kubectl taint node k8s-slave01 taintkey=taintvalue:PreferNoSchedule


* 运行一个Pod控制器(自动会产生Pod并调度到节点上):



[root@k8s-master ~]# kubectl run pod1 --image=nginx:1.17 -n dev
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/pod1 created


* 查看Pod调度情况:


[外链图片转存中...(img-q3FyO4H7-1714516108112)]
[外链图片转存中...(img-XU6ZIlom-1714516108113)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

Logo

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

更多推荐