作者:黄晓萌(学仁)

布景

Job 表明短周期的作业,守时 Job 表明依照预订的时刻运转Job,或者依照某一频率周期性的运转 Job。比方:

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

许多传统企业运用 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 下。

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

Crontab 的痛点问题

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

运用 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 的优势

从 Linux Crontab 到 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: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" ]
  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-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 集群当中运转起来,运用十分便利,如下图:

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 在你的 K8s 集群中布置一个 schedulerx-deployment(只需求装一次),注册到 SchedulerX 上来,让 SchedulerX 能够调度你的 K8s 上的 Pod

  2. 在 SchedulerX 使命办理新建一个 K8s 使命,资源类型挑选 Python-Script(当时支撑 shell/python/php/nodejs 四种脚本类型),把脚本拷贝进去,然后装备守时表达式

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

这儿的镜像只需求构建一个基础镜像即可,假如脚本内容有修正,只需依赖的库没有改动,就不需求从头构建镜像。

  1. 等调度时刻到了,或者经过操控台手动运转一次,能够在 K8s 集群中看到以 Pod 的方法运转脚本,Pod 名称为 schedulerx-python-{JobId}

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

下面经过一个表格更便利的看到两个计划的差异:

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
  1. 在 K8s 集群中运转该 CronJob,检查 pod 前史记载和日志

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

发现原生的 CronJob 只能检查最近 3 条履行记载和日志,想要检查更久之前的记载无法看到,这在事务出现问题想排查的时分就变得尤为困难。虽然能够经过装备 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 来保存更多的 Pod 前史记载,可是保存更多的 Pod,就会愈加占用 K8s 集群的资源,因为 Job 现已跑完了,仅仅为了检查日志保存更多前史记载,本钱太高了。

阿里云解决计划

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

  1. 新建 K8s 使命,使命类型挑选 K8s,资源类型挑选 Job-YAML,打印 bpi(-1)

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

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

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 调度时刻还没到,也能够手动点击“运转一次”来进行测试

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 在 K8s 集群中能够看到 Job 和 Pod 发动成功,每个使命只会保存最近一次调度的 Pod,减少 K8s 集群的资源占用

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 在 SchedulerX 操控台也能够看到前史履行记载,发现运转失利

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 在 SchedulerX 操控台能够看到使命运转日志,检查失利原因

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 在线修正使命的 YAML,打印 bpi(100)

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 不需求删除 Job,经过操控台来重跑使命

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

  1. 使命重跑成功,且能看到新的日志

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

从 Linux Crontab 到 K8s CronJob,守时使命正在阅历怎样的革新

下面经过一个表格来比照两个计划的差异:

K8s原生解决计划 阿里云解决计划
手动运转一次 不支撑 支撑
手动重跑使命 不支撑 支撑
Cron守时调度 支撑,YAML装备 支撑,兼容开源CronJob的YAML,也支撑经过操控台动态装备
K8s资源占用 高,保存最近3次Pod 低,仅保存最近1次Pod
前史记载 最近3次 最近300次
日志 最近3次 最近2周,支撑查找
报警 不支撑 支撑,企业级报警通知服务
操作记载 不支撑 支撑

总结

在云原生年代,运用 K8s CronJob 在许多场景下能够作为 Linux Crontab 替换的解决计划,解决了crontab的一系列痛点问题。经过阿里云 SchedulerX 来调度你的 K8s CronJob,能够降低学习本钱,加快开发功率,让你的使命失利可报警,出问题可排查, 打造云原生可观测系统下的守时使命。