许吉友 - 运维

Kubernetes 调度与资源管理

公开课地址:https://edu.aliyun.com/lesson_1651_13090?spm=5176.10731542.0.0.33d720beJkvduZ#_13090

Kubernetes 调度过程

image-20201110201509555

调度过程 = 把 Pod 放到合适的 Node 上。

那怎么定义合适?

Kubernetes 基础调度能力

资源调度

资源配置方法

Pod 的资源类型:

CPU 和 Memory 很常见,关于 扩展资源见: 为节点发布扩展资源-为容器分派扩展资源.md

关于 ephemeral-storage 参见:https://kubernetes.io/zh/docs/concepts/configuration/manage-resources-containers/#local-ephemeral-storage

如何满足资源需求

关于 QoS 参考: 配置Pod的服务质量.md

QoS Class 是隐性的,不能显示的指定,而是通过 request 和 limit 的组合来自动映射 QoS Class 的。

QoS

个人理解:

在宿主机资源耗尽时,QoS 为 BestEffort 会被最先驱逐,Burstable次之,Guaranteed 最后驱逐。

不同 QoS 的表现

资源 Quota

当一个k8s集群部署多个业务时,需要限制业务使用资源的总量,防止出现整个资源都会被某个业务应用都使用掉,导致另外一个业务没有资源使用。

限制每个 Namespace 的资源可以使用 ResourceQuota:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: default-hzwjv
  namespace: canghai
spec:
  hard:
    requests.cpu: "8"
    requests.memory: 16000Mi
    pods: "10"
  scopeSelector: #可以不填
    matchExpressions:
    - operator: Exists
      scopeName: NotBestEffort

限制 canghai 命名空间下非BestEffort的Qos只能使用8个CPU核心、16000M内存、10个Pod

Scope 包括:

当 Quota 使用超过后,再提交就会返回一个 forbidden 的 403 错误。

关系调度

官方文档:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/assign-pod-node/

Pod 亲和调度

Pod 反亲和示例:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-aff
spec:
 selector:
  matchLabels:
   app: web_server-aff
 replicas: 10
 template:
  metadata:
   labels:
    app: web_server-aff
  spec:
   affinity:
     podAntiAffinity:
       preferredDuringSchedulingIgnoredDuringExecution:
       - weight: 1
         podAffinityTerm:
           labelSelector:
             matchExpressions:
             - key: app
               operator: In
               values:
               - web_server-aff
           topologyKey: kubernetes.io/hostname
   containers:
   - name: nginx
     image: nginx:1.7.9
     ports:
     - containerPort: 80

Node 亲和调度

NodeSelector 示例:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

Node 亲和示例:

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/e2e-az-name
            operator: In
            values:
            - e2e-az1
            - e2e-az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: k8s.gcr.io/pause:2.0

Node 污点/容忍

查看 Node 的污点:

$ kubectl describe node fueltank-1 | grep "Taints"

去掉 Node 的污点:

$ kubectl taint node fueltank-1 node-role.kubernetes.io/master:NoSchedule-

示例:

Node 上带了 k1=v1 且效果是 NoSchedule 的 Taints:

apiVersion: v1
kind: Node
metadata:
  name: demo-node
spec:
  taints:
    - key: "k1"
      value: "v1"
      effect: "NoSchedule"

Pod 上必须带有 k1=v1 且效果是 NoSchedule 的 Tolerations

apiVersion: v1
kind: Pod
metadata:
  name: demo-node
sepc:
  containers:
    - image: nginx:latest
      name: demo
  tolerations:
    - key: "k1"
      operator: "Equal"
      value: "v1"
      effect: "NoSchedule"

Kubernetes 高级调度能力

这两个特性在 v1.14 之后已经是生产环境可用了,并且这俩功能默认是开启的。

如果资源够的话,通过基础调度能力即可,如果资源不够,就需要高级调度了。

如何做到集群资源合理利用?

优先级调度配置

创建一个高优先级的 PriorityClass,得分为 10000:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high
value: 10000
globalDefault: false

创建一个低优先级的 PriorityClass,得分为100:

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low
value: 100
globalDefault: false

为 Pod 配置 priorityClassName:

sepc:
  priorityClassName: high #或 low

优先级调度过程

只开了优先级,没有开抢占:

image-20201111135431166

开了优先级,也开了抢占:

image-20201111135753033

抢占选择 Node 过程:

image-20201111140216845