OpenKruise v1.3:新增自定义 Pod Probe 探针能力与大规模集群性能显著提升

本文涉及的产品
应用实时监控服务-可观测链路OpenTelemetry版,每月50GB免费额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 在版本 v1.3 中,OpenKruise 提供了新的 CRD 资源 PodProbeMarker,改善了大规模集群的一些性能问题,Advanced DaemonSet 支持镜像预热,以及 CloneSet、WorkloadSpread、Advanced CronJob、SidecarSet 一些新的特性。

作者:赵明山(立衡)


云原生应用自动化管理套件、CNCF Sandbox 项目——OpenKruise,近期发布了 v1.3 版本。


OpenKruise 是针对 Kubernetes 的增强能力套件,聚焦于云原生应用的部署、升级、运维、稳定性防护等领域。


所有的功能都通过 CRD 等标准方式扩展,可以适用于 1.16 以上版本的任意 Kubernetes 集群。单条 helm 命令即可完成 Kruise 的一键部署,无需更多配置。


版本解析


在版本 v1.3 中,OpenKruise 提供了新的 CRD 资源 PodProbeMarker,改善了大规模集群的一些性能问题,Advanced DaemonSet 支持镜像预热,以及 CloneSet、WorkloadSpread、Advanced CronJob、SidecarSet 一些新的特性。


新增 CRD 和 Controller:PodProbeMarker


Kubernetes 提供了三种默认的 Pod 生命周期管理:


  • Readiness Probe:用来判断业务容器是否已经准备好响应用户请求,如果检查失败,会将该 Pod 从 Service Endpoints 中剔除。  


  • Liveness Probe:用来判断容器的健康状态,如果检查失败,kubelet 将会重启该容器。  


  • Startup Probe:用来判断容器是否启动完成,如果定义了该 Probe,那么 Readiness Probe 与 Liveness Probe 将会在它成功之后再执行。 


所以 Kubernetes 中提供的 Probe 能力都已经限定了特定的语义以及相关的行为。除此之外,其实还是存在自定义 Probe 语义以及相关行为的需求,例如:


  • GameServer 定义 Idle Probe 用来判断该 Pod 当前是否存在游戏对局,如果没有,从成本优化的角度,可以将该 Pod 缩容掉。 


  • K8s Operator 定义 main-secondary Probe 来判断当前 Pod 的角色(main or secondary),升级的时候,可以优先升级 secondary,进而达到升级过程只有一次选主的行为,降低升级过程中服务抖动时间。 


OpenKruise 提供了自定义 Probe 的能力,并将结果返回到 Pod Status 中,用户可以根据该结果决定后续的行为。


PodProbeMarker 配置如下:


apiVersion: apps.kruise.io/v1alpha1
kind: PodProbeMarker
metadata:
  name: game-server-probe
  namespace: ns
spec:
  selector:
    matchLabels:
      app: game-server
  probes:
  - name: Idle
    containerName: game-server
    probe:
      exec: /home/game/idle.sh
      initialDelaySeconds: 10
      timeoutSeconds: 3
      periodSeconds: 10
      successThreshold: 1
      failureThreshold: 3
    markerPolicy:
    - state: Succeeded
      labels:
        gameserver-idle: 'true'
      annotations:
        controller.kubernetes.io/pod-deletion-cost: '-10'
    - state: Failed
      labels:
        gameserver-idle: 'false'
      annotations:
        controller.kubernetes.io/pod-deletion-cost: '10'
        podConditionType: game.io/idle


PodProbeMarker 结果可以通过 Pod 对象查看:


apiVersion: v1
kind: Pod
metadata:
  labels:
    app: game-server
    gameserver-idle: 'true'
  annotations:
    controller.kubernetes.io/pod-deletion-cost: '-10'
  name: game-server-58cb9f5688-7sbd8
  namespace: ns
spec:
  ...
status:
  conditions:
    # podConditionType
  - type: game.io/idle
    # Probe State 'Succeeded' indicates 'True', and 'Failed' indicates 'False'
    status: "True"
    lastProbeTime: "2022-09-09T07:13:04Z"
    lastTransitionTime: "2022-09-09T07:13:04Z"
    # If the probe fails to execute, the message is stderr
    message: ""


