替代kubernetes Crontab的神器kala

本来 k8s 的 crontab 是启动一个容器来运行的,很简单,如下:

 1apiVersion: batch/v1beta1
 2kind: CronJob
 3metadata:
 4  name: curl-cron
 5spec:
 6  schedule: "*/1 * * * *"
 7  jobTemplate:
 8    spec:
 9      template:
10        spec:
11          containers:
12          - name: curl-cron
13            image: radial/busyboxplus:curl
14            imagePullPolicy: IfNotPresent
15            command:
16            - /bin/sh
17            - -c
18            - date;echo "run crontab";curl http://www.baidu.com
19          restartPolicy: OnFailure
20  successfulJobsHistoryLimit: 2
21  failedJobsHistoryLimit: 2

上面就跑了一个 busybox 的 pod,每分钟去访问百度,然后在 stdout 输出结果

这个没什么,注意上面文件的最后两行。限制成功以及失败 job 的 History 数量,如果不加限制,kubectl get pods 会看到无穷无尽的completed 状态的 curl-cron pod。



分割线,部署 crontab 的 yaml 很简单。但是,现在产品部有个需求,他们要在某一天进行促销活动,大概2天,期间会流量大增,于是想应用 hpa 来伸缩 pod,活动结束后关闭 hpa。之后他们还会有不断的促销,研发不知道什么时候开始,什么时候结束;但是研发又不想产品部看到 yaml,并且随时配合部署 hpa。

还有个问题,如果用crontab,那么活动开始运行一次,活动结束一次,最后研发还得清理删除掉这两个 crontab 来恢复正常。

这下麻烦了,有什么页面管理 crontab 的神器,能让产品部自己运行,然后权限分离,而且能指定再未来的某天运行一次或多次,且不用手工清理就好了。

还真的有一个,kala 就是了!!!

Kala 是一个cron管理配置工具,项目地址:

https://github.com/ajvb/kala

image-20211125164706478

卡拉是基于 Airbnb 的 Chronos 翻写的 Go 程序。

它比 crontab 更好一些的是,可以指定未来某天的一次性执行任务,有个使用界面

Kala 可以执行本地的命令,也可以发起 http 的请求。

