node 节点选择器
我们在创建 pod 资源的时候,pod 会根据 schduler 进行调度,那么默认会调度到随机的一个工
作节点,如果我们想要 pod 调度到指定节点或者调度到一些具有相同特点的 node 节点,怎么办呢?
可以使用
pod 中的 nodeName 或者 nodeSelector 字段指定要调度到的 node 节点
1、nodeName:
指定
pod 节点运行在哪个具体 node
cat pod-node.yaml
apiVersion: v1 #pod属于k8s核心组v1
kind: Pod #创建的是一个pod资源
metadata: #元数据
name: demo-pod1 #pod名字
namespace: default #pod所属的名称空间
labels: #标签
app: myapp #pod具有的标签
env: dev #pod具有的标签
spec:
nodeName: god64
containers: #定义一个容器,容器是独享列表
- name: tomcat-pod-java #容器名字
ports:
- containerPort: 8080 #容器内部的port
的 image: tomcat:8.5-jre8-alpine #容器使用的景象
imagePullPolicy: IfNotPresent #容器拉取的策略
- name: busybox
image: busybox:latest
command: #command是一个列表,定义的时候下面的参数加横线
- "/bin/sh"
- "-c"
- "sleep 3600"
#kubectl apply -f pod-node.yaml
#kubectl get pods -o wide 查看调度到哪里了
#优雅删除
kubectl delete -f pod-node.yaml
#强制删除
kubectl delete -f pod-node.yaml --force --grace-period=0
2、nodeSelector:
指定
pod 调度到具有哪些标签的 node 节点上
#给 node 节点打标签,打个具有 disk=ceph 的标签
kubectl label nodes god62 disk=ceph
kubectl get nodes god62 --show-labels
#定义 pod 的时候指定要调度到具有 disk=ceph 标签的 node 上
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod-1
namespace: default
labels:
app: myapp
env: dev
spec:
nodeSelector: ##定义 pod 的时候指定要调度到具有 disk=ceph 标签的 node 上
disk: ceph
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
#更新,查看调度到哪里了
kubectl apply -f pod-1.yaml
kubectl get pods -o wide
# 查看kubectl describe pods demo-pod 详细信息
3.污点和容忍度
node 节点亲和性调度:nodeAffinity
kubectl explain pods.spec.affinity
FIELDS:
nodeAffinity <Object>
Describes node affinity scheduling rules for the pod.
podAffinity <Object>
Describes pod affinity scheduling rules (e.g. co-locate this pod in the
same node, zone, etc. as some other pod(s)).
podAntiAffinity <Object>
Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
in the same node, zone, etc. as some other pod(s)).
#在查询kubectl explain pods.spec.affinity.nodeAffinity
preferredDuringSchedulingIgnoredDuringExecution <[]Object>
prefered 表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性
requiredDuringSchedulingIgnoredDuringExecution <Object>
require 表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性
kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.no deSelectorTerms
FIELDS:
matchExpressions <[]Object> matchFields <[]Object>
matchExpressions:匹配表达式的 matchFields: 匹配字段的
nodeSelectorTerms <[]Object> -required- #required必须字段
kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.no deSelectorTerms.matchFields
VERSION: v1
RESOURCE: matchExpressions <[]Object>
DESCRIPTION:
FIELDS:
key <string> -required- operator <string> -required- values <[]string>
key:检查 label
operator:做等值选则还是不等值选则
values:给定值
使用 requiredDuringSchedulingIgnoredDuringExecution 硬亲和性 #把 myapp-v1.tar.gz 上传到 62 和 64 上,手动解压:
docker load -i myapp-v1.tar.gz
vim 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
spec:我们检查当前节点中有任意一个节点拥有 zone 标签的值是 foo 或者 bar,就可以把 pod 调度到 这个 node 节点的 foo 或者 bar 标签上的节点上
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- foo
- bar
kubectl apply -f pod-nodeaffinity-demo.yaml
kubectl get pods -o wide | grep pod-node
status 的状态是 pending,上面说明没有完成调度,因为没有一个拥有 zone 的标签的值是 foo 或者 bar,而且使用的是硬亲和性,必须满足条件才能完成调度
kubectl label nodes god64 zone=foo
给这个 god64 节点打上标签 zone=foo,在查看
使用 preferredDuringSchedulingIgnoredDuringExecution 软亲和性
vi 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
Pod 节点亲和性
pod 自身的亲和性调度有两种表示形式
podaffinity:pod 和 pod 更倾向腻在一起,把相近的 pod 结合到相近的位置,如同一区域,同 一机架,这样的话 pod 和 pod 之间更好通信,比方说有两个机房,这两个机房部署的集群有 1000 台主机,那么我们希望把 nginx 和 tomcat 都部署同一个地方的 node 节点上,可以提高 通信效率;
podunaffinity:pod 和 pod 更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于 反亲和性,这样相互之间不会有影响。
第一个 pod 随机选则一个节点,做为评判后续的 pod 能否到达这个 pod 所在的节点上的运行方 式,这就称为 pod 亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们 在定义 pod 亲和性时需要有一个前提,哪些 pod 在同一个位置,哪些 pod 不在同一个位置,这 个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置, 节点名称不相同的表示不是一个位置。
kubectl explain pods.spec.affinity.podAffinity
podAffinity 亲和性
podAntiAffinity 反亲和性
requiredDuringSchedulingIgnoredDuringExecution: 硬亲和性 preferredDuringSchedulingIgnoredDuringExecution:软亲和性
topologyKey: 位置拓扑的键,这个是必须字段 怎么判断是不是同一个位置: rack=rack1
row=row1
使用 rack 的键是同一个位置
使用 row 的键是同一个位置
labelSelector:
我们要判断 pod 跟别的 pod 亲和,跟哪个 pod 亲和,需要靠 labelSelector,通过 labelSelector 选则一组能作为亲和对象的 pod 资源
namespace:
labelSelector 需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过 namespace 指 定,如果不指定 namespaces,那么就是当前创建 pod 的名称空间
定义两个 pod,第一个 pod 做为基准,第二个 pod 跟着它走 cat pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app: myapp
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: app, operator: In, values: ["myapp"]}
topologyKey: kubernetes.io/hostname
# - {key: app, operator: In, values: ["myapp"]}. key里面的app引用的是之前pod的labels的app
operator 的ln代表等值关系,values: ["myapp]对应app的 myapp ,靠第一个pod的标签对应亲和性,第二个标签会找标签app: myapp的标签
#更新看亲和性
kubectl apply -f pod-required-affinity-demo.yaml
kubectl get pods -o wide
看到pod-second跟pod-first在同一个节点
上面说明第一个 pod 调度到哪,第二个 pod 也调度到哪,这就是 pod 节点亲和性
kubectl delete -f pod-required-affinity-demo.yaml
pod 节点反亲和性
定义两个
pod,第一个 pod 做为基准,第二个 pod 跟它调度节点相反
cat pod-required-anti-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first labels:
app: myapp
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: app, operator: In, values: ["myapp"]} topologyKey: kubernetes.io/hostname
kubectl apply -f pod-required-anti-affinity-demo.yaml
kubectl get pods -o wide 显示两个 pod 不在一个 node 节点上,这 就是 pod 节点反亲和性
pod-first running god64
pod-second running god62
kubectl delete -f pod-required-anti-affinity-demo.yaml
换一个 topologykey
kubectl label nodes god62 zone=foo
kubectl label nodes god64 zone=foo
cat pod-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app: myapp
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: app, operator: In, values: ["myapp"]}
topologyKey: zone
kubectl apply -f pod-required-anti-affinity-demo.yaml
kubectl get pods -o wide 显示如下:
pod-first running god64
pod-second pending
第二个节点现是 pending,因为两个节点是同一个位置,现在没有不是同一个位置的了,而且我 们要求反亲和性,所以就会处于 pending 状态,如果在反亲和性这个位置把 required 改成 preferred,那么也会运行。
podaffinity:pod 节点亲和性,pod 倾向于哪个 pod
nodeaffinity:node 节点亲和性,pod 倾向于哪个 node
tolerationSeconds参数含义:
假如说你原来node1节点没有污点,上面会有很多pod在运行,现在你把node1节点打个污点,排斥等级是NoExecute,这样你node1上的pod就会被驱逐走,那多长时间被撵走,取决于tolerationSeconds,这个参数知识在定义排斥等级是NoExecute的时候才会用到