目录

Pod 是 Kubernetes 的基础单元

nodeName

noeSelector

修改一个 label 的值

删除一个 label

指定标签查询 node 节点

亲和性

节点亲和性

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

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状态

但是如果设置了容忍的话:

就会允许创建

Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