注意,kala 的源代码里有一个地方需要修改,否则参数bolt-path不生效,我们改掉它自己编译个2进制程序出来。

 1Modify cmd/server.go
 2
 3switch viper.GetString("jobdb") {
 4case "boltdb":
 5db = boltdb.GetBoltDB(viper.GetString("boltpath"))
 6
 7Change to
 8db = boltdb.GetBoltDB(viper.GetString("bolt-path"))
 9
10Run it :
11./kala serve --jobdb=boltdb --bolt-path=/data/db

我们用 Dockerfile 造一个镜像出来:

 1FROM alpine:3.12
 2RUN apk add --update bash && rm -rf /var/cache/apk/*
 3
 4COPY . /data/
 5
 6RUN mkdir /lib64 && \
 7    ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2 && \
 8    mv /data/kubectl /bin && \
 9    mv /data/.kube /root && \
10    rm -rf /data/Dockerfile
11
12WORKDIR /data
13EXPOSE 8000
14
15CMD ["/data/kala", "serve","--jobdb=boltdb","--bolt-path=/data/db"]
16#CMD /bin/sh -c "while true; do echo hi; sleep 10; done"

注意上面我们把 kubectl 和 .kube 配置一起放进了镜像,当然一些 yaml 和脚本也可以都打进去,然后推到阿里云镜像仓库去(注意安全问题)。

备注 :kala默认的端口是8000,访问 url 是 /webui

然后我们生成一个 secret 放进 k8s

1htpasswd -c auth kala-auth
2New password:
3Re-type new password:
4Adding password for user kala
5
6kubectl create secret generic kala-auth --from-file=kala-auth
7secret "kala-auth" created
8
9kubectl get secret kala-auth -o yaml

然后我们定义一系列的资源文件,Deployment、SVC、Ingress,其中 ingress 引用了 kala-auth 的 secret,并且指定了 app-root 是 /webui/。

另外 kala 使用了 k8s-kala-5g 的持久化卷,务必事先准备好 pv 和 pvc,不持久化的话 pod 一重启,之前保存的配置信息就全没了。

 1---
 2apiVersion: apps/v1
 3kind: Deployment
 4metadata:
 5  name: kala-deploy
 6  labels:
 7    app: kala
 8spec:
 9  replicas: 1
10  selector:
11    matchLabels:
12      app: kala
13  template:
14    metadata:
15      labels:
16        app: kala
17    spec:
18      containers:
19      - name: kala
20        image: registry.cn-shanghai.aliyun.com/xxx/kala:latest
21        imagePullPolicy: Always
22        ports:
23        - containerPort: 8000
24        volumeMounts:
25        - mountPath: /data/db
26          name: kala-data
27      volumes:
28        - name: kala-data
29          persistentVolumeClaim:
30            claimName: k8s-kala-5g
31---
32apiVersion: v1
33kind: Service
34metadata:
35 name: kala-svc
36 labels:
37   app: kala
38spec:
39 ports:
40 - name: http
41   protocol: TCP
42   port: 8000
43   targetPort: 8000
44 selector:
45   app: kala
46 type: ClusterIP
47---
48apiVersion: networking.k8s.io/v1beta1
49kind: Ingress
50metadata:
51  name: kala-com-ingress
52  annotations:
53    kubernetes.io/ingress.class: nginx
54    nginx.ingress.kubernetes.io/block-cidrs: 111.201.134.93/32
55    nginx.ingress.kubernetes.io/auth-type: basic
56    nginx.ingress.kubernetes.io/auth-secret: kala-auth
57    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - Kala'
58    nginx.ingress.kubernetes.io/app-root: '/webui/'
59spec:
60  rules:
61  - host: kala.rendoumi.com
62    http:
63      paths:
64      - path: /
65        backend:
66          serviceName: kala-svc
67          servicePort: 80

这样 kala 就可以从公网访问了,http://kala.rendoumi.com:8000/ ,且需要提供密码才能进入。

下面说一下具体的用法,还是有一些技巧性的,登录进去后的页面:

image-20211125170959532

进入后左上角点击 Create 建立新任务

image-20211125171027673

要填写内容如下:

  • Job name:起个名字,叫:增大HPA

  • Command:要运行的脚本:/data/resize.sh 35 (固定扩大ECI的脚本)

  • Schedule:R0/2021-07-07T06:00:00+08:00/PT0S

​ 这个最重要

​ 这行的格式是这样的:Number of times to repeat/Start Datetime/Interval Between Runs

​ R0 重复0次,即只执行一次,不重复

​ 2021-07-06T06:00:00+8:00 时间戳,注意时区中国+8:00

​ PT0S 无延迟0S启动

​ 合起来就是

​ R0/2021-07-07T06:00:00+08:00/PT0S 就是在2021年7月7日中国时间6点无任何延迟执行一次脚本 resize.sh

  • Reset Form 这个一定要选掉,保持空,否则下次进来上次的数据都没了,还得手动输入,麻烦

其他都不填写,然后 Create 就行了

然后我们可以再建一个恢复的任务

image-20211125171551356

我们去界面就可以看到多了两个任务,增大HPA和恢复HPA,这样就 OK 了

image-20211125171655096

注意:JOB一旦建立,以后就可以直接从界面上手动执行,Run Manually

image-20211125171831594

这东西真是个神器,产品部的同事可以随时修改hpa和恢复,而不用通过研发部了,善莫大焉。


Kubernetes的hpa和自定义指标hpa
Kubernetes搭建minio作为阿里OSS的Gateway
comments powered by Disqus