任务流管理工具
背景
当我们经常和机器打交道时,就会有大量的 任务 需要管理,比如一个小的 shell 脚本,或者一系列 shell 脚本,有时候甚至是一系列的 python 脚本。
场景很多,比如 启动一台机器并进行一些设置,比如 对某个项目进行打包然后推送到制品库 等等。
在 CI 中,我们一般使用 CI 平台提供的任务流管理器,例如 gitlab-ci、jenkins、argo-workflow 等等。
在机器运维中,我们一般使用 ansible、salt 等方案。
在大多数时候,shell 往往是独立运行的,最常见的场景是: 开发人员发现某个操作很繁琐,但内容又非常固定,于是针对特定场景写一个 shell 脚本。
当这类脚本积累了一些之后,就会发现很多场景是可以复用的,可以用一些小场景拼凑一些更大的场景,这时候怎么办呢?
于是就找到了 taskfile 这个项目。
项目能力
和所有任务流管理器一样, taskfile 提供的基础能力就是 编排多个 task
,这是一个用 golang 实现的 shell 管理工具,因此和 ansible 之间很明显的区别就是:无需大量的环境依赖,一个二进制文件即可。 这个特点是吸引我最主要的原因。
每个工具都有其强项和局限,也不是适合每个场景。和很多重量级任务管理器不同,这个工具主打的就是轻量,因此没有 UI 界面、没有状态存储、没有大量的预置组件。
想实现的功能
会调研这个工具,源自于我希望把一些安装系统工具的脚本进行整合,比如 开一台机器、安装一套k8s 环境、部署一些基本服务、结果发送通知到xxx。 在常用的方案中,可能会直接采用 ansible playbook 的方式,每个大的任务都是一个 role。
但是嘞,不太想用 ansible,就希望这些任务都是简单的 script ,一句一个,复杂的就封装成脚本文件,这样看起来很清晰。
下面实现这几个简单的封装:
- 在机器上安装常用的命令:
kubectl
、devspace
、helm
、jq
、kubealias
、deployer
,helm repo add xxx
- 在机器上安装精简版的常用命令:
kubectl
、helm
、kubealias
、deployer
、helm repo add xxx
- offline 模式部署某个版本,并发送通知
- charts 模式部署某个版本,并发送通知
实际使用下来,发现 task 作为一个统一的命令集入口是非常不错的,比自己写一堆的 shell 解析 flag 来得方便多了。
比如,我做了一个 tools 的转存、上传、下载的工具,三个脚本是分开写的,可以单独运行,但同时,使用 taskfile 分别定义 3 个子任务,以前需要使用: python3 savetools.py
、python3 uploadtools.py
等这样运行的,现在直接可以用: task savetools
、 task uploadtools
就完成了。在可理解性上高了不少。
ps: 因为 taskfile 在 子 task 调用上的逻辑不是很合我心意,于是 fork 了一份改了一下,详情可以参见: https://github.com/iamlongalong/task
如何让🤖处理这些task
task 的作用,是封装一些相对复杂的操作,让调用的人无需关心更多的细节。当我们有了这些封装之后,就可以把一个 task 的运行变成 几个特定的参数。这样,也就可以更简单地让🤖 对我们的意图进行拆解,并执行对应的操作。
例如,task deploy:charts 这个任务,需要两个参数: VERSION 和 ENV ,前者标识要部署的版本,后者表示要部署的环境。这往往是调用方最关心的两个参数,而其它的就可以使用默认参数的方式固化下来。
这里有一个问题,如何让 bot 具备执行 task 的能力?从两个方面来思考这个问题: ① 实现层面,如何让 bot 执行 task ② 管理层面,如何管理 bot 的 task 权限
task 如何执行
和 ansible 的 ssh 远程执行不同,taskfile 是在本地执行的,所以就涉及到 taskfile 的分发问题。
参考 gitlab 的做法,每次生成一个 job 的时候,都会生成一系列 token,然后在各个执行机构上,通过这些 token 去获取相关的物料。用 token 做权限管理,就会涉及到 client-server 的开发,显然复杂度就会高很多。
如果 taskfile 本身是开放的,任务的触发是通过一个 ssh 命令实现,这样能够实现松耦合,但另一方面,就会缺少对 agent 的监控能力。
目前还是先走简约实现的方案,由一个 ssh 命令实现。
如何实现
- 机器的管理能力
- ssh 的执行能力
机器的管理,提供一个 task 用于注册到一个机器配置中心。
配置中心使用 golang 实现,提供一个 http 接口,用于获取 id_rsa.pub;提供一个接口用于配置当前机器的 别名。(配置时,会使用 ssh 调用查看是否能够建连)
task 的执行分发能力,提供一个 http 接口,两个参数: NODE_NAME (机器名)、task cmd (任务执行的相关参数)。 以及一个 token,用于校验是否有权限。
目前这个 token 先用 jwt 颁发一个一年的,固定这个 token,之后看怎么做更体系性的权限系统。
对于 🤖 怎么操作
- 接收用户传来的消息
- 解析消息的类型
- 解析消息的参数
- 带特定 token 调用接口
🤔
这个项目先这样弄吧,虽然到处都是漏洞,但仅限于开发环境一些简单场景的使用,先不做过多的设计了,跑起来看看有没有迭代的价值~
结果
- 交互过程
- task 自定义的回调通知
大概先这样,比较简单的玩一下,实现这个基础的能力。
虽然和目标中:”让 LLM 去整理出参数” 还有很大差距,但好在整套机制建立起来了,后面再看有没有必要继续进行下去吧。
具体的 runtask 脚本可以查看这里: https://static.longalong.cn/scripts/runtask.sh
Wisdom, compassion, and courage are the three universally recognized moral qualities of men.
— Confucius
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!