百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

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

sinye56 2024-11-09 13:37 3 浏览 0 评论

作者:黄晓萌(学仁)


背景

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

许多传统企业使用 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: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command: ["/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()

2. 在本地编写 Dockerfile

FROM python:3

WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY edas/schedulerx-job.py /root/edas/schedulerx-job.py

CMD [ "python", "/root/edas/schedulerx-job.py" ]

3. 制作 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

4. 编写 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-python
            image: registry.cn-beijing.aliyuncs.com/demo/edas/schedulerx-job:1.0.0
            imagePullPolicy: IfNotPresent
            command: ["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 四种脚本类型),把脚本拷贝进去,然后配置定时表达式

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

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

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


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: hello
            image: perl:5.34
            command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(100)"]
          restartPolicy: OnFailure

2. 在 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)

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

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

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

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

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

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

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

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

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


K8s原生解决方案

阿里云解决方案

手动运行一次

不支持

支持

手动重跑任务

不支持

支持

Cron定时调度

支持,YAML配置

支持,兼容开源CronJob的YAML,也支持通过控制台动态配置

K8s资源占用

高,保留最近3次Pod

低,仅保留最近1次Pod

历史记录

最近3次

最近300次

日志

最近3次

最近2周,支持搜索

报警

不支持

支持,企业级报警通知服务

操作记录

不支持

支持


总结


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

相关推荐

linux安装FTP

1、在nkftp目录下安装ftp,进入到nkftp里面[root@localhostbin]#cd/data/nkftp执行安装命令:[root@localhostnkftp]#rpm-i...

LINUX下搭建FTP服务器

FTP服务器介绍FTP是FileTransferProtocol(文件传输协议)的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(App...

Linux下如何进行FTP设置

目录:一、Redhat/CentOS安装vsftp软件二、Ubuntu/Debian安装vsftp软件一、Redhat/CentOS安装vsftp软件1.更新yum源yumupdate-y2.安...

推荐使用集串口 SSH远程登录和FTP传输三合一工具MobaXterm

来源:百问网作者:韦东山本文字数:1216,阅读时长:4分钟在以前的资料里,串口和SSH远程登使用SecureCRT,window与ubuntu数据传输使用filezilla,窗口切换来切换去,麻烦也...

如何搭建FTP服务器(Linux系统)

上次说了Windows操作系统下搭建的FTP服务器,那有朋友问我,说买的XX轻量应用服务器都是属于Linux的操作系统,我该如何为搭建FTP服务器呢?...

Linux 命令 ncftp(文件传输)——想玩转linux就请一直看下去

我是IT悟道,点击右上方“关注”,每天分享IT、科技、数码方面的干货。Linuxncftp命令...

如何用 ftp 实现一键上传

简介ftp是Internet标准文件传输协议的用户界面,它允许用户与远程网络站点之间传输文件...

Linux安装ftp

1安装vsftpd组件安装完后,有/etc/vsftpd/vsftpd.conf文件,是vsftp的配置文件。[root@bogon~]#yum-yinstallvsftpd2添加一个...

一天一点点:linux - ftp命令

linuxftp命令设置文件系统相关功能。FTP是ARPANet的标准文件传输协议,该网络就是现今Internet的前身。语法ftp[-dignv][主机名称或IP地址]参数:-d详细显示指令执...

Centos 7 搭建FTP

目录安装软件以及启动服务添加防火墙规则关闭selinuxftp配置常用常用参数详解特殊参数配置文件没有的参数也可以添加到配置中1.安装软件以及启动服务yuminstall-yvsftpdsys...

【Linux】Linux中ftp命令,没有你想的那么简单

本文介绍了Linux中FTP命令的基本用法,包括连接与登录远程服务器,以及解析了FTP协议中五个最常用的操作命令的使用和解析过程。同时,提供了一个包含常用FTP操作命令的表格,供读者参考。通过熟练掌握...

linux 命令行操作ftp

以下是linuxftp命令参数的详解。FTP>!从ftp子系统退出到外壳?FTP>?显示ftp命令说明??和help相同?格式:?[command]说明:[com...

多学习才能多赚钱之:linux如何使用ftp

linux如何使用ftp步骤1:建立FTP连接想要连接FTP服务器,在命令上中先输入ftp然后空格跟上FTP服务器的域名'domain.com'或者IP地址例如:ftpdom...

linux常用网络操作方法:ftp命令使用方法

常用网络操作方法Linux提供了一组强有力的网络命令来为用户服务,这些工具能够帮助用户登录到远程计算机上、传输文件和执行远程命令等。本节介绍下列几个常用的有关网络操作的命令:ftp传输文件tel...

Linux 5.15有望合并Memory Folios方案 内核构建速度可提升7%

甲骨文公司的长期内核开发人员MatthewWilcox已经研究了“内存对开区”概念相当长的一段时间,这可以改善Linux的内存管理,使其具有更大的效率。例如,使用内存对开的基准测试表明,内核的构建速...

取消回复欢迎 发表评论: