TTL 机制排毒,线上k8s的Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job?
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/11huLHJkCeIPZqSyLEoUEmQ 提取码:sa88
k8s系列所有问题更新记录:GitHub
TTL 机制排毒,线上k8s的Job已经通过API 增加了Job的TTL 时长,且成功响应,为什么系统还是清理了Job?的更多相关文章
- 谈谈MySQL bin log的写入机制、以及线上的参数是如何配置的
目录 一.binlog 的高速缓存 二.刷盘机制 三.推荐的策略 推荐阅读 问个问题吧!为什么你需要了解binlog的落盘机制呢? 我来回答一下: 上一篇文章提到了生产环境中你可以使用binlog ...
- 研发流程 接口定义&开发&前后端联调 线上日志观察 模型变动
阿里等大厂的研发流程,进去前先了解一下_我们一起进大厂 - SegmentFault 思否 https://segmentfault.com/a/1190000021831640 接口定义 测试用例评 ...
- 分布式存储 FastDFS-5.0.5线上搭建
前言: 由于公司项目需要,最近开始学习一下分布式存储相关知识,确定使用FastDFS这个开源工具.学习之初,自己利用VMware虚拟机搭建了一个5台机器的集群,摸清了安装过程中可能出现的问 ...
- 线上Redis偶发性链接失败排查记
问题过程 输入法业务于12月12日上线了词库接受业务,对部分用户根据用户uuid判断进行回传,在12月17日早上8点多开始出现大量的php报错(Redis went away),报错导致了大量的链接积 ...
- K8S线上集群排查,实测排查Node节点NotReady异常状态
一,文章简述 大家好,本篇是个人的第 2 篇文章.是关于在之前项目中,k8s 线上集群中 Node 节点状态变成 NotReady 状态,导致整个 Node 节点中容器停止服务后的问题排查. 文章中所 ...
- k8s线上某些特殊情况强制删除 StatefulSet 的 Pod 要考虑什么隐患?
k8s线上某些特殊情况强制删除 StatefulSet 的 Pod 要考虑什么隐患? 考点之什么情况下,需要强制删除 StatefulSet 的 Pod? 考点之如果 StatefulSet 操作不当 ...
- 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器?
探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 线上多个服务应用陷入了死 ...
- 用“逐步排除”的方法定位Java服务线上“系统性”故障(转)
一.摘要 由于硬件问题.系统资源紧缺或者程序本身的BUG,Java服务在线上不可避免地会出现一些“系统性”故障,比如:服务性能明显下降.部分(或所 有)接口超时或卡死等.其中部分故障隐藏颇深,对运维和 ...
- 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程
简述C#中IO的应用 在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...
随机推荐
- 开发并发布依赖包,作为工具包供别人npm install
1.初识包及 npm 包的概念: nodejs 中的第三方模块叫包 不同于 nodejs 中的内置模块与自定义模块,包是由第三方个人或团队开发出来的,免费供所有人使用 nodejs 中的包都是免费开源 ...
- appium报错Message: Cannot set the element to ‘XXXX’. Did you interact with the correct element?
appium+python+android 在定位到模块输入内容的时候遇到了一个问题 send_keys报错 appium报错Message: Cannot set the element to 'X ...
- JavaScript面向对象—继承的实现
JavaScript面向对象-继承的实现 前言 面向对象的三大特性:封装.继承和多态.上一篇我们简单的了解了封装的过程,也就是把对象的属性和方法封装到一个函数中,这一篇讲一下JavaScript中继承 ...
- 微服务7:通信之RPC
★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...
- github:git clone下载加速以及vim-plug下载插件加速
git clone 下载加速 1. 先在github将仓库地址复制下来 2. git clone时将https://github.com/* 改为https://gitclone.com/github ...
- Python:range、np.arange和np.linspace
1. range range是python内置的一个类,该类型表示一个不可改变(immutable)的数字序列,常常用于在for循环中迭代一组特殊的数,它的原型可以近似表示如下: class rang ...
- 我写的 Python 代码,同事都说好
原文链接: 我写的 Python 代码,同事都说好 人生苦短,我用 Python. 程序员的追求就是不写代码,早日财务自由.不对,一不小心把实话说出来了,应该是将代码写得简洁,优雅. Python 程 ...
- SpringMVC前后端分离交互传参详细教程
温故而知新,本文为一时兴起写出,如有错误还请指正 本文后台基于SpringBoot2.5.6编写,前端基于Vue2 + axios和微信小程序JS版分别编写进行联调测试,用于理解前后端分离式开发的交互 ...
- python练习册 每天一个小程序 第0011题
1 # -*-coding:utf-8-*- 2 3 4 def test(content): 5 flag = 0 6 with open('filtered_words.txt') as fp: ...
- 《手把手教你》系列基础篇(八十一)-java+ selenium自动化测试-框架设计基础-TestNG如何暂停执行一些case(详解教程)
1.简介 在实际测试过程中,我们经常会遇到这样的情况,开发由于某些原因导致一些模块进度延后,而你的自动化测试脚本已经提前完成,这样就会有部分模块测试,有部分模块不能进行测试.这就需要我们暂时不让一些t ...