ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

tentakel:基于SSH的轻量集群批量执行工具与巡检实践

tentakel:基于SSH的轻量集群批量执行工具与巡检实践 简介Tentakel是一款面向系统管理员和运维工程师的集群批量操作工具能够对成百上千个分布式节点并发执行命令、脚本和自动化任务适用于服务器批量更新、软件部署、系统升级、日志收集等场景显著降低大规模集群运维的时间成本与误操作风险。资源包共110个文件体积仅547KB以70个Python脚本为核心目录结构清晰既包含可读的源码实现也提供配置示例、Markdown及文本说明、Makefile与打包部署文件配合man帮助页、变更记录等完整参考资料便于阅读、二次开发或快速部署。目前已有713人学习下载。借助该包可深入了解Tentakel的并发调度、SSH密钥认证、任务监控与错误报告、弹性配置及跨平台兼容等核心机制并通过附带的配置模板、自动化工作流示例结合自定义调度策略与权限控制快速搭建适合自身集群环境的运维平台从而提升批量操作效率、可审计性与系统稳定性。1. tentakel 是什么一台机器的命令几十台机器一起跑tentakel 这个名字直译过来是“触手”它要解决的问题就是让你一只手同时伸进几十台机器。它是一个轻量的集群批量执行工具不装 agent、不写 playbook本质上是在本机把多个 ssh 会话并行组织起来把同一条命令撒到一组机器上再统一收结果。第一次接手一批机器时可以用它快速摸底日常巡检时可以用它并行采集状态临时要改配置、看日志也不用为一个动作去引入一套配置管理平台。它适合机器规模在几十台这个量级、操作以临时性和探索性为主的团队也适合已经在用 ansible 但嫌太重、想保留一套轻量通道的熟手。下面内容从安装和最小配置讲起逐步拆到分组策略、执行节奏、常见坑最后落成一套可以直接用的巡检闭环。2. 把 tentakel 装起来并跑通第一组命令从最小配置文件开始2.1 安装前先搞清楚依赖它只是 ssh 的调度器tentakel 最容易被误解的一点是大家以为它和被管理机器之间有某种协议或服务。实际上它什么服务都不需要你只要保证本机能用 ssh 连上目标机器tentakel 就能工作。它做的事就是把配置文件里的一组主机名、和你给的命令翻译成一批并行发起的 ssh 调用然后把各自的输出收回来。所以被管理机器上唯一的依赖是 sshd 和你的登录账号这也就是“无 agent 集群工具”这个说法的来源。安装本身不复杂。先在自己的发行版包管理器里搜一下apt 系用apt-cache search tentakelrpm 系用yum search tentakel只要软件源里有直接装就是。如果源里没有也不用着急tentakel 的依赖非常少源码方式安装也是常规三步# 把你拿到的源码包解压后进入目录按常规流程编译安装 make make test sudo make install逻辑说明make负责生成可执行文件和默认配置模板make test会在本机跑一遍最小用例确认没有环境问题后再make install。参数说明如果你的环境没有 sudo 权限可以只解压后把可执行文件放到个人目录再把 PATH 指过去不影响使用。安装后先确认版本tentakel --version tentakel --help第一行确认装上了第二行看手头版本支持哪些参数。tentakel 不同发行版的打包会有细微差异后面的命令如果和你本机对不上以--help的输出为准。2.2 第一个配置文件一个组、两( 三)台机器tentakel 的默认配置文件是用户家目录下的~/.tentakelrc系统级配置通常在/etc/tentakelrc或/etc/tentakel/下具体路径看安装方式。对个人使用来说写~/.tentakelrc就够。格式非常简单方括号是组名下面每行是一个主机名cat ~/.tentakelrc EOF [test] web01.internal web02.internal EOF逻辑说明[test]定义了一个叫 test 的组组里有两台主机web01.internal和web02.internal。tentakel 看到这个配置后会把后面你给的命令并行发到这两台机器上。参数说明主机名可以是短主机名也可以是完整域名或 IP关键是你的 ssh 能直接解析并连接它行首#开头的是注释会被忽略。这里有个很容易忽略的点tentakel 并不会帮你做 ssh 免密配置所以第一次跑之前先手动确认一下ssh web01.internal hostname如果这一步需要输密码说明你后面跑 tentakel 也会被密码卡住。先把本机到目标机器的免密登录配好再继续往下走。2.3 跑第一组命令并看懂输出配置文件写好、ssh 通路确认后第一组命令就可以发了tentakel test uptimetentakel 会并行连接 test 组里的两台机器在各自终端执行uptime然后把输出收回来。输出里一般会带主机名标识以便区分结果来自哪台机器具体样式取决于版本和是否开启了 verbose。如果你手头版本支持-v参数可以打开 verbose 看更详细的执行状态不支持的版本也不用担心直接看输出内容即可。tentakel -v test uptime逻辑说明test是配置里的组名后面跟的字符串是远程要执行的命令。整条命令会被原样交给远程 shell所以带引号这个习惯要养成避免本机 shell 先把命令拆了。参数说明-v是 verbose 的简写它会把每台机器的连接状态、命令执行状态一并打出来排查问题时很有用如果你的版本不支持-v运行tentakel --help能看到这个参数到底叫什么。跑通这一条tentakel 的核心链路就通了。接下来要解决的是另一个问题机器一多、组一杂配置文件该怎么组织。3. 分组配置再深入按用途拆组、按环境隔离、先查再跑3.1 三种常用的静态分组方式tentakel 的分组模型很朴素一个组名对应一组主机名命令行里给组名命令就会发到该组的所有机器上。实际使用中分组维度通常有三个按角色拆、按环境拆、按批次拆。按角色拆是最常见的比如把 Web 服务器放一个组、数据库放一个组cat ~/.tentakelrc EOF [global] ssh_command ssh -o ConnectTimeout5 -o BatchModeyes [webservers] web01.internal web02.internal web03.internal [dbservers] db01.internal db02.internal [all] web01.internal web02.internal web03.internal db01.internal db02.internal EOF逻辑说明[global]段是全局参数ssh_command指定 tentakel 调用 ssh 时用的命令模板。这里给 ssh 加了两个参数ConnectTimeout5让连接阶段 5 秒超时BatchModeyes禁止交互式输入密码、失败就立刻返回避免批量执行时挂在密码输入上。参数说明BatchModeyes不适用于你还没配好免密的场景它只是让故障快速暴露不是让故障消失。按环境拆则是把生产、测试、演练机器分开维护避免误操作范围扩大。按批次拆适合你临时要处理一批特定机器的情况比如升级只覆盖部分机器时单独建一个临时组用完就删。这三种拆法可以叠加角色组管职责环境组管边界批次组管变化。3.2 用不同配置文件隔离生产与测试环境如果所有环境写在一个~/.tentakelrc里最大的风险就是手抖想对 test 组执行命令结果组名敲成了 prod。tentakel 支持通过-c参数指定配置文件所以更稳妥的做法是为每个环境维护一套独立配置。cat ~/.tentakelrc.prod EOF [app] app01.corp.internal app02.corp.internal EOFcat ~/.tentakelrc.staging EOF [app] stg01.corp.internal stg02.corp.internal EOF# 需要操作哪个环境就显式指名配置文件避免默认配置里混着多个环境 tentakel -c ~/.tentakelrc.prod app uptime tentakel -c ~/.tentakelrc.staging app uptime逻辑说明-c接受一个配置文件路径tentakel 启动时读这个文件而不是默认的~/.tentakelrc。这样一来生产配置和测试配置物理隔离命令行里也能一眼看出当前操作的是哪个环境。参数说明-c的具体拼写如果在你本机版本里不是这个运行tentakel --help确认一下但绝大多数打包版本都支持这个参数。这个习惯很重要。我见过不止一次有人在测试环境执行命令时因为默认配置里同时存在 prod 和 test 两组组名写错一位就发到了生产机器上。用配置文件把环境隔开是从源头降低批量操作风险的手段。3.3 执行前先检查分组别让同一台机器跑两遍配置文件用久了主机名会重复。比如 all 组里手动维护了全量机器webservers 和 dbservers 里也有同样的主机一旦你在命令行里同时指定多个组同一台机器可能被执行两次这在执行重启、停服务这类操作时就是事故。所以我的习惯是改完配置先检查再跑命令。# 列出配置里所有组名 awk -F[][] /^\[/{print $2} ~/.tentakelrc这个命令把配置里所有[...]形式的行截出来显示当前有哪些组。接着检查主机有没有重复# 统计所有主机名出现次数次数大于 1 就说明有重复 grep -v ^# ~/.tentakelrc | grep -v ^\[ | grep -v ^$ | sort | uniq -c | sort -rn逻辑说明先把注释、组名行和空行全部过滤掉剩下的都是主机名然后排序、去重统计最后按出现次数倒序排列。如果看到某个主机名前面的数字大于 1就说明它在配置里出现了多次。参数说明uniq -c是在排序基础上统计连续重复行所以必须先sortsort -rn让重复次数最多的排在最上面一眼就能看到问题主机。在第 3 章的最后留一个建议如果 tentakel 的版本支持在组里引用其他组比如[all:include]这种写法优先用引用而不是手动把主机再抄一遍。手动维护的重复列表迟早会在一次变更中漏掉某台机器。手头版本不支持也没关系那就靠上面这个检查命令兜底。4. 执行节奏与输出处理并行执行怎么不翻车4.1 先懂 tentakel 的并行模型再决定要不要拆组tentakel 默认是并行执行意思是它不会等第一台机器跑完才开始第二台而是把所有目标机器的 ssh 会话同时拉起谁先出结果谁先显示。这个设计在机器少的时候非常爽二十台机器同时执行几秒内全部返回。但机器一多、任务一重并行反而可能翻车所有机器同时执行高负载命令监控会告警同时重启一个服务下游会出现大量连接错误几十台机器同时涌回输出终端直接花屏。所以真正的工程问题不是“怎么让它并行”而是“怎么按自己的节奏控制并行”。在不确定手头版本是否提供并发数限制参数的情况下我一般用分组轮询来控制做法是把一个大组按角色拆成几个小组然后写循环逐组执行# 按 webservers - appservers - dbservers 的顺序逐批执行每批内部并行 for g in webservers appservers dbservers; do echo ${g} tentakel $g uptime done逻辑说明循环体里每次只处理一个组组内机器并行组与组之间串行。这样既保留 tentakel 天然并行的优点又不会让全量机器在同一秒内被命令击中。参数说明${g}是循环变量tentakel $g uptime等价于依次执行tentakel webservers uptime、tentakel appservers uptime、tentakel dbservers uptime。如果手头版本本身支持并发数参数也可以直接传参但我这里给的拆组方案不依赖任何特殊参数在所有版本上都成立。4.2 把超时和密钥行为统一交给 sshtentakel 本身不负责网络超时它把连接这件事交给了 ssh。所以你会发现有时候命令发出去了终端一直没反应也不报错——大概率是某台机器的 ssh 连接卡在了 TCP 层等待超时。解决思路不是在 tentakel 层面找开关而是把超时和交互行为在 ssh 层面统一设置。# 在 ~/.tentakelrc 的 global 段统一给 ssh 传参 [global] ssh_command ssh -o ConnectTimeout5 -o BatchModeyes这个配置的意思是tentakel 每次调用 ssh 时都会自动带上这两个参数。ConnectTimeout5让连接阶段 5 秒超时适用于大多数内网场景BatchModeyes让 ssh 放弃交互式密码输入一旦密钥失效直接失败返回。二者合在一起的效果是批量执行时不会再有一台机器的连接问题拖住整个批次最多 5 秒后报错你立刻知道哪台有问题。参数说明ConnectTimeout的值根据网络情况调整跨机房、跨地域会需要更大值同机房 3 到 5 秒足够BatchModeyes对已经配好免密的机器没有副作用但如果你还在排查密钥问题先单独手动 ssh 确认不要开着 BatchMode 去猜原因。4.3 给命令本身加超时防止远程命令永久挂住连接超时管的是“连不上”的情况但还有一种更隐蔽的场景连接没问题命令在远程机器上卡住了比如某个自动化脚本在等一个永远等不到的锁。这种情况下即使 ssh 连接正常命令也不会返回。处理办法是在命令前包一层timeout# 每台机器上的命令最多执行 15 秒超时则返回非零状态 tentakel all timeout 15 sh -c hostname; uptime; df -h / | tail -1逻辑说明timeout 15是 Linux 自带的命令超时工具15 秒到了就强制终止后面的命令。sh -c ...把多条命令包成一个整体交给远程 shell 执行避免分号在逐层传参时被拆坏。参数说明15 秒这个值要看你命令的预期耗时采集系统信息 15 秒足够跑备份、部署这类长任务就别用这么小的值否则会把正常命令误杀。这一步和 4.2 的ConnectTimeout是两层防护一个管连接建立一个管命令执行。两层都设好批量执行才不容易被一两台异常机器拖住。5. 常见问题与避坑五条批量执行的血泪经验5.1 host key 校验把整个批次卡死现象第一次在新机器上跑 tentakel命令发出去后长时间无响应既不报错也不返回。看进程发现 ssh 进程都停在那里等输入。原因目标机器的 host key 不在本机known_hosts里ssh 默认在交互模式下会询问是否信任BatchMode 没开的时候就直接挂住等待。tentakel 不会替你回答这个问题于是整个批次卡死。解决批量操作前先把目标机器公钥收进known_hosts或者在 ssh 参数里放开对新主机校验的策略。# 把目标主机公钥一次性写入 known_hosts避免批量时卡在确认 ssh-keyscan -T 5 web01.internal web02.internal db01.internal ~/.ssh/known_hosts逻辑说明ssh-keyscan主动连接目标机器并获取 host key-T 5是单个主机的连接超时避免某台机器连不上时卡很久。追加写入known_hosts后就相当于提前回答了 ssh 的信任问题。注意这里写入的是目标机器的 host key不是你的登录凭据不存在泄露密码的风险。5.2 输出混在一起事后找不到是哪台机器现象几十台机器并行执行终端刷出一大堆日志行没有主机标识事后想找某台机器的输出得靠猜。原因并行执行时各台机器的输出是陆续返回的如果命令本身没有打印主机名肉眼几乎无法分辨哪行属于哪台。解决在命令开头显式打印主机名标记收尾时按标记切分。推荐这样写tentakel all echo HOST_START; hostname; echo HOST_END; uptime; df -h / | tail -1逻辑说明echo HOST_START是一个机器可识别的分隔标记hostname打印当前主机名HOST_END结束标记。之后无论是肉眼查看还是脚本切分都能准确把输出归到具体机器。参数说明标记字符串不要用太通用的词比如------这种日志里本身可能出现用HOST_START这种带语义、不易撞车的标记更稳妥。5.3 配置文件里一个空格引发的“主机不存在”现象配置改完后运行 tentakel报错说某台主机无法解析或者命令被莫名其妙地分发到了错误的目标。原因主机行末尾多了空格或制表符tentakel 解析时把空格后的内容也当成了主机名的一部分或者注释符号没放在行首在主机行后面跟了注释文本。这两种情况都不会在配置加载时立即报错但执行时就会出问题。解决统一配置文件格式主机行只写主机名注释单独一行改完配置后用检查命令过滤出实际参与执行的主机清单。# 把配置里真正会被当成主机名的行全部打出来人工扫一遍 grep -v ^# ~/.tentakelrc | grep -v ^\[ | grep -v ^$逻辑说明过滤掉注释、组名和空行后剩下的每一行就是 tentakel 会当作主机名的内容。如果这里出现带空格的行或者明显不是主机名的字符串就是配置解析的根源。参数说明这个命令只是检查不修改配置发现问题后直接用编辑器修掉行尾空格不要试图在配置文件里用引号包主机名tentakel 的解析器不认那套。5.4 免密登录偶尔失效BatchMode 是最后的后悔药现象某天批量执行时几台机器突然开始提示输入密码终端切换不了输入框整个批次像被冻住一样强杀后那几台机器也没有返回任何输出。原因ssh-agent 里密钥没有加载或者目标机器的authorized_keys被动过ssh 回退到了密码认证。tentakel 不会感知到这一点它会继续等。解决平时就打开BatchModeyes让认证失败快速返回错误而不是无声等待同时养成批量操作前先验证密钥加载的习惯。# 检查当前 ssh-agent 里已加载的密钥数量 ssh-add -l如果输出显示The agent has no identities说明本机没加载密钥tentakel 自然也拿不到免密通道。这不是玄学基本上每次批量免密失效都能追溯到 ssh-agent 或目标机authorized_keys其中一环。BatchModeyes的作用是把这个故障从“挂起”变成“快速报错”你会在几秒内看到哪台机器认证失败而不是等一根看不到头的进度条。5.5 sudo 和别名让同一命令在不同机器上结果不同现象同一个命令在 A 机器上正常在 B 机器上报sudo: no tty present在 C 机器上跑出来的结果格式不一样。原因远程机器默认不分配伪终端sudo 在无 tty 环境下默认拒绝另外各机器的 shell 别名、默认 PATH 不同命令解释结果自然不同。这三类问题叠加在一起会出现“命令看着一样、执行结果各不相同”的诡异局面。解决需要 sudo 时给 ssh 加-tt强制分配伪终端命令内部用sudo -n禁止交互式输密码避免在批量命令里依赖别名或相对路径。# 配置里给 ssh 加 -tt命令里用 sudo -n ssh_command ssh -tt -o ConnectTimeout5 -o BatchModeyestentakel all sudo -n systemctl status nginx逻辑说明-tt强制分配伪终端满足 sudo 对 tty 的依赖sudo -n表示非交互模式如果 sudo 需要密码就立刻失败不会卡住。参数说明如果有些机器不需要 sudo 而有些需要建议拆成两个组分别执行而不是在同一组里混合 sudo 和非 sudo 命令这样失败的范围更可控。6. 进阶让 tentakel 成为日常巡检的第一入口6.1 巡检脚本模板带主机标记、可落盘、可核对tentakel 的价值体现在单点命令真正产生效率的是把它封装进日常巡检流程。下面是我一直在用的一个模板它解决了三件事结果按主机切分、落到独立文件便于排查、执行后能核对主机数量。#!/usr/bin/env bash # 巡检脚本tentakel 作为入口采集结果并按主机归档 set -uo pipefail GROUP${1:-all} TS$(date %Y%m%d_%H%M%S) DIR/tmp/ops_${TS} mkdir -p $DIR tentakel $GROUP \ echo HOST_START; hostname; echo HOST_END; uptime; df -h / | tail -1; free -m | head -2 \ $DIR/raw.log 21 awk /HOST_START/ {getline host; next} /HOST_END/ {print host; next} {print host | $0} $DIR/raw.log $DIR/parsed.log online$(grep -c HOST_START $DIR/raw.log) parsed$(grep -c ^HOSTNAME: $DIR/parsed.log) echo reachable hosts: ${online}, parsed: ${parsed}逻辑说明脚本先把 tentakel 原始输出落盘到带时间戳的目录然后用 awk 按HOST_START和HOST_END标记切分把后续每行输出都打上主机名前缀。最后统计在线主机数和解析出的主机数两者不一致就说明有机器没跑完或有输出被截断。参数说明set -uo pipefail防止未定义变量和管道错误被静默吞掉${1:-all}表示脚本第一个参数传入组名不传默认用 all 组awk 里的getline host取到的是 hostname 命令的输出行通常形如HOSTNAME: web01.internal所以后面用^HOSTNAME:匹配。6.2 用 SSH 证书机制免去逐台部署公钥机器数量少时ssh-copy-id逐台部署公钥可以接受但机器一多逐台部署本身就是一件该被自动化的事。最可靠的批量免密方案是用 SSH 证书机制本机持有一个 CA 签发的用户证书目标机器信任该 CA每次登录自动通过验证不需要在每台机器上维护公钥列表。tentakel 不需要感知证书的存在它只负责调 ssh认证逻辑完全由 ssh 层接管。这个方案的好处是换密钥、加机器都不用在目标机器上动手适合跟 tentakel 配合做常态化巡检。6.3 跑完怎么验证数量核对与失败重跑巡检脚本最后的数字核对就是验证手段。reachable hosts是 tentakel 实际连接到的主机数如果这个数少于配置里的主机总数说明有机器 ssh 不通或认证失败去raw.log里搜错误信息即可定位。失败重跑时不需要重新跑全量把失败的主机单独建一个临时组或直接用-c指定一个只含失败主机的小配置文件补跑一次即可。我现在的习惯是tentakel 只负责把命令送到、把结果带回来命令靠标记切分故障靠数量核对免密靠证书机制不靠碰运气。把这三件事想清楚之后批量操作就不再是提心吊胆的“一把梭”而是一套随时可以解释、可以复盘、可以重跑的流程。希望帮到你。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表