K8S集群调度

目录

[Pod 是 Kubernetes 的基础单元](#Pod 是 Kubernetes 的基础单元)

nodeName

noeSelector

[修改一个 label 的值](#修改一个 label 的值)

[删除一个 label](#删除一个 label)

[指定标签查询 node 节点](#指定标签查询 node 节点)

亲和性

节点亲和性

[Pod 亲和性](#Pod 亲和性)

键值运算关系

硬策略(示例)

软策略(示例)

硬策略和软策略一起使用(示例)

pod亲和性调度

[Pod 反亲和性调度](#Pod 反亲和性调度)


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

bash 复制代码
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
bash 复制代码
kubectl apply -f myapp.yaml
bash 复制代码
kubectl describe pod myapp-99655c7fd-bckjv

noeSelector

pod.spec.nodeSelector:通过 kubernetes 的 label-selector 机制选择节点,由调度器调度策略匹配 label,然后调度 Pod 到目标节点,该匹配规则属于强制约束

#给对应的 node 设置标签分别为 kgc=a 和 kgc=b

bash 复制代码
kubectl labels node node01 kgc=a
kubectl labels node node02 kgc=b

#查看标签

bash 复制代码
kubectl get nodes --show-labels

示例:

vim myapp1.yaml

bash 复制代码
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
bash 复制代码
kubectl apply -f myapp1.yaml 
bash 复制代码
 kubectl describe pod myapp1-7c5b7d7488-875gb

通过事件可以发现要先经过 scheduler 调度分配

修改一个 label 的值

bash 复制代码
kubectl label nodes node02 kgc=a --overwrite

删除一个 label

bash 复制代码
kubectl label nodes node02 kgc-

指定标签查询 node 节点

bash 复制代码
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

bash 复制代码
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
bash 复制代码
kubectl apply -f pod1.yaml

kubectl get pods -o wide

可以看到NotIn node02,而结果也是在node01上

这边有多余pod,删除它们看得更清楚

bash 复制代码
kubectl delete pod --all

软策略(示例)

bash 复制代码
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
bash 复制代码
kubectl apply -f pod2.yaml

kubectl get pods -o wide

可以看得到软策略是In node03,但是没有node03,所以会从node01和node02中进行选择

如果将node03改成node01,那么就会选择node01

硬策略和软策略一起使用(示例)

bash 复制代码
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

bash 复制代码
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资源

bash 复制代码
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
bash 复制代码
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一样时候

bash 复制代码
kubectl label node node01 kgc=b --overwrite

此时可以看到node01和node02上都可以创建pod,因为node01和node02标签 kgc=b是一样的,属于同一个域中

Pod 反亲和性调度

示例:

bash 复制代码
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
bash 复制代码
kubectl apply -f pod5.yaml

kubectl get pods --show-labels -o wide

因为是反亲和的软策略,所以In myapp01就是优先选择不和myapp01在一个域的node节点,也就是不能在myapp01所在的node02节点,所以是node01

示例2:

bash 复制代码
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阻塞状态。

相关推荐
让生命变得有价值2 小时前
k8s 启用 ValidatingAdmissionPolicy 特性
java·容器·kubernetes·kubelet
Allocator2 小时前
docker 容器访问宿主机器服务的最简单方法
运维·docker·容器
AlenTech3 小时前
如何设置docker的定时关闭和启动
docker·容器·eureka
我从不骗人4 小时前
Docker使用相关记录
运维·docker·容器
valkyrja1106 小时前
小白docker入门简介
docker·容器·小白·初学
君败红颜13 小时前
Docker 常用命令详解(详细版)
运维·docker·容器
想学习java初学者14 小时前
Docker Compose部署Rabbitmq(Dockerfile安装延迟队列)
docker·容器·rabbitmq
梦游钓鱼17 小时前
windows安装docker
运维·docker·容器
roman_日积跬步-终至千里17 小时前
【Docker】自定义网络:实现容器之间通过域名相互通讯
网络·docker·容器
AlenTech17 小时前
如何设置定时关闭或启动整个docker而不是某个容器
运维·docker·容器