性能优化:大规模集群性能显著提升


  • #1026[1]  引入了延迟入队机制,大幅优化了在大规模应用集群下 kruise-manager 拉起时的 CloneSet 控制器工作队列堆积问题,在理想情况下初始化时间减少了 80% 以上。
     
  • #1027[2]  优化 PodUnavailableBudget 控制器 Event Handler 逻辑,减少无关 Pod 入队数量。
     
  • #1011[3]  通过缓存机制,优化了大规模集群下 Advanced DaemonSet 重复模拟 Pod 调度计算的 CPU、Memory 消耗。
     
  • #1015[4] , #1068[5]大幅降低了大规模集群下的运行时内存消耗。弥补了 v1.1 版本中 Disable DeepCopy 的一些疏漏点,减少 expressions 类型 label selector 的转换消耗。


SidecarSet 支持注入特定的历史版本


SidecarSet 通过 ControllerRevision 记录了关于 containers、volumes、initContainers、imagePullSecrets 和 patchPodMetadata 等字段的历史版本,并允许用户在 Pod 创建时选择特定的历史版本进行注入。


基于这一特性,用户可以规避在 SidecarSet 灰度发布时,因 Deployment 等 Workload 扩容、升级等操作带来的 SidecarSet 发布风险。如果不选择注入版本,SidecarSet 将对重建 Pod 默认全都注入最新版本 Sidecar。


SidecarSet 相关 ControllerRevision 资源被放置在了与 Kruise-Manager 相同的命名空间中,用户可以使用以下命令来查看:


kubectl get controllerrvisions -n kruise-system -l kruise.io/sidecarset-name=your-sidecarset-name


此外,用户还可以通过 SidecarSet 的 status.latestRevision 字段看到当前版本对应的 ControllerRevision 名称,以方便自行记录。


1. 通过 ControllerRevision 名称指定注入的 Sidecar 版本


apiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
metadata:
  name: sidecarset
spec:
  ...
  injectionStrategy:
    revisionName: specific-controllerRevision-name


2. 通过自定义版本标识指定注入的 Sidecar 版本


用户可以通过在发版时,同时给 SidecarSet 打上 apps.kruise.io/sidecarset-custom-version=your-version-id 来标记每一个历史版本,SidecarSet 会将这个 label 向下带入到对应的 ControllerRevision 对象,以便用户进行筛选,并且允许用户在选择注入历史版本时,使用改 your-version-id 来进行描述。


假设用户只想灰度 10% 的 Pods 到 version-2,并且对于新创建的 Pod 希望都注入更加稳定的 version-1 版本来控制灰度风险:


apiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
metadata:
  name: sidecarset
  labels:
    apps.kruise.io/sidecarset-custom-version: version-2
spec:
  ...
  updateStrategy:
    partition: 90%
  injectionStrategy:
    customVersion: version-1


SidecarSet 支持注入 Pod Annotations


SidecarSet 支持注入 Pod Annotations,配置如下:


apiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
spec:
  containers:
  ...
  patchPodMetadata:
  - annotations:
    oom-score: '{"log-agent": 1}'
    custom.example.com/sidecar-configuration: '{"command": "/home/admin/bin/start.sh", "log-level": "3"}'
  patchPolicy: MergePatchJson
  - annotations:
    apps.kruise.io/container-launch-priority: Ordered
    patchPolicy: Overwrite | Retain


patchPolicy 为注入的策略,如下:


  • Retain:默认策略,如果 Pod 中存在 annotation[key]=value ,则保留 Pod 原有的 value。只有当 Pod 中不存在 annotation[key] 时,才注入 annotations[key]=value。


  • Overwrite:与 Retain 对应,当 Pod 中存在 annotation[key]=value,将被强制覆盖为 value2。


  • MergePatchJson:与 Overwrite 对应,annotations value为 json 字符串。如果 Pod 不存在该 annotations[key],则直接注入。如果存在,则进行 json value 合并。例如:Pod 中存在 annotations[oom-score]='{"main": 2}',注入后将 value json 合并为 annotations[oom-score]='{"log-agent": 1, "main": 2}'。 


注意:patchPolicy 为 Overwrite和MergePatchJson 时,SidecarSet 原地升级 Sidecar Container 时,能够同步更新该 annotations。但是,如果只修改 annotations 则不能生效,只能搭配 Sidecar 容器镜像一起原地升级。


patchPolicy 为 Retain 时,SidecarSet 原地升级 Sidecar Container 时,将不会同步更新该 annotations。


上述配置后,SidecarSet 在注入 Sidecar Container时,会注入 Pod annotations,如下:


apiVersion: v1
kind: Pod
metadata:
  annotations:
    apps.kruise.io/container-launch-priority: Ordered
    oom-score: '{"log-agent": 1, "main": 2}'
    custom.example.com/sidecar-configuration: '{"command": "/home/admin/bin/start.sh", "log-level": "3"}'
  name: test-pod
spec:
  containers:
    ...


