作者:黄晓萌(学仁)
布景
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 原生解决计划
- 将 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()
- 在本地编写 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" ]
- 制作 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
- 编写 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 集群当中运转起来,运用十分便利,如下图:
-
在你的 K8s 集群中布置一个 schedulerx-deployment(只需求装一次),注册到 SchedulerX 上来,让 SchedulerX 能够调度你的 K8s 上的 Pod
-
在 SchedulerX 使命办理新建一个 K8s 使命,资源类型挑选 Python-Script(当时支撑 shell/python/php/nodejs 四种脚本类型),把脚本拷贝进去,然后装备守时表达式
这儿的镜像只需求构建一个基础镜像即可,假如脚本内容有修正,只需依赖的库没有改动,就不需求从头构建镜像。
- 等调度时刻到了,或者经过操控台手动运转一次,能够在 K8s 集群中看到以 Pod 的方法运转脚本,Pod 名称为 schedulerx-python-{JobId}
下面经过一个表格更便利的看到两个计划的差异:
K8s原生解决计划 | 阿里云解决计划 | |
---|---|---|
脚本办理 | 不支撑 | 支撑,经过SchedulerX操控台能够进行脚本办理 |
开发功率 | 慢,每次修正脚本都需求从头构建镜像 | 快,在线修正脚本,不需求构建镜像,主动布置 |
学习本钱 | 高,需求学习Docker和K8s等容器相关常识 | 低,不需求容器相关常识,会写脚本就行 |
增强原生 K8s CronJob
SchedulerX 不光能够快速开发 K8s 脚本使命,屏蔽容器服务的细节,给不熟悉容器服务的同学带来福音,一起还能保管原生 K8s Job/CronJob,增强可运维可观测等才能。
K8s 原生解决计划
以官方供给的 CronJob 为例。
- 编写 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
- 在 K8s 集群中运转该 CronJob,检查 pod 前史记载和日志
发现原生的 CronJob 只能检查最近 3 条履行记载和日志,想要检查更久之前的记载无法看到,这在事务出现问题想排查的时分就变得尤为困难。虽然能够经过装备 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 来保存更多的 Pod 前史记载,可是保存更多的 Pod,就会愈加占用 K8s 集群的资源,因为 Job 现已跑完了,仅仅为了检查日志保存更多前史记载,本钱太高了。
阿里云解决计划
阿里使命调度 SchedulerX 能够保管原生 K8s Job/CronJob,便利移植,运用 SchedulerX 保管,能够具有更强的可运维可观测才能,比方使命重跑、日志服务、报警监控等。
- 新建 K8s 使命,使命类型挑选 K8s,资源类型挑选 Job-YAML,打印 bpi(-1)
- 经过工具来生成 cron 表达式,比方每小时第 8 分钟跑
- 调度时刻还没到,也能够手动点击“运转一次”来进行测试
- 在 K8s 集群中能够看到 Job 和 Pod 发动成功,每个使命只会保存最近一次调度的 Pod,减少 K8s 集群的资源占用
- 在 SchedulerX 操控台也能够看到前史履行记载,发现运转失利
- 在 SchedulerX 操控台能够看到使命运转日志,检查失利原因
- 在线修正使命的 YAML,打印 bpi(100)
- 不需求删除 Job,经过操控台来重跑使命
- 使命重跑成功,且能看到新的日志
下面经过一个表格来比照两个计划的差异:
K8s原生解决计划 | 阿里云解决计划 | |
---|---|---|
手动运转一次 | 不支撑 | 支撑 |
手动重跑使命 | 不支撑 | 支撑 |
Cron守时调度 | 支撑,YAML装备 | 支撑,兼容开源CronJob的YAML,也支撑经过操控台动态装备 |
K8s资源占用 | 高,保存最近3次Pod | 低,仅保存最近1次Pod |
前史记载 | 最近3次 | 最近300次 |
日志 | 最近3次 | 最近2周,支撑查找 |
报警 | 不支撑 | 支撑,企业级报警通知服务 |
操作记载 | 不支撑 | 支撑 |
总结
在云原生年代,运用 K8s CronJob 在许多场景下能够作为 Linux Crontab 替换的解决计划,解决了crontab的一系列痛点问题。经过阿里云 SchedulerX 来调度你的 K8s CronJob,能够降低学习本钱,加快开发功率,让你的使命失利可报警,出问题可排查, 打造云原生可观测系统下的守时使命。