不用装Agent,SSH直连搞定服务器监控

不用装Agent,SSH直连搞定服务器监控

几台宿主机跑着几十个 Docker 容器,怎么用一台服务器把它们全盯住?SSH + 定时任务 + 告警,不装 Agent,不买 Zabbix。


一、痛点:谁在看服务器?

我们公司的服务器上跑了几十个 Docker 容器------Nginx、MySQL、Redis、微服务......运维同事最怕的就是:服务挂了没人知道,等用户投诉了才发现。

之前的做法是手动 SSH 上去 top 看一眼,CPU 高不高、内存够不够、磁盘满了没。一台还好,几台轮着查就很烦了。更别说 Docker 容器------谁知道哪个容器偷偷把内存吃光了。

所以就有了这个需求:用一台服务器,定时采集所有机器的指标,异常自动告警。


二、整体思路

不复杂,就一条链路:

markdown 复制代码
定时任务(5分钟一次)
  → SSH 连接目标主机
    → 执行采集命令(Windows用PowerShell,Linux用shell)
      → 解析结果入库
        → 前端实时展示 + 告警通知

不用在每台被监控的机器上装 Agent,就靠 SSH 直连。轻量、无侵入。


三、核心实现

3.1 跨平台 SSH 采集

SSH 连接用 JSch(Java 的 SSH 客户端库),不用装额外依赖:

java 复制代码
JSch jsch = new JSch();
Session session = jsch.getSession(account, ip, 22);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect();

连上之后执行采集命令。这里要区分操作系统------Windows 和 Linux 命令完全不一样

Windows 用 PowerShell + WMI:

powershell 复制代码
$cpu = (Get-WmiObject Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average
$os  = Get-WmiObject Win32_OperatingSystem
$mem = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / $os.TotalVisibleMemorySize * 100, 1)
$disk = Get-WmiObject Win32_LogicalDisk -Filter 'DeviceID=''C:'''
if ($disk) { $du = [math]::Round(($disk.Size - $disk.FreeSpace) / $disk.Size * 100, 1) } else { $du = 0 }
echo CPU=$cpu; echo MEM=$mem; echo DISK=$du

关键细节:多核 CPU 必须用 Measure-Object -Average 算均值,否则拿到的不是整体使用率。

Linux 用 shell 命令:

bash 复制代码
top -bn1 | grep 'Cpu(s)' | awk '{printf "CPU=%.1f\n",100-$8}'
free -m | awk '/Mem:/{printf "MEM=%.1f\n",$3/$2*100}'
df -h / | awk 'NR==2{gsub(/%/,"");print "DISK="$5}'

不管是 Windows 还是 Linux,输出统一都是 CPU=xx MEM=xx DISK=xx 这种格式,Java 端解析就很方便了。

3.2 定时任务

用若依自带的定时任务框架,每 5 分钟执行一次:

java 复制代码
@Component("kvmCollectTask")
public class KvmCollectTask {
    @Autowired
    private KvmCollectorService kvmCollectorService;

    /** 每5分钟采集一次 */
    public void collectMetrics() {
        kvmCollectorService.collectAllHosts();
    }
}

采集方法里遍历所有主机,逐个 SSH 采集,异常的主机自动标记为离线。

批量采集的时候注意: 接口里要开独立线程,不让前端点完按钮一直转圈:

java 复制代码
new Thread(() -> kvmCollectorService.collectAllHosts(), "kvm-batch-collect").start();

3.3 告警系统

采集完不能只存起来,得在指标异常的时候主动通知

三级阈值设计:

级别 条件 处理
HEALTHY CPU/内存/磁盘 全部 < 80% 正常
WARNING 任一 ≥ 80% 触发预警
CRITICAL 任一 ≥ 90% 触发严重告警

告警去重是关键。 同一个主机的 CPU 一直 95%,不能每次采集都发一条告警,不然五分钟一条,一天就是 288 条。

dedupKey 做去重:

java 复制代码
String dedupKey = "HOST_" + host.getId() + "_CPU";
KvmAlert existing = alertMapper.selectByDedupKey(dedupKey);
if (existing != null) {
    // 已有同类告警,不重复发
    return;
}
// 新告警,插入
alertMapper.insertKvmAlert(alert);

自动恢复: 指标降回正常范围后,不用人工处理,代码自动把告警状态改为 RESOLVED:

