从 Linux Crontab 到 K8s CronJob,定时任务正在经历怎样的变革

作者:黄晓萌(学仁)

背景

Job 表示短周期的作业,定时 Job 表示按照预定的时间运行Job,或者按照某一频率周期性的运行 Job。比如:

image.png

许多传统企业使用 Linux 自带的 crontab 来做定时任务的方案,该方案非常简单,适合做主机上的运维工作,比如定时清理日志、周期性做健康检查。随着信息化时代的高速发展,业务变得越来越复杂,很多场景都需要定时任务,但是 crontab 方案存在高可用问题,不适合应用在业务应用上。

在云原生时代,K8s CronJob 设计了一套高可用的定时任务解决方案,保障了业务的稳定。但是把 K8s CronJob 应用在生产上,发现定时任务真的出问题的时候排查起来很麻烦,于是越来越多用户对定时任务的可观测有了更多的诉求,阿里云也推出了自己的云原生定时任务解决方案,可以托管原生 K8s CronJob,提供可报警、可观测、可运维等能力,帮助企业提效。

Linux Crontab 方案面临的问题

什么是 Crontab

Crontab 是 Linux 系统中的一个服务,用于创建、编辑和管理定时任务。通过 crontab 命令,用户可以设置系统在指定时间自动执行某个命令或脚本。

Crontab 命令的语法分为两部分,分别是时间表达式和命令。时间表达式如下:

# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系统上,7 也是星期日)
# │ │ │ │ │                          或者是 sun,mon,tue,web,thu,fri,sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *

命令常用来执行某个脚本,举个例子:

  • 每隔 5 分钟执行 hello.sh:*/5 * * * * sh /root/script/hello.sh
  • 每天早上 6 点半执行 world.py:  30 6 * * * python /root/script/world.py

Crontab 的工作原理

Crontab 由一个名为"Crond"的守护进程负责调度任务,当 Crond 启动的时候,就会从配置文件(路径在 /var/spool/cron 下)加载所有的定时任务。当执行 crontab 命令的时候,会动态的添加新的定时任务,并加入到配置文件中。Crontab 每次执行任务,都会产生执行记录,目录在 /var/log/cron 下。

图片

Crontab 的痛点问题

图片

使用 crontab 主要有如下痛点:

  • 无高可用: 为了保证业务幂等执行,需要在不同的机器配置不同的 crontab 任务。crontab 只能调度本机器上的定时任务,如果某一个机器挂了,那上面的定时任务也都不会执行了,有稳定性风险。
  • 无自动负载均衡: 不同的脚本放在不同的机器上,需要手动负载均衡,如果脚本比较多,运维代价很高。
  • 无权限隔离: 一般企业生产的机器只有运维才能登陆,但是开发要新增/修改脚本和定时任务,也需要登录到生产的机器上,没法做到权限隔离。

云原生 K8s CronJob 方案的优势

什么是 K8s CronJob

Job 是 K8s 中的一种资源,用来处理短周期的 Pod,相当于一次性任务,跑完就会把 Pod 销毁,不会一直占用资源,可以节省成本,提高资源利用率。CronJob 也是 K8s 中的资源,用来周期性的重复调度 Job。

下面是一个 CronJob 的示例,每隔 5 分钟调度脚本 edas/schedulerx-job.sh:

apiVersion: batch/v1
kind: CronJob
metadata:name: hello
spec:schedule: "*/5 * * * *"jobTemplate:spec:template:spec:containers:- name: helloimage: busybox:1.28imagePullPolicy: IfNotPresentcommand: ["/bin/sh", "/root/script/edas/schedulerx-job.sh"]restartPolicy: OnFailure

K8s CronJob 的优势

图片

与单纯使用 Crontab 相比,使用 K8s CronJob 带来了如下优势:

  • 高可用: K8s 会保证集群的高可用,如集群中有节点挂了,都不会影响定时任务的调度。
  • 自动负载均衡: Pod 默认选择负载最低的 node 执行,支持 NodeSelector 和亲和性等多种负载均衡策略。
  • 权限隔离: 只有运维可以登录 master 和 worker 节点,开发通过管控或者 ApiServer 来创建和更新 CronJob,并且支持命名空间隔离,RBAC 权限管理。

