脚本如何检测iSCSI目标是否正常:从基础到高可用监控实战指南
目录导读
-
iSCSI目标检测的重要性与场景分析

- 为什么需要定期检测iSCSI目标状态?
- 常见故障场景:目标离线、路径失效、认证失败
-
核心检测机制:从ICMP到SCSI指令
- Ping测试的局限性
- 使用
iscsiadm命令查询会话与目标状态 - 基于
sg_inq与dd的深度读写检测
-
自动化监控脚本编写实战
- 基础Shell脚本:多目标循环检测
- 高级功能:邮件告警、日志轮转、异常恢复自动重连
- Python脚本方案:利用
python-iscsi库实现跨平台监控
-
常见问题与排查指南
- 检测结果异常时的排查步骤
- 为什么目标显示连接但IO超时?
- 如何区分目标故障还是网络抖动?
-
总结与最佳实践
- 监控频率与资源开销的平衡
- 结合Nagios/Zabbix的集成方案
iSCSI目标检测的重要性与场景分析
为什么需要定期检测iSCSI目标状态?
iSCSI(Internet Small Computer System Interface)是企业级存储网络中的核心协议,通过IP网络将块设备暴露给客户端,一旦iSCSI目标(Target)宕机或路径异常,依赖该存储的数据库、虚拟化平台或容器化应用可能直接IO挂起,导致服务雪崩,自动化检测脚本是运维体系的必备组件。
常见故障场景
| 故障类型 | 表现 | 影响范围 |
|---|---|---|
| 目标离线 | 节点宕机、iSCSI服务停止 | 所有连接的Initiator无法读写 |
| 路径失效 | 网络中断、多路径(MPIO)部分链路故障 | IO性能下降或单点故障 |
| 认证失败 | CHAP密码过期、用户权限变更 | 连接被拒绝,无法挂载 |
| 目标LUN隐藏 | 存储端策略变更,LUN被取消映射 | 特定主机数据不可见 |
问答环节
Q:用Ping检测目标IP正常,但iSCSI无法IO,这合理吗?
A:绝对合理,Ping只测试网络层连通性,不验证iSCSI服务进程(如tgt、LIO)是否存活,也无法检查iSCSI会话层状态,许多案例显示,目标主机的IP可达,但iSCSI服务已崩溃(如内存溢出),此时必须通过SCSI命令级别的检测才能发现问题。
核心检测机制:从ICMP到SCSI指令
1 Ping测试的局限性(仅作为预热检测)
Ping可作为前置快速检测,但绝不能单独使用,一个更完整的检测链是:
ping -c 3 -W 2 $TARGET_IP > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "WARNING: ICMP to target failed, but iSCSI might still work (check later)"
fi
2 利用iscsiadm检测会话与设备状态
iSCSI Initiator端的核心工具是iscsiadm,它能直接查询会话状态和登录信息:
检测会话是否存活:
# 列出所有活跃会话
iscsiadm -m session -P 3 | grep "iSCSI Session State" | awk '{print $4}'
# 输出应为:STATE: LOGGED_IN 或 STATE: ACTIVE
检测具体目标连接状态:
# 查看指定目标的详细信息 iscsiadm -m session -r $SESSION_ID -o show | grep "Current Portal" # 如果终端不可达,会出现 "Connection refused" 或 "timeout"
3 深度检测:SCSI命令级读写验证
真正可靠的检测应直接向目标LUN发送SCSI指令,例如用sg_inq读取设备标准查询数据:
# 假设LUN设备为 /dev/sdb
sg_inq /dev/sdb > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "CRITICAL: SCSI INQUIRY failed - LUN may be dead or access denied"
fi
还可以通过dd进行小数据块写测试(注意破坏风险,只适用测试LUN):
dd if=/dev/zero of=/dev/sdb bs=512 count=1 oflag=direct 2>&1 # 返回非零即表示写入失败
重要提示: 生产环境的写测试应使用sg_pt安全写入,或者只在专用测试LUN上执行。
自动化监控脚本编写实战
1 基础Shell脚本:多目标循环检测
以下脚本检测所有已登录的iSCSI目标,并输出状态码:
#!/bin/bash
# iscsi_health_check.sh - 检测iSCSI目标可用性
LOGFILE="/var/log/iscsi_health.log"
ALERT_EMAIL="admin@example.com"
# 获取所有会话ID
sessions=$(iscsiadm -m session | awk '{print $2}' | sed 's/\[//;s/\]//')
for sid in $sessions; do
# 检测会话状态
state=$(iscsiadm -m session -r $sid -P 3 | grep "State:" | awk '{print $2}')
if [ "$state" != "LOGGED_IN" ]; then
echo "$(date) - SESSION $sid STATE IS $state" >> $LOGFILE
echo "Session $sid is DOWN" | mail -s "iSCSI Alert" $ALERT_EMAIL
fi
# 进一步检测LUN的SCSI命令响应
device=$(iscsiadm -m session -r $sid -P 3 | grep "Attached scsi disk" | awk '{print $4}')
if [ -n "$device" ]; then
sg_inq /dev/$device > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "$(date) - DEVICE $device SCSI INQUIRY FAILED" >> $LOGFILE
fi
fi
done
2 高级功能:自动恢复与多路径检测
当检测到目标异常时,脚本可尝试重新登录或切换路径:
# 异常自动重连函数
reconnect_target() {
local portal=$1
local target_iqn=$2
iscsiadm -m node -T $target_iqn -p $portal --logout
iscsiadm -m node -T $target_iqn -p $portal --login
if [ $? -eq 0 ]; then
echo "$(date) - RECONNECTED $target_iqn via $portal" >> $LOGFILE
fi
}
# 在检测到故障时调用
if [ "$state" != "LOGGED_IN" ]; then
reconnect_target "$portal" "$target_iqn"
fi
3 Python脚本方案:结构化监控
利用python-iscsi库(需先安装pip install python-iscsi)可以更灵活地解析iSCSI状态:
#!/usr/bin/env python3
import iscsi
from iscsi import Node
def check_targets():
nodes = Node.get_nodes()
for node in nodes:
session = node.get_session()
if session is None:
print(f"CRITICAL: No session for {node.name}")
continue
# 检查设备读写能力
device = session.get_device()
if device and device.is_online():
# 发送测试SCSI命令
result = session.test_unit_ready()
if result != 0:
print(f"WARNING: Unit not ready on {device.name}")
else:
print(f"CRITICAL: Device offline")
问答环节
Q:为什么生产环境不建议用dd写测试?
A:dd的oflag=direct绕过文件系统缓存,直接写入块设备,若误写入生产数据库的LUN,哪怕只写一个扇区,也会导致文件系统元数据损坏,安全做法是使用只读SCSI命令(如TEST UNIT READY),或专门创建一个400M的测试LUN用于监控。
常见问题与排查指南
1 检测结果异常时的排查步骤
-
如果是Ping通但
iscsiadm显示STATE: FAILED:- 检查iSCSI服务版本:
iscsiadm -V,部分老版本存在会话超时不释放的bug。 - 查看内核日志:
dmesg | grep -i iscsi,可能提示iSCSI TCP connection timeout。 - 尝试手动重连:
iscsiadm -m node -T $IQN --login。
- 检查iSCSI服务版本:
-
如果是
sg_inq返回Device not ready:- 目标端可能正在做LUN映射变更或存储重置,等5分钟后复测。
- 检查是否有多路径问题:
multipath -ll,若路径状态为undef,需排查存储侧配置。
2 为什么目标显示连接但IO超时?
这种情况常见于半连接状态——Initiator认为会话还在,但目标已在TCP层面断开(例如防火墙杀掉了空闲连接),解决方案:
- 调整iSCSI的
Keepalive参数:在/etc/iscsi/iscsid.conf中设置node.session.timeo.replacement_timeout = 120。 - 在监控脚本中设置异步超时:使用
timeout 5 sg_inq /dev/sdb强制命令5秒内返回。
3 如何区分目标故障还是网络抖动?
建议采用连续三次检测策略:
for i in 1 2 3; do
sg_inq /dev/sdb > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "OK"
break
fi
sleep 1
done
# 如果三次均失败,则判定为目标故障而非网络抖动
总结与最佳实践
1 监控频率与资源开销的平衡
- 轻量级检测(每60秒):仅执行
iscsiadm -m session -P 3和Ping,适合所有场景。 - 深度检测(每5分钟):执行
sg_inq和TEST UNIT READY,只对关键LUN执行。 - 写测试(每小时):仅在测试LUN上使用
dd,生产LUN禁止。
2 集成到现有监控体系
| 监控平台 | 集成方式 |
|---|---|
| Nagios | 将检测脚本封装为NRPE插件,返回OK/WARNING/CRITICAL状态码 |
| Zabbix | 使用UserParameter自定义键值,例如iscsi.state[$1] |
| Prometheus | 通过Node Exporter的textfile收集器暴露iSCSI状态指标 |
最后的核心建议:永远不要只依赖单一的检测方法,将网络层(Ping)、会话层(iscsiadm)、SCSI层(sg_inq)三者组合,才能构建对iSCSI目标的全面监控,避免因“假存活”导致的数据灾难。
(文章完)