线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

生也有涯,知也无涯。这篇文章主要讲述线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job?相关的知识,希望能为你提供帮助。
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job?

面试官:"已完成 Job 的 TTL 机制了解嘛?简单说说TTL存在的时间偏差问题?"

面试官:"能简单描述一下什么是TTL-after-finished 控制器嘛?"

面试官:"我明明已经通过API 增加了Job的TTL 时长,且得到了成功的响应,为什么系统还是清理了Job?"

面试官:"如何更加准确的跟踪 Job 完成情况?了解 Finalizer 追踪 Job嘛?"

面试官:"说说什么场景下CronJob 无法被调度?"

线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

囧么肥事-胡说八道
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

已完成 Job 的 TTL 机制了解嘛?简单说说TTL存在的时间偏差问题?
完成的 Job 通常不需要继续留存在系统中。在系统中一直保留它们会给 API 服务器带来额外的压力。
实际上自动清理完成的 Job有两种常规方式:
1、更高级别的控制器管理2、已完成 Job 的 TTL 机制

更高级别的控制器管理
如果 Job 由某种更高级别的控制器来管理,例如CronJobs, 则 Job 可以被 CronJob 基于特定的根据容量裁定的清理策略清理掉。
已完成 Job 的 TTL 机制
自动清理已完成 Job (状态为 CompleteFailed)的另一种方式是使用由TTL-after-finished控制器所提供 的 TTL 机制。 通过设置 Job 的 .spec.ttlSecondsAfterFinished 字段,可以让该控制器清理掉 已结束的资源。
注意点一:TTL 控制器清理 Job 时,会级联式地删除 Job 对象。 换言之,它会删除所有依赖的对象,包括 Pod 及 Job 本身。
注意点二:当 Job 被删除时,系统会考虑其生命周期保障,其生命周期函数也将被触发,例如 Finalizers
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

面试官:“能简单描述一下什么是TTL-after-finished 控制器嘛?”TTL-after-finished 控制器只支持 Job。集群操作员可以通过指定 Job 的 .spec.ttlSecondsAfterFinished 字段来自动清理已结束的作业(Job状态为Complete或Failed)。
TTL-after-finished 控制器假设作业能在执行完成后的 TTL 秒内被清理,也就是当 TTL 过期后,当 TTL 控制器清理作业时,它将做级联删除操作,即删除资源对象的同时也删除其依赖对象。 注意,当资源被删除时,由该资源的生命周期保证其终结器(Finalizers)等被执行。
Job可以随时设置 TTL 秒,可以植入多种不同的需求场景,以下是设置 Job 的 .spec.ttlSecondsAfterFinished 字段的一些示例:
  • 在作业清单(manifest)中指定此字段,以便 Job 在完成后的某个时间被自动清除。
  • 将此字段设置为现有的、已完成的作业,以采用此新功能。
  • 创建作业时使用 mutating admission webhook 动态设置该字段。集群管理员可以使用它对完成的作业强制执行 TTL 策略。
  • 作业完成后使用 mutating admission webhook 动态设置该字段,并根据作业状态、标签等选择不同的 TTL 值。
字段解释 ttlSecondsAfterFinished
  • Job pi-with-ttlttlSecondsAfterFinished 值为 100,则在其结束 100 秒之后,Job将可以被自动删除
  • 如果 ttlSecondsAfterFinished 被设置为 0,则 TTL 控制器在 Job 执行结束后,立刻就可以清理该 Job 及其 Pod
  • 如果 ttlSecondsAfterFinished 值未设置,则 TTL 控制器不会清理该 Job
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

面试官:“我明明已经通过API 增加了Job的TTL 时长,且得到了成功的响应,为什么系统还是清理了Job?”这里涉及到两个TTL的概念:时间偏差和更新TTL秒数周期
时间偏差问题
由于 TTL-after-finished 控制器使用存储在 Kubernetes 资源中的时间戳来确定 TTL 是否已过期, 该功能对集群中的时间偏差很敏感,所以,设置非零 TTL 时,可能导致 TTL-after-finished 控制器在错误的时间清理资源对象。
更新 TTL 秒数问题
在创建 Job 或已经执行结束后,仍可以修改其 TTL 周期,例如 Job 的 .spec.ttlSecondsAfterFinished 字段。
但是一旦 Job 变为可被删除状态(当其 TTL 已过期时),即使通过 API 增加其 TTL 时长得到了成功的响应,系统也不保证 Job 将被保留。
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

