【K8S专栏】Kubernetes调度管理(下)

简介: 【K8S专栏】Kubernetes调度管理

污点调度

在Kubernetes中,有些节点自带污点 ,比如Master节点,这类节点,如果Pod没有配置容忍污点,则这些Pod不会调度到这类节点上。

在实际中,污点调度也是非常有用的,有些场景某些节点只允许某些项目组的Pod允许,比如大数据项目是一些高IO项目,不想和其他普通项目混合在一起,而其他项目如果使用标签选择器配置部署又比较麻烦,这时候就可以使用污点选择器。

我们可以通过kubectl explain node.spec.taints来查看污点相关的配置信息:

$ kubectl explain node.spec.taints
KIND:     Node
VERSION:  v1
RESOURCE: taints <[]Object>
DESCRIPTION:
     If specified, the node's taints.
     The node this Taint is attached to has the "effect" on any pod that does
     not tolerate the Taint.
FIELDS:
   effect       <string> -required-
     Required. The effect of the taint on pods that do not tolerate the taint.
     Valid effects are NoSchedule, PreferNoSchedule and NoExecute.
     Possible enum values:
     - `"NoExecute"` Evict any already-running pods that do not tolerate the
     taint. Currently enforced by NodeController.
     - `"NoSchedule"` Do not allow new pods to schedule onto the node unless
     they tolerate the taint, but allow all pods submitted to Kubelet without
     going through the scheduler to start, and allow all already-running pods to
     continue running. Enforced by the scheduler.
     - `"PreferNoSchedule"` Like TaintEffectNoSchedule, but the scheduler tries
     not to schedule new pods onto the node, rather than prohibiting new pods
     from scheduling onto the node entirely. Enforced by the scheduler.
   key  <string> -required-
     Required. The taint key to be applied to a node.
   timeAdded    <string>
     TimeAdded represents the time at which the taint was added. It is only
     written for NoExecute taints.
   value        <string>
     The taint value corresponding to the taint key.

其中effect定义对Pod的排斥效果:

  • NoSchdule:仅影响调度过程,对现存在的Pod不产生影响;
  • NoExecute:不仅影响调度,而且还影响现存Pod,不容忍的Pod对象将被驱逐;
  • PreferNoSchedule:软排斥,不是完全禁止Pod调度;

如果要给节点添加污点,则如下:

$ kubectl taint nodes kk-node01 node-type=dev:NoSchedule

给节点 kk-node01增加一个污点,它的键名是 node-type,键值是 dev,效果是 NoSchedule。这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到 kk-node01这个节点。

如果要删除污点,则使用如下命令:

$ kubectl taint nodes kk-node01 node-type=dev:NoSchedule-

如果要配置容忍污点,则如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        imagePullPolicy: IfNotPresent 
        ports:
        - containerPort: 80
      tolerations:
      - key: "node-type"
        operator: Equal
        value: dev
        effect: NoSchedule
        tolerationSeconds: 20

operator支持EqualExists,默认是Equal

如果是Equal,表示污点的键值需要一致,如果使用Exists,则表示只要存在该键的污点,比如:

tolerations:
- key: "key1"
  operator: "Exists"
  effect: "NoSchedule"

该配置表示只要匹配容忍度,并且key1的健存在即可调度。

如果一个容忍度的 key 为空且 operator 为 Exists, 表示这个容忍度与任意的 key、value 和 effect 都匹配,即这个容忍度能容忍任何污点。如果 effect 为空,则可以与所有键名 key1 的效果相匹配。

你可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置。Kubernetes 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历, 过滤掉那些 Pod 中存在与之相匹配的容忍度的污点。余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点,特别是以下情况:

  • 如果未被忽略的污点中存在至少一个 effect 值为 NoSchedule 的污点, 则 Kubernetes 不会将 Pod 调度到该节点。
  • 如果未被忽略的污点中不存在 effect 值为 NoSchedule 的污点, 但是存在 effect 值为 PreferNoSchedule 的污点, 则 Kubernetes 会 尝试 不将 Pod 调度到该节点。
  • 如果未被忽略的污点中存在至少一个 effect 值为 NoExecute 的污点, 则 Kubernetes 不会将 Pod 调度到该节点(如果 Pod 还未在节点上运行), 或者将 Pod 从该节点驱逐(如果 Pod 已经在节点上运行)。