K8s CronJob 的进阶能力

Linux Crontab 只能周期性调度本机的脚本,功能比较简单,K8s 定时任务支持更多的进阶能力:

  • 在 Job 资源上
    • 并行执行: 通常一个 Job 只启动一个 Pod,可以通过配置 spec.completions 参数,来决定一个 Job 要执行多少个 Pod。
    • 索引任务: 并行执行通常需要和索引任务结合使用,当配置 .spec.completionMode=“Indexed” 时,这个 Job 就是一个索引任务,每个 Pod 会获得一个不同的索引值,介于 0 和 .spec.completions-1 之间,这样就可以让不同的 Pod 根据索引值处理不同的数据。
    • 并行限流: 并行执行的时候,通常还需要做限流,可以配置 .spec.parallelism 参数,来控制一个 Job 最多同时跑多少个 Pod。
    • 失败自动重试: 可以配置 .spec.backoffLimit,来设置 Job 失败重试次数。
    • 超时: 可以配置 .spec.activeDeadlineSeconds,来设置 Job 超时的时间。
  • 在 CronJob 资源上
    • 时区: 可以通过设置 .spec.timeZone 参数,决定 CronJob 按照哪个时区的时间来调度任务。
    • 并发性规则: 当一个 Job 还在执行,下次调度时间到了,是否执行新的 Job,可以通过 .spec.concurrencyPolicy 来配置,取值为 Allow/Forbid/Replace。
    • 任务历史限制: 可以通过配置 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 来决定保留多少成功和失败的 Job。

阿里云 K8s CronJob 提效新模式

阿里云分布式任务调度 SchedulerX 和云原生结合,推出可视化 K8s Job 解决方案。针对脚本使用者,屏蔽了容器服务的细节,不用构建镜像就可以让不熟悉容器的同学(比如运维和运营同学)玩转 K8s Job,受益容器服务带来的降本增效福利。针对容器使用者,SchedulerX 不但完全兼容原生的 K8s Job,还能支持历史执行记录、日志服务、重跑任务、报警监控、可视化任务编排等能力,为企业级应用保驾护航。

快速迁移 Crontab 脚本任务

通过上面的章节,我们知道 Linux Crontab 存在许多问题,迁移到 K8s CronJob 可以带来很多好处,但是要从 crontab 迁移到 K8s CronJob 还是挺麻烦的,这里以通过 python 脚本访问数据库为例,来对比两种方案的差异。

K8s 原生解决方案
  1. 将 crontab 脚本拷贝到本地,取名为 edas/schedulerx-job.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-import MySQLdb# 打开数据库连接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8' )# 使用cursor()方法获取操作游标 
cursor = db.cursor()# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE \
WHERE INCOME > %s" % (1000)
try:# 执行SQL语句cursor.execute(sql)# 获取所有记录列表results = cursor.fetchall()for row in results:fname = row[0]lname = row[1]age = row[2]sex = row[3]income = row[4]# 打印结果print "fname=%s,lname=%s,age=%s,sex=%s,income=%s" % \(fname, lname, age, sex, income )except:print "Error: unable to fetch data"# 关闭数据库连接
db.close()
  1. 在本地编写 Dockerfile
FROM python:3WORKDIR /usr/src/appCOPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txtCOPY edas/schedulerx-job.py /root/edas/schedulerx-job.pyCMD [ "python", "/root/edas/schedulerx-job.py" ]
  1. 制作 docker 镜像,推到镜像仓库中
docker build -t registry.cn-beijing.aliyuncs.com/demo/edas/schedulerx-job:1.0.0 .
docker push registry.cn-beijing.aliyuncs.com/demo/edas/schedulerx-job:1.0.0
  1. 编写 K8s CronJob 的 YAML 文件,image 选择第 3 步制作的镜像,command 的命令为执行脚本
apiVersion: batch/v1
kind: CronJob
metadata:name: demo-python
spec:schedule: "*/5 * * * *"jobTemplate:spec:template:spec:containers:- name: demo-pythonimage: registry.cn-beijing.aliyuncs.com/demo/edas/schedulerx-job:1.0.0imagePullPolicy: IfNotPresentcommand: ["python",  "/root/edas/schedulerx-job.py"]restartPolicy: OnFailure