注意:SidecarSet 从权限、安全的考虑不应该注入或修改除 Sidecar Container 之外的 Pod 字段,所以如果想要使用该能力,首先需要配置 SidecarSet_PatchPodMetadata_WhiteList 白名单或通过如下方式关闭白名单校验:


> helm install kruise https://... --set featureGates="SidecarSetPatchPodMetadataDefaultsAllowed =true"


Advanced DaemonSet 支持镜像预热


如果你在安装或升级 Kruise 的时候启用了  PreDownloadImageForDaemonSetUpdate feature-gate,DaemonSet 控制器会自动在所有旧版本 pod 所在 node 节点上预热你正在灰度发布的新版本镜像。这对于应用发布加速很有帮助。


默认情况下 DaemonSet 每个新镜像预热时的并发度都是 1,也就是一个个节点拉镜像。


如果需要调整,你可以通过 apps.kruise.io/image-predownload-parallelism annotation 来设置并发度。


apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
metadata:
  annotations:
    apps.kruise.io/image-predownload-parallelism: "10"


CloneSet 扩缩容与 PreparingDelete


默认情况下,CloneSet 将处于 PreparingDelete 状态的 Pod 视为正常,意味着这些 Pod 仍然被计算在 replicas 数量中。


在这种情况下:


  • 如果你将 replicas 从 N 改为 N-1,当一个要删除的 Pod 还在 PreparingDelete 状态中时,你重新将 replicas 改为 N,CloneSet 会将这个 Pod 重新置为 Normal 状态。 


  • 如果你将 replicas 从 N 改为 N-1 的同时在 podsToDelete 中设置了一个 Pod,当这个 Pod 还在 PreparingDelete 状态中时,你重新将 replicas 改为 N,CloneSet 会等到这个 Pod 真正进入 terminating 之后再扩容一个 Pod 出来。 


  • 如果你在不改变 replicas 的时候指定删除一个 Pod,当这个 Pod 还在 PreparingDelete 状态中时,CloneSet 会等到这个 Pod 真正进入 terminating 之后再扩容一个 Pod 出来。 


从 Kruise v1.3.0 版本开始,你可以在 CloneSet 中设置一个 apps.kruise.io/cloneset-scaling-exclude-preparing-delete: "true" 标签,它标志着这个 CloneSet 不会将 PreparingDelete 状态的 Pod 计算在 replicas 数量中。


在这种情况下:


  • 如果你将 replicas 从 N 改为 N-1,当一个要删除的 Pod 还在 PreparingDelete 状态中时,你重新将 replicas 改为 N,CloneSet 会将这个 Pod 重新置为 Normal 状态。 


  • 如果你将 replicas 从 N 改为 N-1 的同时在 podsToDelete 中设置了一个 Pod,当这个 Pod 还在 PreparingDelete 状态中时,你重新将 replicas 改为 N,CloneSet 会立即创建一个新 Pod。 


  • 如果你在不改变 replicas 的时候指定删除一个 Pod,当这个 Pod 还在 PreparingDelete 状态中时,CloneSet 会立即创建一个新 Pod。


Advanced CronJob Time zones


默认情况下,所有 AdvancedCronJob schedule 调度时,都是基于 kruise-controller-manager 容器本地的时区所计算的。


不过,在 v1.3.0 版本中我们引入了 spec.timeZone 字段,你可以将它设置为任意合法时区的名字。例如,设置 spec.timeZone: "Asia/Shanghai" 则 Kruise 会根据国内的时区计算 schedule 任务触发时间。


Go 标准库中内置了时区数据库,作为在容器的系统环境中没有外置数据库时的 fallback 选择。


其他改动


你可以通过 Github release[6] 页面,来查看更多的改动以及它们的作者与提交记录。


社区参与


非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。


你是否已经有一些希望与我们社区交流的内容呢?


可以在我们的
社区双周会上分享你的声音,或通过以下渠道参与讨论:


  • 加入社区 Slack channel[7] (English)
  • 加入社区钉钉群:搜索群号 23330762 (Chinese)
  • 加入社区微信群(新):添加用户 openkruise 并让机器人拉你入群 (Chinese) 


参考链接


[1] #1026

https://github.com/openkruise/kruise/pull/1026


[2] #1027

https://github.com/openkruise/kruise/pull/1027


[3] #1011

https://github.com/openkruise/kruise/pull/1011


[4] #1015

https://github.com/openkruise/kruise/pull/1015


[5] #1068

https://github.com/openkruise/kruise/pull/1068


[6] Github release:

https://github.com/openkruise/kruise/releases


[7] Slack channel