例如,假设你给一个节点添加了如下污点

$ kubectl taint nodes node1 key1=value1:NoSchedule
$ kubectl taint nodes node1 key1=value1:NoExecute
$ kubectl taint nodes node1 key2=value2:NoSchedule

假定有一个 Pod,它有两个容忍度:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"

在这种情况下,上述 Pod 不会被调度到上述节点,因为其没有容忍度和第三个污点相匹配。但是如果在给节点添加上述污点之前,该 Pod 已经在上述节点运行, 那么它还可以继续运行在该节点上,因为第三个污点是三个污点中唯一不能被这个 Pod 容忍的。

通常情况下,如果给一个节点添加了一个 effect 值为 NoExecute 的污点, 则任何不能忍受这个污点的 Pod 都会马上被驱逐,任何可以忍受这个污点的 Pod 都不会被驱逐。但是,如果 Pod 存在一个 effect 值为 NoExecute 的容忍度指定了可选属性 tolerationSeconds 的值,则表示在给节点添加了上述污点之后, Pod 还能继续在节点上运行的时间。例如:

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
  tolerationSeconds: 3600

这表示如果这个 Pod 正在运行,同时一个匹配的污点被添加到其所在的节点, 那么 Pod 还将继续在节点上运行 3600 秒,然后被驱逐。如果在此之前上述污点被删除了,则 Pod 不会被驱逐。

重新调度

在Kubernetes中,kube-scheduler负责将Pod调度到合适的Node上,但是Kubernetes是一个非常动态的,高度弹性的环境,有时候会造成某一个或多个节点pod数分配不均,比如:

  • 一些节点利用率低下或过度使用
  • 添加删除标签或添加删除污点,pod或Node亲和性改变等造成原调度不再满足
  • 一些节点故障,其上运行的Pod调度到其他节点
  • 新节点加入集群

由于以上种种原因,可能导致多个Pod运行到不太理想的节点,而整个K8S集群也会处于一段时间不均衡的状态,这时候就需要重新平衡集群。Descheduler就是这样一个项目。

Descheduler可以根据一些规则配置来重新平衡集群状态,目前支持的策略有:

  • RemoveDuplicates
  • LowNodeUtilization
  • RemovePodsViolatingInterPodAntiAffinity
  • RemovePodsViolatingNodeAffinity
  • RemovePodsViolatingNodeTaints
  • RemovePodsViolatingTopologySpreadConstraint
  • RemovePodsHavingTooManyRestarts
  • PodLifeTime

这些策略可以启用,也可以关闭,默认情况下,所有策略都是启动的。

另外,还有一些通用配置,如下:

  • nodeSelector:限制要处理的节点
  • evictLocalStoragePods: 驱除使用LocalStorage的Pods
  • ignorePvcPods: 是否忽略配置PVC的Pods,默认是False
  • maxNoOfPodsToEvictPerNode:节点允许的最大驱逐Pods数

由于我集群版本是1.24.2,所以安装descheduler v0.24版本。

(1)下载对应的Helm chart,我这里选择的是0.24版本

$ wget https://github.com/kubernetes-sigs/descheduler/releases/download/descheduler-helm-chart-0.24.0/descheduler-0.24.0.tgz

(2)如果可以科学上网,直接使用以下命令部署即可。

$ helm install descheduler .

如果不能科学上网,就替换镜像,修改value.yaml里的镜像信息,如下:

image:
  repository: registry.cn-hangzhou.aliyuncs.com/coolops/descheduler 
  # Overrides the image tag whose default is the chart version
  tag: "v0.24.0"
  pullPolicy: IfNotPresent