java 复制代码
if (val < warn) {
    existing.setStatus("RESOLVED");
    existing.setResolutionNotes("指标恢复正常,自动解决");
    alertMapper.updateKvmAlert(existing);
}

3.4 Docker 容器监控

宿主机指标看了还不够,上面的 Docker 容器也得监控。直接用 docker stats --no-stream 拿实时数据:

bash 复制代码
docker stats --no-stream

输出大概长这样:

erlang 复制代码
CONTAINER ID   NAME          CPU %   MEM USAGE / LIMIT   MEM %   NET I/O       BLOCK I/O
abc123def456   nginx         1.50%   120MiB / 2GiB       5.86%   1.2MB / 0.8MB  0B / 0B
def456abc789   my-app        23.40%  512MiB / 4GiB       12.50%  50MB / 30MB    10MB / 5MB

Java 端解析 docker stats 的输出,按列拆分取 CPU%、MEM%、网络和磁盘 IO。

Windows 踩坑: Docker Desktop 在 Windows 上,SSH 直接执行 docker 命令会找不到,因为非交互式 SSH 不加载用户 PATH。加 cmd /c 前缀解决:

java 复制代码
String wrap = isWin ? "cmd /c " : "";
String cmd = wrap + "docker stats --no-stream";

3.5 一个大坑:Docker 容器回连宿主机

这个问题卡了我半天。

场景是这样的:监控服务本身跑在 Docker 容器里,要 SSH 去采集宿主机的指标。宿主机 IP 是 192.168.2.42,容器里直接 ssh 192.168.2.42 连不上。

原因是 Windows Docker Desktop 的网络隔离------容器不能通过宿主机的外网 IP 回连。

解决办法:先试原 IP,失败后自动回退到 host.docker.internal

java 复制代码
for (String targetIp : new String[]{ip, "host.docker.internal"}) {
    try {
        return sshCollectRaw(targetIp, account, password, osType);
    } catch (Exception e) {
        log.debug("SSH采集 [{}] 失败,尝试下一个...", targetIp);
    }
}
throw new RuntimeException("SSH采集失败: 所有地址均无法连接");

host.docker.internal 是 Docker Desktop 提供的特殊域名,容器里访问它会解析到宿主机的内部地址(192.168.65.254),完美绕过网络隔离。


四、前端展示

后端数据有了,前端做成监控页面:

  • 指标卡片:CPU / 内存 / 磁盘使用率,红黄绿三色标识
  • 告警列表:当前活跃告警 + 已恢复历史,一目了然
  • Docker 容器列表:每个容器的 CPU/内存/网络 IO,实时更新
  • 3 秒自动刷新:前端轮询后端接口,不用手动刷新页面


五、总结

这套方案的核心思想就一句话:不装 Agent,SSH 直连,定时采集,异常告警。

相比 Zabbix、Prometheus 这些重型监控系统,优势是:

传统监控 这套方案
部署 每台机器装 Agent 零侵入,SSH 即用
配置 复杂的 yaml 配置文件 填 IP、账号、密码就行
学习成本 会 SSH 就会用
适用规模 几十到上万个节点 几台到几十台

一个中小企业、一个运维外包团队、一台服务器------够用了。


同系列文章:

下一篇:Docker 部署避坑指南,敬请关注。

相关推荐
snow@li1 小时前
深入理解内核与操作系统的关系
运维·服务器·microsoft
laoli_coding2 小时前
系统部署之部署方式
服务器
无足鸟ICT3 小时前
【RHCA+】管道符
linux·运维·服务器
老约家的可汗3 小时前
Linux的库制作和原理
linux·运维·服务器
玖玥拾4 小时前
C# 语言进阶(十四)Unity UI界面开发 + 网络消息联动
服务器·开发语言·网络·ui·unity·c#·游戏引擎
巴啦啦小魔仙变身5 小时前
SIGINT = Signal Interrupte
linux·服务器·python
不会C语言的男孩5 小时前
TCP通信可视化工具,含下载地址
服务器·网络·安全
TDengine (老段)6 小时前
TDengine SMA 索引 — 块级/文件级统计索引
android·大数据·服务器·数据库·人工智能·时序数据库·tdengine
玖玥拾6 小时前
C# 语言进阶(十三)网络 DLL 库分层设计
服务器·开发语言·网络·网络协议·c#