脚本如何检测iSCSI目标是否正常

wen 实用脚本 15

脚本如何检测iSCSI目标是否正常:从基础到高可用监控实战指南

目录导读

  1. iSCSI目标检测的重要性与场景分析

    脚本如何检测iSCSI目标是否正常

    • 为什么需要定期检测iSCSI目标状态?
    • 常见故障场景:目标离线、路径失效、认证失败
  2. 核心检测机制:从ICMP到SCSI指令

    • Ping测试的局限性
    • 使用iscsiadm命令查询会话与目标状态
    • 基于sg_inqdd的深度读写检测
  3. 自动化监控脚本编写实战

    • 基础Shell脚本:多目标循环检测
    • 高级功能:邮件告警、日志轮转、异常恢复自动重连
    • Python脚本方案:利用python-iscsi库实现跨平台监控
  4. 常见问题与排查指南

    • 检测结果异常时的排查步骤
    • 为什么目标显示连接但IO超时?
    • 如何区分目标故障还是网络抖动?
  5. 总结与最佳实践

    • 监控频率与资源开销的平衡
    • 结合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:ddoflag=direct绕过文件系统缓存,直接写入块设备,若误写入生产数据库的LUN,哪怕只写一个扇区,也会导致文件系统元数据损坏,安全做法是使用只读SCSI命令(如TEST UNIT READY),或专门创建一个400M的测试LUN用于监控。


常见问题与排查指南

1 检测结果异常时的排查步骤

  1. 如果是Ping通但iscsiadm显示STATE: FAILED

    • 检查iSCSI服务版本:iscsiadm -V,部分老版本存在会话超时不释放的bug。
    • 查看内核日志:dmesg | grep -i iscsi,可能提示iSCSI TCP connection timeout
    • 尝试手动重连:iscsiadm -m node -T $IQN --login
  2. 如果是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_inqTEST 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目标的全面监控,避免因“假存活”导致的数据灾难。


(文章完)

抱歉,评论功能暂时关闭!