https://kubernetes.slack.com/channels/openkruise


此处,查看 OpenKruise 项目官方主页与文档!

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
6月前
|
Kubernetes 监控 Cloud Native
Kubernetes自动伸缩方案的终极指南
【4月更文挑战第18天】
312 0
Kubernetes自动伸缩方案的终极指南
|
3月前
|
资源调度 Kubernetes 调度
玩转Kubernetes集群:掌握节点和Pod自动扩缩容,让你的系统更智能、更高效!
【8月更文挑战第22天】Kubernetes的核心功能之一是自动扩缩容,确保系统稳定与高可用。节点自动扩缩容由调度器和控制器管理器协作完成,依据资源紧张程度动态调整。主要采用HPA、VPA及Cluster Autoscaler实现。Pod自动扩缩容通常通过HPA控制器按需调整副本数量。例如,设置HPA控制器监视特定部署的CPU使用率,在80%阈值上下自动增减副本数。合理利用这些工具可显著提升系统性能。
100 2
|
6月前
|
Kubernetes 监控 Go
容器服务Kubernetes版产品使用合集之如果业务已经接入了pinpoint agent产生冲突如何解决
容器服务Kubernetes版,作为阿里云提供的核心服务之一,旨在帮助企业及开发者高效管理和运行Kubernetes集群,实现应用的容器化与微服务化。以下是关于使用这些服务的一些建议和合集,涵盖基本操作、最佳实践、以及一些高级功能的使用方法。
|
6月前
|
存储 运维 监控
Kubernetes 集群的持续监控与优化策略
【5月更文挑战第3天】在微服务架构和容器化部署日益普及的背景下,Kubernetes 已成为众多企业的首选容器编排平台。然而,随着集群规模的增长和业务复杂度的提升,有效的集群监控和性能优化成为确保系统稳定性和提升资源利用率的关键。本文将深入探讨针对 Kubernetes 集群的监控工具选择、监控指标的重要性解读以及基于数据驱动的性能优化实践,为运维人员提供一套系统的持续监控与优化策略。
160 7
|
6月前
|
运维 Prometheus 监控
Kubernetes 集群的监控与维护策略
【5月更文挑战第30天】 在微服务架构日益普及的背景下,容器编排工具如Kubernetes成为确保服务高效运行的关键。本文聚焦于Kubernetes集群的监控和维护,首先探讨了监控系统的重要性及其对集群健康的影响,随后详细介绍了一套综合监控策略,包括节点性能监控、应用服务质量跟踪以及日志管理等方面。此外,文章还提出了一系列实用的集群维护技巧和最佳实践,旨在帮助运维人员预防故障发生,快速定位问题,并确保集群长期稳定运行。
|
6月前
|
存储 运维 监控
Kubernetes 集群的监控与性能优化策略
【5月更文挑战第19天】 在微服务架构日益普及的背景下,容器编排工具如Kubernetes已成为部署、管理和扩展服务的关键平台。然而,随着集群规模的增长和服务的复杂化,有效的监控和性能优化成为确保系统稳定性和高效性的重要挑战。本文将探讨针对Kubernetes集群监控的最佳实践,并提出一系列性能优化策略,旨在帮助运维人员识别潜在的瓶颈,保障服务的持续可靠性及响应速度。
|
6月前
|
存储 运维 监控
Kubernetes 集群的持续监控与性能优化策略
【5月更文挑战第11天】在微服务架构日益普及的当下,Kubernetes 已成为容器编排的事实标准。随着其在不同规模企业的广泛采用,如何确保 Kubernetes 集群的高效稳定运行变得至关重要。本文将探讨一套系统的 Kubernetes 集群监控方法,并结合实践经验分享针对性能瓶颈的优化策略。通过实时监控、日志分析与定期审计的结合,旨在帮助运维人员快速定位问题并提出解决方案,从而提升系统的整体表现。
|
6月前
|
Kubernetes 监控 物联网
IoT 边缘集群基于 Kubernetes Events 的告警通知实现(二):进一步配置
IoT 边缘集群基于 Kubernetes Events 的告警通知实现(二):进一步配置
|
Kubernetes 监控 Python
阿里云kubernetes(ACK)pod异常问题分析辅助工具-pod生命周期及事件可观测一览图
阿里云kubernetes(ACK)pod异常问题分析辅助工具-pod生命周期及事件可观测一览图
|
域名解析 Prometheus Kubernetes
kubernetes 部署Prometheus监控集群传统部署方案)(2)
kubernetes 部署Prometheus监控集群传统部署方案)(2)
kubernetes 部署Prometheus监控集群传统部署方案)(2)