然后再执行安装命令。

安装完成过后,会配置默认的调度策略,如下:

apiVersion: v1
data:
  policy.yaml: |
    apiVersion: "descheduler/v1alpha1"
    kind: "DeschedulerPolicy"
    strategies:
      LowNodeUtilization:
        enabled: true
        params:
          nodeResourceUtilizationThresholds:
            targetThresholds:
              cpu: 50
              memory: 50
              pods: 50
            thresholds:
              cpu: 20
              memory: 20
              pods: 20
      RemoveDuplicates:
        enabled: true
      RemovePodsViolatingInterPodAntiAffinity:
        enabled: true
      RemovePodsViolatingNodeAffinity:
        enabled: true
        params:
          nodeAffinityType:
          - requiredDuringSchedulingIgnoredDuringExecution
      RemovePodsViolatingNodeTaints:
        enabled: true
kind: ConfigMap
metadata:
  annotations:
    meta.helm.sh/release-name: descheduler
    meta.helm.sh/release-namespace: default
  creationTimestamp: "2022-08-02T03:06:57Z"
  labels:
    app.kubernetes.io/instance: descheduler
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: descheduler
    app.kubernetes.io/version: 0.24.0
    helm.sh/chart: descheduler-0.24.0
  name: descheduler
  namespace: default
  resourceVersion: "894636"
  uid: 4ab2e628-9404-4e52-bd88-615f5e096d90

其中配置了:

  • LowNodeUtilization:设置了cpu\内存\pod水位,thresholds表示未充分利用,targetThresholds表示过度使用
  • RemoveDuplicates:开启同节点只有一个Pod运行
  • RemovePodsViolatingInterPodAntiAffinity:删除违反亲和性的Pod
  • RemovePodsViolatingNodeAffinity:删除不满足Node亲和性的Pod
  • RemovePodsViolatingNodeTaints:删除不被Node污点容忍的Pod

并且会创建一个CronJob,周期性的执行调度均衡。

apiVersion: batch/v1
kind: CronJob
metadata:
  annotations:
    meta.helm.sh/release-name: descheduler
    meta.helm.sh/release-namespace: default
  creationTimestamp: "2022-08-02T03:06:57Z"
  generation: 1
  labels:
    app.kubernetes.io/instance: descheduler
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: descheduler
    app.kubernetes.io/version: 0.24.0
    helm.sh/chart: descheduler-0.24.0
  name: descheduler
  namespace: default
  resourceVersion: "898221"
  uid: e209e498-71cb-413f-97a9-372aea5442bc
spec:
  concurrencyPolicy: Forbid
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
      creationTimestamp: null
    spec:
      template:
        metadata:
          annotations:
            checksum/config: 5efec14c3638fa4028e25f3fa067758f13dcae442fe711439c7d0b2e9913d41e
          creationTimestamp: null
          labels:
            app.kubernetes.io/instance: descheduler
            app.kubernetes.io/name: descheduler
          name: descheduler
        spec:
          containers:
          - args:
            - --policy-config-file
            - /policy-dir/policy.yaml
            - --v
            - "3"
            command:
            - /bin/descheduler
            image: registry.cn-hangzhou.aliyuncs.com/coolops/descheduler:v0.24.0
            imagePullPolicy: IfNotPresent
            livenessProbe:
              failureThreshold: 3
              httpGet:
                path: /healthz
                port: 10258
                scheme: HTTPS
              initialDelaySeconds: 3
              periodSeconds: 10
              successThreshold: 1
              timeoutSeconds: 1
            name: descheduler
            resources:
              requests:
                cpu: 500m
                memory: 256Mi
            securityContext:
              allowPrivilegeEscalation: false
              capabilities:
                drop:
                - ALL
              privileged: false
              readOnlyRootFilesystem: true
              runAsNonRoot: true
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
            volumeMounts:
            - mountPath: /policy-dir
              name: policy-volume
          dnsPolicy: ClusterFirst
          priorityClassName: system-cluster-critical
          restartPolicy: Never
          schedulerName: default-scheduler
          securityContext: {}
          serviceAccount: descheduler
          serviceAccountName: descheduler
          terminationGracePeriodSeconds: 30
          volumes:
          - configMap:
              defaultMode: 420
              name: descheduler
            name: policy-volume
  schedule: '*/2 * * * *'
  successfulJobsHistoryLimit: 3
  suspend: false