我们看到把一个 contab 迁移到 K8s CronJob,就需要这么多步骤,如果之后要修改脚本,还需要重新构建镜像和重新发布 K8s CronJob,这里先不计算开始之前的学习成本,单纯从使用角度来看,有着较高的上手成本。

阿里云解决方案

阿里任务调度 SchedulerX 结合云原生技术,提出了一套可视化的脚本任务解决方案,通过任务调度系统来管理脚本,直接在线编写脚本,不需要构建镜像,就可以将脚本以 Pod 的方式在用户的 K8s 集群当中运行起来,使用非常方便,如下图:

图片

  1. 在你的 K8s 集群中部署一个 schedulerx-deployment(只需要装一次),注册到 SchedulerX 上来,让 SchedulerX 可以调度你的 K8s 上的 Pod

  2. 在 SchedulerX 任务管理新建一个 K8s 任务,资源类型选择 Python-Script(当前支持 shell/python/php/nodejs 四种脚本类型),把脚本拷贝进去,然后配置定时表达式

图片

这里的镜像只需要构建一个基础镜像即可,如果脚本内容有修改,只要依赖的库没有改变,就不需要重新构建镜像。

  1. 等调度时间到了,或者通过控制台手动运行一次,可以在 K8s 集群中看到以 Pod 的方式运行脚本,Pod 名称为 schedulerx-python-{JobId}

image.png

下面通过一个表格更方便的看到两个方案的差异:

K8s原生解决方案阿里云解决方案
脚本管理不支持支持,通过SchedulerX控制台可以进行脚本管理
开发效率慢,每次修改脚本都需要重新构建镜像快,在线修改脚本,不需要构建镜像,自动部署
学习成本高,需要学习Docker和K8s等容器相关知识低,不需要容器相关知识,会写脚本就行

增强原生 K8s CronJob

SchedulerX 不但能够快速开发 K8s 脚本任务,屏蔽容器服务的细节,给不熟悉容器服务的同学带来福音,同时还能托管原生 K8s Job/CronJob,增强可运维可观测等能力。

K8s 原生解决方案

以官方提供的 CronJob 为例。

  1. 编写 hello.yaml
apiVersion: batch/v1
kind: CronJob
metadata:name: hello
spec:schedule: "* * * * *"jobTemplate:spec:template:spec:containers:- name: helloimage: perl:5.34command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(100)"]restartPolicy: OnFailure
  1. 在 K8s 集群中运行该 CronJob,查看 pod 历史记录和日志

图片

发现原生的 CronJob 只能查看最近 3 条执行记录和日志,想要查看更久之前的记录无法看到,这在业务出现问题想排查的时候就变得尤为困难。虽然可以通过配置 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 来保留更多的 Pod 历史记录,但是保留更多的 Pod,就会更加占用 K8s 集群的资源,因为 Job 已经跑完了,只是为了查看日志保留更多历史记录,成本太高了。

阿里云解决方案

阿里任务调度 SchedulerX 可以托管原生 K8s Job/CronJob,方便移植,使用 SchedulerX 托管,可以具有更强的可运维可观测能力,比如任务重跑、日志服务、报警监控等。

  1. 新建 K8s 任务,任务类型选择 K8s,资源类型选择 Job-YAML,打印 bpi(-1)

图片

  1. 通过工具来生成 cron 表达式,比如每小时第 8 分钟跑

图片

  1. 调度时间还没到,也可以手动点击“运行一次”来进行测试

图片

  1. 在 K8s 集群中可以看到 Job 和 Pod 启动成功,每个任务只会保留最近一次调度的 Pod,减少 K8s 集群的资源占用

图片

  1. 在 SchedulerX 控制台也可以看到历史执行记录,发现运行失败

image.png

  1. 在 SchedulerX 控制台可以看到任务运行日志,查看失败原因

图片

  1. 在线修改任务的 YAML,打印 bpi(100)

图片

  1. 不需要删除 Job,通过控制台来重跑任务

image.png

  1. 任务重跑成功,且能看到新的日志

图片

图片

下面通过一个表格来对比两个方案的差异:

K8s原生解决方案阿里云解决方案
手动运行一次不支持支持
手动重跑任务不支持支持
Cron定时调度支持,YAML配置支持,兼容开源CronJob的YAML,也支持通过控制台动态配置
K8s资源占用高,保留最近3次Pod低,仅保留最近1次Pod
历史记录最近3次最近300次
日志最近3次最近2周,支持搜索
报警不支持支持,企业级报警通知服务
操作记录不支持支持

总结

在云原生时代,使用 K8s CronJob 在很多场景下可以作为 Linux Crontab 替换的解决方案,解决了crontab的一系列痛点问题。通过阿里云 SchedulerX 来调度你的 K8s CronJob,能够降低学习成本,加快开发效率,让你的任务失败可报警,出问题可排查, 打造云原生可观测体系下的定时任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2659315.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

docker学习笔记02-安装mysql

1.安装mysql8 下载MySQL镜像 docker pull mysql:8.0创建并启动容器 docker run -itd --name mysqltest -p 9999:3306 -e MYSQL_ROOT_PASSWORD123456 mysql其中-it是交互界面 -d是后台执行 -name 指定容器名称 -p指定映射端口 -e设置环境变量 最后mysql是镜像名或者用镜像id如…

最新云渲染平台选择,云渲染避免踩坑指南

​随着云计算技术的飞速发展,云渲染逐步成为各类行业的优选工具,它凭借出色的效能和强大的并行计算能力,显著提高了工作效率,然而,要想充分利用云渲染技术,选择一款合适的云渲染平台是刻不容缓的课题&#…

一种删除 KubeSphere 中一直卡在 Terminating 的 Namespace--KubeSphere Logging System的简单方法

文章目录 一、问题提出二、删除方法1,获取kubesphere-logging-syste的详细信息json文件2,编辑kubesphere-logging-system.json3,执行清理命令 三、检查结果 一、问题提出 在使用 KubeSphere 的时候发现有一个日志服务KubeSphere Logging Sys…

React快速入门之交互性

响应事件 创建事件处理函数 处理函数名常以handle事件名命名 function handlePlayClick() {alert(Playing);}传递事件处理函数 函数名、匿名两种方式&#xff01; function PlayButton() {function handlePlayClick() {alert(Playing);}return (<Button handleClick{handl…

网站显示不安全警告怎么办?消除网站不安全警告超全指南

网站显示不安全警告怎么办&#xff1f;当用户访问你的网站&#xff0c;而您的网站没有部署SSL证书实现HTTPS加密时&#xff0c;网站就会显示不安全警告&#xff0c;这种警告&#xff0c;不仅有可能阻止用户继续浏览网站&#xff0c;影响网站声誉&#xff0c;还有可能影响网站在…

Android 8.1 设置USB传输文件模式(MTP)

项目需求&#xff0c;需要在电脑端adb发送通知手机端接收指令&#xff0c;将USB的仅充电模式更改成传输文件&#xff08;MTP&#xff09;模式&#xff0c;便捷用户在我的电脑里操作内存文件&#xff0c;下面是我们的常见的修改方式 1、android12以下、android21以上是这种方式…

纸质版表格怎么用扫描仪转换成电子版表格

要将纸质版表格转换成电子版表格&#xff0c;可以使用以下步骤&#xff1a; 1、准备一台物理扫描仪并与电脑连接好&#xff0c;并安装好驱动。 2、打开安装好的金鸣表格文字识别电脑客户端。 3、点击“扫描文件”&#xff0c;在弹出的对话框中选中需要使用的扫描仪。 4、点击“…

法线贴图可以实现什么样的3D效果

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 在 3D 建模中&#xff0c;曲面由多边形表示。照明计算是基于这些多边…

成考生必看!2023年成人高考录取后入学拿证流程

成人高考录取后并不是就可以坐等拿证了&#xff01; 成人高考录取后你还有这些事情要做。 一起来了解一下吧&#xff01; 成人高考入学到拿证流程 办理入学流程 1.入学时间 确认被高校录取后&#xff0c;12月下旬左右开始办理入学(实际时间以各院校安排为准&#xff09; 2.缴…

