自动调度(Deployment)

Deployment 功能包括自动部署容器应用的多份副本,以及持续监控副本的数量,在集群内始终维持用户指定的副本数量。多个Pod由系统全自动完成调度。运行节点的选择由 Scheduler 经过调度算法得出,用户无法干预调度过程和结果。

定向调度(NodeSelector)

查看标签
kubectl get nodes —show-labels

为 k8s-node-1 节点打 zone=north 标签
kubectl label node k8s-node-1 zone=north

应用资源(pod只调度到有 zone: north 标签的节点)

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. labels:
  5. app: busybox-pod
  6. name: test-busybox
  7. spec:
  8. containers:
  9. - command:
  10. - sleep
  11. - "3600"
  12. image: busybox
  13. imagePullPolicy: Always
  14. name: test-busybox
  15. nodeSelector:
  16. zone: north

亲和性&反亲和性

亲和性调度可分成软策略和硬策略两种方式:

  • 软策略:若没有满足调度要求的节点,Pod 会忽略调度规则,继续完成调度过程。简单说是,满足条件最好,没有的话也无所谓
  • 硬策略:若没有满足条件的节点,会不断重试直到满足条件为止。简单说是,必须满足要求,不然就不干了

对于亲和性与反亲和性都有两种规则可以设置:
preferredDuringSchedulingIgnoredDuringExecution 软策略
requiredDuringSchedulingIgnoredDuringExecution 硬策略

nodeAffinity(node亲和性)

节点亲和性(nodeAffinity)主要是用来控制 Pod 要部署在哪些节点上,以及不能部署在哪些节点上。

示例:(node-affinity-demo.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-affinity
  labels:
    app: node-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: node-affinity
  template:
    metadata:
      labels:
        app: node-affinity
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
            nodeSelectorTerms:
            - matchExpressions:
              - key: kubernetes.io/hostname
                operator: NotIn
                values:
                - k8s-node3
          preferredDuringSchedulingIgnoredDuringExecution:  # 软策略
          - weight: 1
            preference:
              matchExpressions:
              - key: com
                operator: In
                values:
                - crab

配置解读:
不能运行在 k8s-node3 节点,优先调度到满足标签 com=crab 的节点。

注意:
若 nodeSelectorTerms 下面有多个选项时,满足任何一个条件就可以了;若 matchExpressions 有多个选项,则必须同时满足这些条件才能正常调度 Pod。

操作符说明:

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

podAffinity(pod 亲和性)

Pod 亲和性主要解决 Pod 可以和哪些 Pod 部署在同一个拓扑域中的问题。比如一个 Pod 在 A 节点上了,那么另一个 Pod 也要在 A 节点。

pod-affinity-demo.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-affinity
  labels:
    app: pod-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pod-affinity
  template:
    metadata:
      labels:
        app: pod-affinity
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - busybox-pod
            topologyKey: kubernetes.io/hostname

配置解读:
要求调度到拥有 app=busybox-pod 标签的 pod 所在的节点上。

# 查看有标签 app=busybox-pod 的 pod 列表
$ kubectl get pods -l app=busybox-pod -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
test-busybox   1/1     Running   0          27m   10.244.2.242   crab-node2   <none>           <none>

# 应用
$ kubectl apply -f pod-affinity-demo.yaml 

# 查看
$ kubectl get pods -o wide -l app=pod-affinity
NAME                            READY   STATUS    RESTARTS   AGE   IP             NODE         NOMINATED NODE   READINESS GATES
pod-affinity-587f9b5b58-5nxmf   1/1     Running   0          26s   10.244.2.249   crab-node2   <none>           <none>
pod-affinity-587f9b5b58-m2j7s   1/1     Running   0          26s   10.244.2.248   crab-node2   <none>           <none>
pod-affinity-587f9b5b58-vrd7b   1/1     Running   0          26s   10.244.2.250   crab-node2   <none>           <none>

podAntiAffinity(pod 反亲和性)

Pod 反亲和性主要解决 Pod 不可以和哪些 Pod 部署在同一个拓扑域中的问题。比如一个 Pod 在 A 节点上了,那么另一个 Pod 一定不在 A 节点上。

pod-antiaffinity-demo.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-antiaffinity
  labels:
    app: pod-antiaffinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: pod-antiaffinity
  template:
    metadata:
      labels:
        app: pod-antiaffinity
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - busybox-pod
            topologyKey: kubernetes.io/hostname

配置解读:
当拥有标签 app=busybox-pod 的 Pod 运行在 A 节点上时,那么 Pod 不会调度到 A 节点上。

污点&容忍

对于 nodeAffinity 无论是硬策略还是软策略方式,都是调度 Pod 到预期节点。而污点(Taints)与之相反,当 A 节点标记为 Taints ,则此节点不会被调度 Pod ,除非 Pod 被标识为可以容忍污点节点。

kubeadm 搭建的集群默认 master 节点有污点标记,所以用户创建 Pod 时不会调度到 master 节点。

$ kubectl describe node crab-master
Name:               crab-master
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=crab-master
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/master=
......
Taints:             node-role.kubernetes.io/master:NoSchedule
Unschedulable:      false
......

污点影响策略:

  • NoSchedule:已调度在node上的pod保持不动,新增pod没有此污点容忍度就不能调度到有此污点的node
  • NoExecute:已调度在node上的pod都将被驱逐,新增pod没有此污点容忍度就不能调度到有此污点的node
  • PreferNoSchedule:NoSchedule 的软策略版本,表示尽量不调度到污点节点上

污点 taint 标记节点:
$ kubectl taint nodes crab-node2 test=node2:NoSchedule

取消节点的污点标记:
$ kubectl taint nodes crab-node2 test-

将 Pod 调度到 master 节点:(taint-demo.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint
  labels:
    app: taint
spec:
  replicas: 3
  selector:
    matchLabels:
      app: taint
  template:
    metadata:
      labels:
        app: taint
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: http
          containerPort: 80
      tolerations:   #  因master节点被标记为了污点,要想 Pod 能够调度到该节点去,要增加容忍的声明
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

Pod 的 tolerations 内容中 key 和 effect 的值要与 Taint 设置保持一致,且满足以下条件之一:

  • operator的值是Exists(无须指定value)
  • operator的值是Equal且value相等

若不指定 operator,默认值为 Equal 。

两个特殊值:

  • 空的 key 再配合 Exists 能匹配所有的 key 与 value,即能容忍所有节点的所有 Taints
  • 空的 effect 匹配所有的 effect