status:
  lastScheduleTime: "2022-08-02T03:28:00Z"
  lastSuccessfulTime: "2022-08-02T03:28:03Z"

该Job会每2分钟执行一次均衡调度。

总结

Kubernetes的调度策略是非常复杂的,里面有许多复杂的算法,这里介绍的只是一些常用的调度策略,足够满足日常使用。如果想更深入的研究可以多看看官方文档以及源码。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
15天前
|
监控 Kubernetes Cloud Native
基于阿里云容器服务Kubernetes版(ACK)的微服务架构设计与实践
本文介绍了如何基于阿里云容器服务Kubernetes版(ACK)设计和实现微服务架构。首先概述了微服务架构的优势与挑战,如模块化、可扩展性及技术多样性。接着详细描述了ACK的核心功能,包括集群管理、应用管理、网络与安全、监控与日志等。在设计基于ACK的微服务架构时,需考虑服务拆分、通信、发现与负载均衡、配置管理、监控与日志以及CI/CD等方面。通过一个电商应用案例,展示了用户服务、商品服务、订单服务和支付服务的具体部署步骤。最后总结了ACK为微服务架构提供的强大支持,帮助应对各种挑战,构建高效可靠的云原生应用。
|
2月前
|
存储 运维 Kubernetes
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
飞轮科技推出了 Doris 的 Kubernetes Operator 开源项目(简称:Doris Operator),并捐赠给 Apache 基金会。该工具集成了原生 Kubernetes 资源的复杂管理能力,并融合了 Doris 组件间的分布式协同、用户集群形态的按需定制等经验,为用户提供了一个更简洁、高效、易用的容器化部署方案。
正式开源,Doris Operator 支持高效 Kubernetes 容器化部署方案
|
3月前
|
存储 Kubernetes Docker
Kubernetes(k8s)和Docker Compose本质区别
理解它们的区别和各自的优势,有助于选择合适的工具来满足特定的项目需求。
312 19
|
3月前
|
Kubernetes 应用服务中间件 nginx
二进制安装Kubernetes(k8s)v1.32.0
本指南提供了一个详细的步骤,用于在Linux系统上通过二进制文件安装Kubernetes(k8s)v1.32.0,支持IPv4+IPv6双栈。具体步骤包括环境准备、系统配置、组件安装和配置等。
1081 11
|
3月前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
|
11天前
|
Prometheus Kubernetes 监控
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
|
15天前
|
运维 分布式计算 Kubernetes
ACK One多集群Service帮助大批量应用跨集群无缝迁移
ACK One多集群Service可以帮助您,在无需关注服务间的依赖,和最小化迁移风险的前提下,完成跨集群无缝迁移大批量应用。
|
2月前
|
缓存 容灾 网络协议
ACK One多集群网关:实现高效容灾方案
ACK One多集群网关可以帮助您快速构建同城跨AZ多活容灾系统、混合云同城跨AZ多活容灾系统,以及异地容灾系统。
|
3月前
|
Kubernetes Ubuntu 网络安全
ubuntu使用kubeadm搭建k8s集群
通过以上步骤,您可以在 Ubuntu 系统上使用 kubeadm 成功搭建一个 Kubernetes 集群。本文详细介绍了从环境准备、安装 Kubernetes 组件、初始化集群到管理和使用集群的完整过程,希望对您有所帮助。在实际应用中,您可以根据具体需求调整配置,进一步优化集群性能和安全性。
183 12
|
3月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。

热门文章

最新文章