【28】Kotlin语法进阶——使用协程编写高效的并发程序

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、Kotlin中的协程1.1 协程的基本用法1.1.1协程与协程作用域1.1.2 使用launch函数创建子协程1.1.3 通过suspend关键声明挂起函数1.1.4 coroutineScope函数 1.2…

Arduino串口测试

目录 一、硬件介绍 1、控制器 2、TTL转USB串口 二、软件程序 1、单片机发送字符串 &#xff08;1&#xff09;每个串口对应的类名称介绍 &#xff08;2&#xff09;发送功能 &#xff08;3&#xff09;代码 &#xff08;4&#xff09;测试 2、单片机接收字符串 &…

鸿蒙开发之android对比开发《基础知识》

基于华为鸿蒙未来可能不再兼容android应用&#xff0c;推出鸿蒙开发系列文档&#xff0c;帮助android开发人员快速上手鸿蒙应用开发。 1. 鸿蒙使用什么基础语言开发&#xff1f; ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript&#xff08;简称TS&#xff09;基本语法风…

记录 | ubuntu源码编译python3.7.3(指定版本)

一、安装依赖包 sudo apt-get install -y make build-essential libssl-dev zlib1g-dev sudo apt-get install -y libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm sudo apt-get install -y libncurses5-dev libncursesw5-dev xz-utils tk-dev 二、从Python网…

二叉树数据结构:深入了解二叉树的概念、特性与结构

在探索栈和队列之后&#xff08;大家可以移步至我的数据结构专栏&#xff09;&#xff1a;T-rLN的数据结构专栏 我们转向了更为复杂而有趣的数据结构——二叉树。本文将引领我们进入二叉树的世界&#xff0c;从最基本的概念和结构开始&#xff0c;逐步深入了解二叉树的顺序结构…

听GPT 讲Rust源代码--src/tools(30)

File: rust/src/tools/clippy/clippy_lints/src/casts/cast_slice_from_raw_parts.rs 在Rust源代码中&#xff0c;cast_slice_from_raw_parts.rs文件位于rust/src/tools/clippy/clippy_lints/src/casts/目录下&#xff0c;它是Clippy工具中的一个lint&#xff0c;用于检查通过f…

【技巧】7z分卷压缩文件如何解压?

7z分卷压缩格式是一种常用的文件压缩格式&#xff0c;可以在压缩文件时将文件分割成多个独立的文件&#xff0c;更方便储存或者传输。那压缩好的7z分卷文件要如何解压呢&#xff1f;不清楚的小伙伴一起来看看吧。 想要解压7z分卷压缩文件&#xff0c;需要用到支持7z格式的解压…

Springboot拦截器及统一异常处理

文章目录 一、Java中异常相关概念1、异常类2、异常处理方法3、注意事项4、自定义异常 二、配置全局异常处理1、统一返回体定义2、定义异常处理实现类3、全局异常处理类 三、Springboot拦截器1、定义拦截器2、注册拦截器 四、验证效果 一、Java中异常相关概念 1、异常类 Throw…

微信小程序登录用户信息、手机号、照片等隐私api不能使用解决的方案

问题 突然小程序不能使用用户信息、手机号、图片上传的功能 例如这种错误 "getUserProfile:fail api scope is not declared in the privacy agreement" 定位问题 经过微信社区查询得知 为规范开发者的用户个人信息处理行为&#xff0c;保障用户的合法权益&…

(2)llvm解析器和抽象语法树

解析器的输出是抽象语法树 对于数字字面量&#xff0c;创造了一个实例&#xff0c;并捕捉 变量捕捉函数名&#xff1b;二元表达式捕捉运算符&#xff1b;函数调用捕捉函数名和函数调用参数 函数原型和函数定义 构建语法树 getNextToken会从输入流里拿一个token&#xff0c;Cur…

2023年中职“网络安全”——B-5:网络安全事件响应(Server2216)

B-5&#xff1a;网络安全事件响应 任务环境说明&#xff1a; 服务器场景&#xff1a;Server2216&#xff08;开放链接&#xff09; 用户名:root密码&#xff1a;123456 1、黑客通过网络攻入本地服务器&#xff0c;通过特殊手段在系统中建立了多个异常进程&#xff0c;找出启…