K8S集群调度
(12)kubelet 是在 Node 上面运行的进程,它也通过 List-Watch 的方式监听(Watch,通过https的6443端口)APIServer 发送的 Pod 更新的事件。因为是硬策略,所以要满足和myapp01不在同一个域中,此时myapp在node02上,而topologyKey: kgc,node01和node02标签都是kgc=a,所以node01和node02在同一个域
目录
Pod 是 Kubernetes 的基础单元
(1)这里有三个 List-Watch,分别是 Controller Manager(运行在 Master),Scheduler(运行在 Master),kubelet(运行在 Node)。 他们在进程已启动就会监听(Watch)APIServer 发出来的事件。
(2)用户通过 kubectl 或其他 API 客户端提交请求给 APIServer 来建立一个 Pod 对象副本。
(3)APIServer 尝试着将 Pod 对象的相关元信息存入 etcd 中,待写入操作执行完成,APIServer 即会返回确认信息至客户端。
(4)当 etcd 接受创建 Pod 信息以后,会发送一个 Create 事件给 APIServer。
(5)由于 Controller Manager 一直在监听(Watch,通过https的6443端口)APIServer 中的事件。此时 APIServer 接受到了 Create 事件,又会发送给 Controller Manager。
(6)Controller Manager 在接到 Create 事件以后,调用其中的 Replication Controller 来保证 Node 上面需要创建的副本数量。一旦副本数量少于 RC 中定义的数量,RC 会自动创建副本。总之它是保证副本数量的 Controller(PS:扩容缩容的担当)。
(7)在 Controller Manager 创建 Pod 副本以后,APIServer 会在 etcd 中记录这个 Pod 的详细信息。例如 Pod 的副本数,Container 的内容是什么。
(8)同样的 etcd 会将创建 Pod 的信息通过事件发送给 APIServer。
(9)由于 Scheduler 在监听(Watch)APIServer,并且它在系统中起到了“承上启下”的作用,“承上”是指它负责接收创建的 Pod 事件,为其安排 Node;“启下”是指安置工作完成后,Node 上的 kubelet 进程会接管后继工作,负责 Pod 生命周期中的“下半生”。 换句话说,Scheduler 的作用是将待调度的 Pod 按照调度算法和策略绑定到集群中 Node 上。
(10)Scheduler 调度完毕以后会更新 Pod 的信息,此时的信息更加丰富了。除了知道 Pod 的副本数量,副本内容。还知道部署到哪个 Node 上面了。并将上面的 Pod 信息更新至 API Server,由 APIServer 更新至 etcd 中,保存起来。
(11)etcd 将更新成功的事件发送给 APIServer,APIServer 也开始反映此 Pod 对象的调度结果。
(12)kubelet 是在 Node 上面运行的进程,它也通过 List-Watch 的方式监听(Watch,通过https的6443端口)APIServer 发送的 Pod 更新的事件。kubelet 会尝试在当前节点上调用 Docker 启动容器,并将 Pod 以及容器的结果状态回送至 APIServer。
(13)APIServer 将 Pod 状态信息存入 etcd 中。在 etcd 确认写入操作成功完成后,APIServer将确认信息发送至相关的 kubelet,事件将通过它被接受。
nodeName
pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配
vim myapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
nodeName: node01
containers:
- name: myapp
image: soscscs/myapp:v1
ports:
- containerPort: 80
kubectl apply -f myapp.yaml
kubectl describe pod myapp-99655c7fd-bckjv
noeSelector
pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,然后调度 Pod 到目标节点,该匹配规则属于强制约束
#给对应的 node 设置标签分别为 kgc=a 和 kgc=b
kubectl labels node node01 kgc=a
kubectl labels node node02 kgc=b
#查看标签
kubectl get nodes --show-labels
示例:
vim myapp1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp1
spec:
replicas: 3
selector:
matchLabels:
app: myapp1
template:
metadata:
labels:
app: myapp1
spec:
nodeSelector:
kgc: a
containers:
- name: myapp1
image: soscscs/myapp:v1
ports:
- containerPort: 80
kubectl apply -f myapp1.yaml
kubectl describe pod myapp1-7c5b7d7488-875gb
通过事件可以发现要先经过 scheduler 调度分配
修改一个 label 的值
kubectl label nodes node02 kgc=a --overwrite
删除一个 label
kubectl label nodes node02 kgc-
指定标签查询 node 节点
kubectl get node -l kgc=a
亲和性
节点亲和性
pod.spec.nodeAffinity
●preferredDuringSchedulingIgnoredDuringExecution:软策略
●requiredDuringSchedulingIgnoredDuringExecution:硬策略
Pod 亲和性
pod.spec.affinity.podAffinity/podAntiAffinity
●preferredDuringSchedulingIgnoredDuringExecution:软策略
●requiredDuringSchedulingIgnoredDuringExecution:硬策略
键值运算关系
●In:label 的值在某个列表中 pending
●NotIn:label 的值不在某个列表中
●Gt:label 的值大于某个值
●Lt:label 的值小于某个值
●Exists:某个 label 存在
●DoesNotExist:某个 label 不存在
硬策略(示例)
硬策略是只有满足条件才会创建pod
软策略是如果满足条件,会优先去满足条件,如果不满足,也会继续在剩下的节点中选择一个创建pod
mkdir /opt/affinity
cd /opt/affinity
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values::
- node02
kubectl apply -f pod1.yaml
kubectl get pods -o wide
可以看到NotIn node02,而结果也是在node01上
这边有多余pod,删除它们看得更清楚
kubectl delete pod --all
软策略(示例)
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node03
kubectl apply -f pod2.yaml
kubectl get pods -o wide
可以看得到软策略是In node03,但是没有node03,所以会从node01和node02中进行选择
如果将node03改成node01,那么就会选择node01
硬策略和软策略一起使用(示例)
apiVersion: v1
kind: Pod
metadata:
name: affinity
labels:
app: node-affinity-pod
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: NotIn
values:
- node02
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: kgc
operator: In
values:
- a
执行结果:
如果硬策略和软策略一起使用,会先满足硬策略,再满足软策略
所以会先满足NotIn node02,再去 In kgc=a,也就是node01
pod亲和性调度
先创建一个标签为app=myapp01 的pod
vim pod3.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp01
labels:
app: myapp01
spec:
containers:
- name: with-node-affinity
image: soscscs/myapp:v1
kubectl apply -f pod3.yaml
kubectl get pods --show-labels -o wide
使用pod亲和性创建多个pod资源
vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp02
labels:
app: myapp02
spec:
containers:
- name: myapp02
image: soscscs/myapp:v1
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01
topologyKey: kgc
kubectl apply -f pod4.yaml
kubectl get pods --show-labels -o wide
此时node01 kgc=a node02 kgc=b a和b不一样,所以node01和node02不在一个域内,所以只会在 有myapp01在的node02中创建pod
此时将node01的标签改成 kgc=b 也就是和node02一样时候
kubectl label node node01 kgc=b --overwrite
此时可以看到node01和node02上都可以创建pod,因为node01和node02标签 kgc=b是一样的,属于同一个域中
Pod 反亲和性调度
示例:
vim pod5.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp10
labels:
app: myapp10
spec:
containers:
- name: myapp10
image: soscscs/myapp:v1
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01
topologyKey: kubernetes.io/hostname
kubectl apply -f pod5.yaml
kubectl get pods --show-labels -o wide
因为是反亲和的软策略,所以In myapp01就是优先选择不和myapp01在一个域的node节点,也就是不能在myapp01所在的node02节点,所以是node01
示例2:
vim pod6.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp20
labels:
app: myapp20
spec:
containers:
- name: myapp20
image: soscscs/myapp:v1
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01
topologyKey: kgc
此时node01和node02的标签都是kgc=a
因为是硬策略,所以要满足和myapp01不在同一个域中,此时myapp在node02上,而topologyKey: kgc,node01和node02标签都是kgc=a,所以node01和node02在同一个域里,没有满足条件的node节点,所以显示pending阻塞状态。
污点和容忍
污点是指在节点上设置一个标记,表示该节点有一些特殊的限制条件,例如需要特定的硬件设备或软件配置。通过设置污点,可以阻止一些不符合要求的Pod被调度到该节点上。
容忍是指Pod对污点的容忍程度。在Pod的描述中,可以设置容忍规则,使Pod能够被调度到拥有特定污点的节点上。这样,即使节点上存在污点,仍然可以容忍并运行Pod。
设置污点
kubectl taint node node01 key1=value1:NoSchedule
去除污点
kubectl taint node node01 key1:NoSchedule-
查看污点
kubectl describe node node-name #找到taints字段
在node01 和 node02 上都设置的污点后,容器就无法创建,显示pending状态
但是如果设置了容忍的话:
就会允许创建
更多推荐
所有评论(0)