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 (状态为 CompleteFailed)的另一种方式是使用由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-ttlttlSecondsAfterFinished 值为 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控制器需要去维护一个统计 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 手动添加或删除该注解。

前面你提到了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。

例如,如果 startingDeadlineSeconds200,则控制器会统计在过去 200 秒中错过了多少次 Job。

如果未能在调度时间内创建 CronJob,则计为错过。 例如,如果 concurrencyPolicy 被设置为 Forbid,并且当前有一个调度仍在运行的情况下, 试图调度的 CronJob 将被计算为错过。

例如,假设一个 CronJob 被设置为从 08:30:00 开始每隔一分钟创建一个新的 Job,并且它的 startingDeadlineSeconds 字段未被设置。

如果 CronJob 控制器从 08:29:0010:21:00 终止运行,则该 Job 将不会启动,因为其错过的调度 次数超过了 100。

进一步分析

假设将 CronJob 设置为从 08:30:00 开始每隔一分钟创建一个新的 Job,并将其 startingDeadlineSeconds 字段设置为 200 秒。

如果 CronJob 控制器恰好在与上一个示例相同的时间段(08:29:0010:21:00)终止运行, 则 Job 仍将从 10:22:00 开始。

造成这种情况的原因是控制器现在检查在最近 200 秒(即 3 个错过的调度)中发生了多少次错过的 Job 调度,而不是从现在为止的最后一个调度时间开始。

这里理解一个概念

CronJob 仅负责创建与其调度时间相匹配的 Job,而 Job 又负责管理其代表的 Pod。

Kubernetes 推荐学习书

Kubernetes权威指南PDF

链接:https://pan.baidu.com/s/11huLHJkCeIPZqSyLEoUEmQ 提取码:sa88

k8s系列所有问题更新记录:GitHub

TTL 机制排毒,线上k8s的Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job?的更多相关文章

  1. 谈谈MySQL bin log的写入机制、以及线上的参数是如何配置的

    目录 一.binlog 的高速缓存 二.刷盘机制 三.推荐的策略 推荐阅读 问个问题吧!为什么你需要了解binlog的落盘机制呢? 我来回答一下: ​ 上一篇文章提到了生产环境中你可以使用binlog ...

  2. 研发流程 接口定义&开发&前后端联调 线上日志观察 模型变动

    阿里等大厂的研发流程,进去前先了解一下_我们一起进大厂 - SegmentFault 思否 https://segmentfault.com/a/1190000021831640 接口定义 测试用例评 ...

  3. 分布式存储 FastDFS-5.0.5线上搭建

    前言:       由于公司项目需要,最近开始学习一下分布式存储相关知识,确定使用FastDFS这个开源工具.学习之初,自己利用VMware虚拟机搭建了一个5台机器的集群,摸清了安装过程中可能出现的问 ...

  4. 线上Redis偶发性链接失败排查记

    问题过程 输入法业务于12月12日上线了词库接受业务,对部分用户根据用户uuid判断进行回传,在12月17日早上8点多开始出现大量的php报错(Redis went away),报错导致了大量的链接积 ...

  5. K8S线上集群排查,实测排查Node节点NotReady异常状态

    一,文章简述 大家好,本篇是个人的第 2 篇文章.是关于在之前项目中,k8s 线上集群中 Node 节点状态变成 NotReady 状态,导致整个 Node 节点中容器停止服务后的问题排查. 文章中所 ...

  6. k8s线上某些特殊情况强制删除 StatefulSet 的 Pod 要考虑什么隐患?

    k8s线上某些特殊情况强制删除 StatefulSet 的 Pod 要考虑什么隐患? 考点之什么情况下,需要强制删除 StatefulSet 的 Pod? 考点之如果 StatefulSet 操作不当 ...

  7. 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器?

    探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 线上多个服务应用陷入了死 ...

  8. 用“逐步排除”的方法定位Java服务线上“系统性”故障(转)

    一.摘要 由于硬件问题.系统资源紧缺或者程序本身的BUG,Java服务在线上不可避免地会出现一些“系统性”故障,比如:服务性能明显下降.部分(或所 有)接口超时或卡死等.其中部分故障隐藏颇深,对运维和 ...

  9. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程

    简述C#中IO的应用   在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...

随机推荐

  1. Go之Logrus用法入门

    Go之Logrus用法入门 Logrus是Go (golang)的结构化日志程序,完全兼容标准库的API日志程序. Logrus is a structured logger for Go (gola ...

  2. 论文翻译:2020_DCCRN: Deep Complex Convolution Recurrent Network for Phase-Aware Speech Enhancement

    论文地址:DCCRN:用于相位感知语音增强的深度复杂卷积循环网络 论文代码:https://paperswithcode.com/paper/dccrn-deep-complex-convolutio ...

  3. DBScan聚类,打破形状的限制,使用密度聚类

    如何用花盆摆放成国庆字,并且包围这两个字. 在DBSCAN中衡量密度主要使用的指标:半径.最少样本量 算法原理 *直接密度可达 如果一个点在核心对象的半径区域内,那么这个点和核心对象称为直接密度可达, ...

  4. php——字符串的""和null,empty的关系

    public function test(){ $test = ""; if($test==null){ echo "test==null <hr>" ...

  5. 4月17日 python学习总结 反射、object内置方法、元类

    一.反射 下述四个函数是专门用来操作类与对象属性的,如何操作? 通过字符串来操作类与对象的属性,这种操作称为反射 class People: country="China" def ...

  6. 09自动售货机综设实验(含按键消抖,led和状态机)

    一设计功能 1.上次状态机的练习 2这次自动售货机综设 (一)对比两次的售货机 上次售货机的关键是画出状态转移图.明确输入分几种,输出是啥,有哪些状态.如下图所示 (二)系统或综合设计的经验: 既然这 ...

  7. Mycat 数据切分 看这一篇就够了

    数据切分 ​ 数据切分指的是通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库上面,以达到分散单台设备负载的效果. ​ 数据的切分根据其切分规则的类型,可以分为两种切分模式.一种 ...

  8. CF17E Palisection(manacher/回文树)

    CF17E Palisection(manacher/回文树) Luogu 题解时间 直接正难则反改成求不相交的对数. manacher求出半径之后就可以差分搞出以某个位置为开头/结尾的回文串个数. ...

  9. Python 中 PyQt5 库语法(一)

    目录 PyQt5库(一) 一. 简介 1. 什么是 Qt 2. 什么是PyQt 3. 环境搭建 二. 基本结构 1. 第一个程序 2. 控件操作 3. 快速生成代码 4. 面向对象 三. 基类控件 1 ...

  10. Makefile学习(一)

       objects = main.o kbd.o command.o display.o \              insert.o search.o files.o utils.o       ...