作者:黃曉萌(學(xué)仁)
背景
Job 表示短周期的作業(yè),定時 Job 表示按照預(yù)定的時間運行Job,或者按照某一頻率周期性的運行 Job。比如:
許多傳統(tǒng)企業(yè)使用 Linux 自帶的 crontab 來做定時任務(wù)的方案,該方案非常簡單,適合做主機上的運維工作,比如定時清理日志、周期性做健康檢查。隨著信息化時代的高速發(fā)展,業(yè)務(wù)變得越來越復(fù)雜,很多場景都需要定時任務(wù),但是 crontab 方案存在高可用問題,不適合應(yīng)用在業(yè)務(wù)應(yīng)用上。
在云原生時代,K8s CronJob 設(shè)計了一套高可用的定時任務(wù)解決方案,保障了業(yè)務(wù)的穩(wěn)定。但是把 K8s CronJob 應(yīng)用在生產(chǎn)上,發(fā)現(xiàn)定時任務(wù)真的出問題的時候排查起來很麻煩,于是越來越多用戶對定時任務(wù)的可觀測有了更多的訴求,阿里云也推出了自己的云原生定時任務(wù)解決方案,可以托管原生 K8s CronJob,提供可報警、可觀測、可運維等能力,幫助企業(yè)提效。
Linux Crontab 方案面臨的問題
什么是 Crontab
Crontab 是 Linux 系統(tǒng)中的一個服務(wù),用于創(chuàng)建、編輯和管理定時任務(wù)。通過 crontab 命令,用戶可以設(shè)置系統(tǒng)在指定時間自動執(zhí)行某個命令或腳本。
Crontab 命令的語法分為兩部分,分別是時間表達式和命令。時間表達式如下:
# ┌───────────── 分鐘 (0 - 59)
# │ ┌───────────── 小時 (0 - 23)
# │ │ ┌───────────── 月的某天 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 周的某天 (0 - 6)(周日到周一;在某些系統(tǒng)上,7 也是星期日)
# │ │ │ │ │ 或者是 sun,mon,tue,web,thu,fri,sat
# │ │ │ │ │
# │ │ │ │ │
# * * * * *
命令常用來執(zhí)行某個腳本,舉個例子:
- 每隔 5 分鐘執(zhí)行 hello.sh:*/5 * * * * sh /root/script/hello.sh
- 每天早上 6 點半執(zhí)行 world.py: ?30 6 * * * python /root/script/world.py
Crontab 的工作原理
Crontab 由一個名為"Crond"的守護進程負責(zé)調(diào)度任務(wù),當(dāng) Crond 啟動的時候,就會從配置文件(路徑在 /var/spool/cron 下)加載所有的定時任務(wù)。當(dāng)執(zhí)行 crontab 命令的時候,會動態(tài)的添加新的定時任務(wù),并加入到配置文件中。Crontab 每次執(zhí)行任務(wù),都會產(chǎn)生執(zhí)行記錄,目錄在 /var/log/cron 下。
Crontab 的痛點問題
使用 crontab 主要有如下痛點:
- 無高可用: 為了保證業(yè)務(wù)冪等執(zhí)行,需要在不同的機器配置不同的 crontab 任務(wù)。crontab 只能調(diào)度本機器上的定時任務(wù),如果某一個機器掛了,那上面的定時任務(wù)也都不會執(zhí)行了,有穩(wěn)定性風(fēng)險。
- 無自動負載均衡: 不同的腳本放在不同的機器上,需要手動負載均衡,如果腳本比較多,運維代價很高。
- 無權(quán)限隔離: 一般企業(yè)生產(chǎn)的機器只有運維才能登陸,但是開發(fā)要新增/修改腳本和定時任務(wù),也需要登錄到生產(chǎn)的機器上,沒法做到權(quán)限隔離。
云原生 K8s CronJob 方案的優(yōu)勢
什么是 K8s CronJob
Job 是 K8s 中的一種資源,用來處理短周期的 Pod,相當(dāng)于一次性任務(wù),跑完就會把 Pod 銷毀,不會一直占用資源,可以節(jié)省成本,提高資源利用率。CronJob 也是 K8s 中的資源,用來周期性的重復(fù)調(diào)度 Job。
下面是一個 CronJob 的示例,每隔 5 分鐘調(diào)度腳本 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 的優(yōu)勢
與單純使用 Crontab 相比,使用 K8s CronJob 帶來了如下優(yōu)勢:
- 高可用: K8s 會保證集群的高可用,如集群中有節(jié)點掛了,都不會影響定時任務(wù)的調(diào)度。
- 自動負載均衡: Pod 默認選擇負載最低的 node 執(zhí)行,支持 NodeSelector 和親和性等多種負載均衡策略。
- 權(quán)限隔離: 只有運維可以登錄 master 和 worker 節(jié)點,開發(fā)通過管控或者 ApiServer 來創(chuàng)建和更新 CronJob,并且支持命名空間隔離,RBAC 權(quán)限管理。
K8s CronJob 的進階能力
Linux Crontab 只能周期性調(diào)度本機的腳本,功能比較簡單,K8s 定時任務(wù)支持更多的進階能力:
- 在 Job 資源上
-
- 并行執(zhí)行: 通常一個 Job 只啟動一個 Pod,可以通過配置 spec.completions 參數(shù),來決定一個 Job 要執(zhí)行多少個 Pod。
- 索引任務(wù): 并行執(zhí)行通常需要和索引任務(wù)結(jié)合使用,當(dāng)配置 .spec.completionMode=“Indexed” 時,這個 Job 就是一個索引任務(wù),每個 Pod 會獲得一個不同的索引值,介于 0 和 .spec.completions-1 之間,這樣就可以讓不同的 Pod 根據(jù)索引值處理不同的數(shù)據(jù)。
- 并行限流: 并行執(zhí)行的時候,通常還需要做限流,可以配置 .spec.parallelism 參數(shù),來控制一個 Job 最多同時跑多少個 Pod。
- 失敗自動重試: 可以配置 .spec.backoffLimit,來設(shè)置 Job 失敗重試次數(shù)。
- 超時: 可以配置 .spec.activeDeadlineSeconds,來設(shè)置 Job 超時的時間。
- 在 CronJob 資源上
-
- 時區(qū): 可以通過設(shè)置 .spec.timeZone 參數(shù),決定 CronJob 按照哪個時區(qū)的時間來調(diào)度任務(wù)。
- 并發(fā)性規(guī)則: 當(dāng)一個 Job 還在執(zhí)行,下次調(diào)度時間到了,是否執(zhí)行新的 Job,可以通過 .spec.concurrencyPolicy 來配置,取值為 Allow/Forbid/Replace。
- 任務(wù)歷史限制: 可以通過配置 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 來決定保留多少成功和失敗的 Job。
阿里云 K8s CronJob 提效新模式
阿里云分布式任務(wù)調(diào)度 SchedulerX 和云原生結(jié)合,推出可視化 K8s Job 解決方案。針對腳本使用者,屏蔽了容器服務(wù)的細節(jié),不用構(gòu)建鏡像就可以讓不熟悉容器的同學(xué)(比如運維和運營同學(xué))玩轉(zhuǎn) K8s Job,受益容器服務(wù)帶來的降本增效福利。針對容器使用者,SchedulerX 不但完全兼容原生的 K8s Job,還能支持歷史執(zhí)行記錄、日志服務(wù)、重跑任務(wù)、報警監(jiān)控、可視化任務(wù)編排等能力,為企業(yè)級應(yīng)用保駕護航。
快速遷移 Crontab 腳本任務(wù)
通過上面的章節(jié),我們知道 Linux Crontab 存在許多問題,遷移到 K8s CronJob 可以帶來很多好處,但是要從 crontab 遷移到 K8s CronJob 還是挺麻煩的,這里以通過 python 腳本訪問數(shù)據(jù)庫為例,來對比兩種方案的差異。
K8s 原生解決方案
- 將 crontab 腳本拷貝到本地,取名為 edas/schedulerx-job.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打開數(shù)據(jù)庫連接
db = MySQLdb.connect("localhost", "testuser", "test123", "TESTDB", charset='utf8' )
# 使用cursor()方法獲取操作游標
cursor = db.cursor()
# SQL 查詢語句
sql = "SELECT * FROM EMPLOYEE \
WHERE INCOME > %s" % (1000)
try:
# 執(zhí)行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]
# 打印結(jié)果
print "fname=%s,lname=%s,age=%s,sex=%s,income=%s" % \
(fname, lname, age, sex, income )
except:
print "Error: unable to fetch data"
# 關(guān)閉數(shù)據(jù)庫連接
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 的命令為執(zhí)行腳本
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,就需要這么多步驟,如果之后要修改腳本,還需要重新構(gòu)建鏡像和重新發(fā)布 K8s CronJob,這里先不計算開始之前的學(xué)習(xí)成本,單純從使用角度來看,有著較高的上手成本。
阿里云解決方案
阿里任務(wù)調(diào)度 SchedulerX 結(jié)合云原生技術(shù),提出了一套可視化的腳本任務(wù)解決方案,通過任務(wù)調(diào)度系統(tǒng)來管理腳本,直接在線編寫腳本,不需要構(gòu)建鏡像,就可以將腳本以 Pod 的方式在用戶的 K8s 集群當(dāng)中運行起來,使用非常方便,如下圖:
-
在你的 K8s 集群中部署一個 schedulerx-deployment(只需要裝一次),注冊到 SchedulerX 上來,讓 SchedulerX 可以調(diào)度你的 K8s 上的 Pod
-
在 SchedulerX 任務(wù)管理新建一個 K8s 任務(wù),資源類型選擇 Python-Script(當(dāng)前支持 shell/python/php/nodejs 四種腳本類型),把腳本拷貝進去,然后配置定時表達式
這里的鏡像只需要構(gòu)建一個基礎(chǔ)鏡像即可,如果腳本內(nèi)容有修改,只要依賴的庫沒有改變,就不需要重新構(gòu)建鏡像。
- 等調(diào)度時間到了,或者通過控制臺手動運行一次,可以在 K8s 集群中看到以 Pod 的方式運行腳本,Pod 名稱為 schedulerx-python-{JobId}
下面通過一個表格更方便的看到兩個方案的差異:
K8s原生解決方案 | 阿里云解決方案 | |
---|---|---|
腳本管理 | 不支持 | 支持,通過SchedulerX控制臺可以進行腳本管理 |
開發(fā)效率 | 慢,每次修改腳本都需要重新構(gòu)建鏡像 | 快,在線修改腳本,不需要構(gòu)建鏡像,自動部署 |
學(xué)習(xí)成本 | 高,需要學(xué)習(xí)Docker和K8s等容器相關(guān)知識 | 低,不需要容器相關(guān)知識,會寫腳本就行 |
增強原生 K8s CronJob
SchedulerX 不但能夠快速開發(fā) K8s 腳本任務(wù),屏蔽容器服務(wù)的細節(jié),給不熟悉容器服務(wù)的同學(xué)帶來福音,同時還能托管原生 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 歷史記錄和日志
發(fā)現(xiàn)原生的 CronJob 只能查看最近 3 條執(zhí)行記錄和日志,想要查看更久之前的記錄無法看到,這在業(yè)務(wù)出現(xiàn)問題想排查的時候就變得尤為困難。雖然可以通過配置 .spec.successfulJobsHistoryLimit 和 .spec.failedJobsHistoryLimit 來保留更多的 Pod 歷史記錄,但是保留更多的 Pod,就會更加占用 K8s 集群的資源,因為 Job 已經(jīng)跑完了,只是為了查看日志保留更多歷史記錄,成本太高了。
阿里云解決方案
阿里任務(wù)調(diào)度 SchedulerX 可以托管原生 K8s Job/CronJob,方便移植,使用 SchedulerX 托管,可以具有更強的可運維可觀測能力,比如任務(wù)重跑、日志服務(wù)、報警監(jiān)控等。
- 新建 K8s 任務(wù),任務(wù)類型選擇 K8s,資源類型選擇 Job-YAML,打印 bpi(-1)
- 通過工具來生成 cron 表達式,比如每小時第 8 分鐘跑
- 調(diào)度時間還沒到,也可以手動點擊“運行一次”來進行測試
- 在 K8s 集群中可以看到 Job 和 Pod 啟動成功,每個任務(wù)只會保留最近一次調(diào)度的 Pod,減少 K8s 集群的資源占用
- 在 SchedulerX 控制臺也可以看到歷史執(zhí)行記錄,發(fā)現(xiàn)運行失敗
- 在 SchedulerX 控制臺可以看到任務(wù)運行日志,查看失敗原因
- 在線修改任務(wù)的 YAML,打印 bpi(100)
- 不需要刪除 Job,通過控制臺來重跑任務(wù)
- 任務(wù)重跑成功,且能看到新的日志
下面通過一個表格來對比兩個方案的差異:文章來源:http://www.zghlxwxcb.cn/news/detail-776576.html
K8s原生解決方案 | 阿里云解決方案 | |
---|---|---|
手動運行一次 | 不支持 | 支持 |
手動重跑任務(wù) | 不支持 | 支持 |
Cron定時調(diào)度 | 支持,YAML配置 | 支持,兼容開源CronJob的YAML,也支持通過控制臺動態(tài)配置 |
K8s資源占用 | 高,保留最近3次Pod | 低,僅保留最近1次Pod |
歷史記錄 | 最近3次 | 最近300次 |
日志 | 最近3次 | 最近2周,支持搜索 |
報警 | 不支持 | 支持,企業(yè)級報警通知服務(wù) |
操作記錄 | 不支持 | 支持 |
總結(jié)
在云原生時代,使用 K8s CronJob 在很多場景下可以作為 Linux Crontab 替換的解決方案,解決了crontab的一系列痛點問題。通過阿里云 SchedulerX 來調(diào)度你的 K8s CronJob,能夠降低學(xué)習(xí)成本,加快開發(fā)效率,讓你的任務(wù)失敗可報警,出問題可排查, 打造云原生可觀測體系下的定時任務(wù)。文章來源地址http://www.zghlxwxcb.cn/news/detail-776576.html
到了這里,關(guān)于從 Linux Crontab 到 K8s CronJob,定時任務(wù)正在經(jīng)歷怎樣的變革的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!