任务流管理工具

背景

当我们经常和机器打交道时,就会有大量的 任务 需要管理,比如一个小的 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 ,一句一个,复杂的就封装成脚本文件,这样看起来很清晰。

下面实现这几个简单的封装:

  1. 在机器上安装常用的命令: kubectldevspacehelmjqkubealiasdeployerhelm repo add xxx
  2. 在机器上安装精简版的常用命令: kubectlhelmkubealiasdeployerhelm repo add xxx
  3. offline 模式部署某个版本,并发送通知
  4. charts 模式部署某个版本,并发送通知

实际使用下来,发现 task 作为一个统一的命令集入口是非常不错的,比自己写一堆的 shell 解析 flag 来得方便多了。

比如,我做了一个 tools 的转存、上传、下载的工具,三个脚本是分开写的,可以单独运行,但同时,使用 taskfile 分别定义 3 个子任务,以前需要使用: python3 savetools.pypython3 uploadtools.py 等这样运行的,现在直接可以用: task savetoolstask 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 调用接口

🤔

这个项目先这样弄吧,虽然到处都是漏洞,但仅限于开发环境一些简单场景的使用,先不做过多的设计了,跑起来看看有没有迭代的价值~

结果

  1. 交互过程

  1. 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 协议 ,转载请注明出处!