如何更加准确的跟踪 Job 完成情况?了解 Finalizer 追踪 Job嘛?
想要更加准确的跟踪 Job 完成情况,需要为API 服务器和控制器管理器启用 JobTrackingWithFinalizers特性,该特性默认是禁用的。
未启用JobTrackingWithFinalizers特性前是如何跟踪Job完成情况的?也就是说,Job控制器需要去维护一个统计 succeededfailed 的 Pod 的计数器。
然而,Pod 可能会因为一些原因被移除,导致统计不准确:
  • 当一个节点宕机时,垃圾收集器会删除孤立(Orphan)Pod。
  • 垃圾收集器在某个阈值后删除已完成的 Pod(处于 SucceededFailed 阶段)。
  • 人工干预删除 Job 的 Pod。
  • 一个外部控制器(不包含于 Kubernetes)来删除或取代 Pod。
启用JobTrackingWithFinalizers特性后是如何跟踪Job完成情况的?如果集群启用了 JobTrackingWithFinalizers 特性,控制面会跟踪属于任何 Job 的 Pod。 并注意是否有任何这样的 Pod 被从 API 服务器上删除。 为了实现这一点,Job 控制器创建的 Pod 带有 Finalizer batch.kubernetes.io/job-tracking。 控制器只有在 Pod 被记入 Job 状态后才会移除 Finalizer,允许 Pod 可以被其他控制器或用户删除。
注意:Job 控制器只对新的 Job 使用新的算法。在启用该特性之前创建的 Job 不受影响。 你可以根据检查 Job 是否含有 batch.kubernetes.io/job-tracking 注解,来确定 Job 控制器是否正在使用 Pod Finalizer 追踪 Job。 注意不应该给 Job 手动添加或删除该注解。
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片

前面你提到了CronJobs负载,它编排的Job为什么需要是幂等的?
CronJob 创建基于时隔重复调度的 Jobs。CronJob 用于执行周期性的动作,例如备份、报告生成等。 你可以定义任务开始执行的时间间隔,这些每一个任务都应该配置为周期性重复的(例如:每天/每周/每月一次);
CronJob 根据计划编排,在每次该执行任务的时候大约会创建一个 Job。 之所以说 " 大约" ,是因为在某些情况下,可能会创建两个 Job,或者不会创建任何 Job。 k8s 试图使这些情况尽量少发生,但暂时还不能完全杜绝。因此,Job 应该是 幂等的
思考什么场景下CronJob 无法被调度?
无法调度,第一种,startingDeadlineSeconds值低于CronJob 周期检查时间,第二种,多次错过调度。
如果 startingDeadlineSeconds 的设置值低于 10 秒钟,CronJob 可能无法被调度。 因为 CronJob 控制器每 10 秒钟执行一次检查。
对于每个 CronJob负载来说,CronJob 检查从上一次调度的时间点到现在所错过了调度次数。如果错过的调度次数超过 100 次, 那么它就不会启动这个任务,并记录这个错误:
需要注意的是,如果 startingDeadlineSeconds 字段非空,则控制器会统计从 startingDeadlineSeconds 设置的值到现在而不是从上一个计划时间到现在错过了多少次 Job。
如果未能在调度时间内创建 CronJob,则计为错过。 例如,如果 concurrencyPolicy 被设置为 Forbid,并且当前有一个调度仍在运行的情况下, 试图调度的 CronJob 将被计算为错过。
进一步分析
造成这种情况的原因是控制器现在检查在最近 200 秒(即 3 个错过的调度)中发生了多少次错过的 Job 调度,而不是从现在为止的最后一个调度时间开始。
这里理解一个概念
【线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()】
线上k8s集群TTL 机制排毒,Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job()

文章图片


    推荐阅读