共计 4086 个字符,预计需要花费 11 分钟才能阅读完成。
TTL 机制排毒,线上 k8s 的 Job 曾经通过 API 减少了 Job 的 TTL 时长,且胜利响应,为什么零碎还是清理了 Job?
面试官:"已实现 Job 的 TTL 机制理解嘛?简略说说 TTL 存在的工夫偏差问题?"
面试官:"能简略形容一下什么是 TTL-after-finished 控制器嘛?"
面试官:"我明明曾经通过 API 减少了 Job 的 TTL 时长,且失去了胜利的响应,为什么零碎还是清理了 Job?"
面试官:"如何更加精确的跟踪 Job 实现状况?理解 Finalizer 追踪 Job 嘛?"
面试官:"说说什么场景下 CronJob 无奈被调度?"
囧么肥事 - 胡言乱语
已实现 Job 的 TTL 机制理解嘛?简略说说 TTL 存在的工夫偏差问题?
实现的 Job 通常不须要持续留存在零碎中。在零碎中始终保留它们会给 API 服务器带来额定的压力。
实际上主动清理实现的 Job 有两种惯例形式:
1、更高级别的控制器治理
2、已实现 Job 的 TTL 机制
更高级别的控制器治理
如果 Job 由某种更高级别的控制器来治理,例如CronJobs
,则 Job 能够被 CronJob
基于特定的依据容量裁定的清理策略清理掉。
已实现 Job 的 TTL 机制
主动清理已实现 Job(状态为 Complete
或 Failed
)的另一种形式是应用由 TTL-after-finished
控制器所提供 的 TTL 机制。通过设置 Job 的 .spec.ttlSecondsAfterFinished
字段,能够让该控制器清理掉 已完结的资源。
留神点一:TTL 控制器清理 Job 时,会级联式地删除 Job 对象。换言之,它会删除所有依赖的对象,包含 Pod 及 Job 自身。
留神点二:当 Job 被删除时,零碎会思考其生命周期保障,其生命周期函数也将被触发,例如 Finalizers
。
面试官:“能简略形容一下什么是 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-ttl
的ttlSecondsAfterFinished
值为 100,则在其完结100
秒之后,Job 将 能够被主动删除 - 如果
ttlSecondsAfterFinished
被设置为0
,则 TTL 控制器在 Job 执行完结后,立即就能够清理该 Job 及其 Pod - 如果
ttlSecondsAfterFinished
值未设置,则 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 将被保留。
如何更加精确的跟踪 Job 实现状况?理解 Finalizer 追踪 Job 嘛?
想要更加精确的跟踪 Job 实现状况,须要为 API 服务器和控制器管理器启用 JobTrackingWithFinalizers
个性,该个性默认是禁用的。
启用后,管制面会追踪新的 Job,对现有 Job 不受影响
未启用 JobTrackingWithFinalizers
个性前是如何跟踪 Job 实现状况的?
该性能未启用时,Job 控制器依附计算 k8s 集群中存在的 Pod 来跟踪作业状态。
也就是说,Job 控制器须要去保护一个统计 succeeded
和 failed
的 Pod 的计数器。
然而,Pod 可能会因为一些起因被移除,导致统计不精确:
- 当一个节点宕机时,垃圾收集器会删除孤立(Orphan)Pod。
- 垃圾收集器在 某个阈值后删除已实现的 Pod(处于
Succeeded
或Failed
阶段)。 - 人工干预删除 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 手动增加或删除该注解。
后面你提到了 CronJobs 负载,它编排的 Job 为什么须要是幂等的?
CronJob 创立基于时隔反复调度的 Jobs。CronJob
用于执行周期性的动作,例如 备份、报告生成 等。你能够定义工作开始执行的工夫距离,这些每一个工作都应该配置为周期性反复的(例如:每天 / 每周 / 每月一次);
CronJob
依据打算编排,在每次该执行工作的时候 大概会创立一个 Job。之所以说 “ 大概 ”,是因为在某些状况下,可能会创立两个 Job,或者不会创立任何 Job。k8s 试图使这些状况尽量少产生,但临时还不能齐全杜绝。因而,Job 应该是 幂等的。
留神:如果
startingDeadlineSeconds
设置为很大的数值或未设置(默认),并且concurrencyPolicy
设置为Allow
,则作业将始终至多运行一次。
思考什么场景下 CronJob 无奈被调度?
无奈调度,第一种,startingDeadlineSeconds
值低于CronJob
周期查看工夫,第二种,屡次错过调度。
如果 startingDeadlineSeconds
的设置值 低于 10 秒钟,CronJob 可能无奈被调度。因为 CronJob 控制器每 10 秒钟执行一次查看。
对于每个 CronJob 负载来说,CronJob 查看从上一次调度的工夫点到当初所错过了调度次数。如果错过的调度次数超过 100 次,那么它就不会启动这个工作,并记录这个谬误:
Cannot determine if job needs to be started.
Too many missed start time (> 100).
Set or decrease .spec.startingDeadlineSeconds or check clock skew.
须要留神的是,如果 startingDeadlineSeconds
字段非空,则控制器会统计从 startingDeadlineSeconds
设置的值到当初而不是从上一个打算工夫到当初错过了多少次 Job。
例如,如果
startingDeadlineSeconds
是200
,则控制器会统计在过来 200 秒中错过了多少次 Job。
如果未能在调度工夫内创立 CronJob,则计为错过。例如,如果 concurrencyPolicy
被设置为 Forbid
,并且以后有一个调度仍在运行的状况下,试图调度的 CronJob 将被计算为错过。
例如,假如一个 CronJob 被设置为从
08:30:00
开始每隔一分钟创立一个新的 Job,并且它的startingDeadlineSeconds
字段未被设置。如果 CronJob 控制器从
08:29:00
到10:21:00
终止运行,则该 Job 将不会启动,因为其错过的调度 次数超过了 100。
进一步剖析
假如将 CronJob 设置为从
08:30:00
开始每隔一分钟创立一个新的 Job,并将其startingDeadlineSeconds
字段设置为 200 秒。如果 CronJob 控制器恰好在与上一个示例雷同的时间段(
08:29:00
到10:21:00
)终止运行,则 Job 仍将从10:22:00
开始。
造成这种状况的起因是控制器当初查看在最近 200 秒(即 3 个错过的调度)中产生了多少次错过的 Job 调度,而不是从当初为止的最初一个调度工夫开始。
这里了解一个概念
CronJob 仅负责创立与其调度工夫相匹配的 Job,而 Job 又负责管理其代表的 Pod。
Kubernetes 举荐学习书
Kubernetes 权威指南 PDF
链接:https://pan.baidu.com/s/11huL… 提取码:sa88
k8s 系列所有问题更新记录:GitHub Gitee