Привет! На связи Андрей Лебедев, системный администратор Cloud4Y. Хочу с вами поделиться одним из вариантов настройки мониторинга СХД.

На СХД 3PAR, к сожалению, отсутствует мониторинг по SNMP, так как на FTS, к примеру. Часть проблем можно отлавливать с помощью SNM Trap, но в целом собирать так метрики нельзя. Зато можно использовать авторизацию по SSH и официальный модуль от HPE. В данной статье покажу пример использование модулей Posh‑SSH + HPE3PARToolKit через скрипт для сбора различных метрик, вывод их в файл и дальнейшую передачу на Zabbix Server.

Помимо мониторинга с помощью скриптов существует ещё как минимум два способа мониторинга 3PAR:

  • Grafana + официальный скрипт HPE

  • SNMP Trap

Предлагаю разобрать мониторинг через скрипты в Zabbix. Для такого мониторинга необходимо установить модули PowerShell: PoshSSH и HPE3PARToolKit. Минимально необходимая версия PowerShell — 5.1. Проверить версию PowerShell можно командой host или $PSVersionTable

Установка модулей

Install-Module -Name Posh-SSH 
Install-Module -Name HPEStoragePowerShellToolkit

Если по каким‑то причинам установка онлайн невозможна, то можно скачать необходимые модули на другом компьютере, а затем перенести их в нужную папку с модулями.

Save-Module –Name Posh-SSH –Path C:\PS\

Копируем модули по пути C:\Program Files\WindowsPowerShell\Modules и проверяем, что модули установлены:

Get-Module -Name Posh-SSH,HPEStoragePowerShellToolkit -ListAvailable

На примере скрипта по мониторингу VLUN рассмотрим составляющие скрипта. Для получения данных через PS необходима УЗ на 3PAR с минимальной ролью «Browse». В первой части скрипта выполняется сбор суммы всех томов под одним и тем же VV:

$Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress ip_адрес_3PAR -SANUserName «Имя пользователя 3PAR» -SANPassword «пароль»
    $dataVlun = Get-StatVlun -SANConnection $Connection1 -Iteration 1 -vvSum
    $removessh = ($Connection1 | Close-Connection)

    $data = @()

    $dataVlun | ForEach-Object {

        $3parexport = @{}

        $3parexport["{#NAMEVLUN}"] = $_.VVName
        
        $data += $3parexport

    }

    $exportdata = @{}
    $exportdata["data"] = $data

    $exportdata | ConvertTo-Json -Compress -Depth 10 | Out-File -FilePath "Вывод в файл" 

Скрипт подсоединяется на 3PAR через SSH, выполняет команду Get-StatVlun в 1 итерацию и записывает сумму всех томов одного и того же Virtual Volume в переменную. Далее через цикл идёт сбор томов в пустую переменную, и в конце данные сжимаются а вывод записывается в файл.

Вторая часть скрипта выполняет сбор метрик по каждому тому 3PAR. При сравнении вывода через CLI и непосредственно на самом 3PAR была обнаружена небольшая несостыковка в данных. Из-за того, что в вывод через CLI добавляются столбцы r/w_Cur, r/w_Avg и r/w_Max, происходит смещение столбцов. 

Так значение операций ввода-вывода будет равняться столбцу r/w_Cur, а не I/O_Cur, KB_Cur равняется I/O_Cur, Svt_Cur = KB_Cur.

$Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress ip_адрес_3PAR -SANUserName «Имя пользователя 3PAR» -SANPassword «пароль»
    $dataVlun = Get-StatVlun -SANConnection $Connection1 -Iteration 1 -vvSum -rw 
    $removessh = ($Connection1 | Close-Connection)
 
    $3parexport = @{}
    $3parexport_write = @{}
    $3parexport_read = @{}
    $3parexport_total = @{}

    $dataVlun | ForEach-Object {
        $exportport = ($_.Host)+($_.Port)+($_.VVName)
        If ($_."r/w" -eq "t"){


          If (-Not $3parexport.ContainsKey($exportport)) {
            $3parexport_total[$exportport] = @{
                "RW" = $_."r/w"
                "KBCur" = $_.KB_Cur
                "SVTCur" = $_.Svt_Cur
                "IOCur" = $_."I/O_Cur"
                "RWCur" = $_."r/w_Cur"
            }
          }
        }               
        If ($_."r/w" -eq "r"){

          If (-Not $3parexport.ContainsKey($exportport)) {
            $3parexport_read[$exportport] = @{
                "RW" = $_."r/w"
                "KBCur" = $_.KB_Cur
                "SVTCur" = $_.Svt_Cur
                "IOCur" = $_."I/O_Cur"
                "RWCur" = $_."r/w_Cur"
            }
          }
        }               
        If ($_."r/w" -eq "w"){

          If (-Not $3parexport.ContainsKey($exportport)) {
            $3parexport_write[$exportport] = @{
                "RW" = $_."r/w"
                "KBCur" = $_.KB_Cur
                "SVTCur" = $_.Svt_Cur
                "IOCur" = $_."I/O_Cur"
                "RWCur" = $_."r/w_Cur"
            }
          }
        }                   
    
    }
    $3parexport_read | ConvertTo-Json -Compress -Depth 10 | Out-File -FilePath "Вывод в файл"
    $3parexport_write | ConvertTo-Json -Compress -Depth 10 | Out-File -FilePath "Вывод в файл"
    $3parexport_total | ConvertTo-Json -Compress -Depth 10 | Out-File -FilePath "Вывод в файл" 

Происходит авторизация по SSH, выполнение команды Get-StatVlun -Iteration 1 -vvSum -rw
Ключи:

-rw выводит данные по каждому тому на чтение, запись и суммарно
RW – записывает в себя чтение\запись или сумму. В данном примере записывает сумму чтения + запись по каждому тому.
KBcur – текущее время обслуживания в мс
IOCur – текущее количество КБ в секунду
RWcur – текущее количество операций ввода-вывода в секунду

В конце получаем 3 файла – на чтение, на запись и суммарно.

Добавление в Zabbix


По ссылке можно найти готовый шаблон для Zabbix, где собраны некоторые элементы данных и автообнаружение (CPU, VLUN, VV, PortCheck, Disk). Шаблон под версию 7.0 и выше.

А ниже — примеры скриптов мониторинга:

CPU
    ####################################################
    ################## 3PAR CPU Node #################
    ####################################################

$Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
$dataCPU = Get-StatCPU -SANConnection $Connection1 -Iteration 1 
$removessh = ($Connection1 | Close-Connection)

$data = @()

$dataCPU | ForEach-Object {

    $3parexport = @{}

    $3parexport["{#NODENUM}"] = $_."node"
        
    $data += $3parexport

    }

$exportdata = @{}
$exportdata["data"] = $data

$exportdata | ConvertTo-Json -Compress -Depth 10 | Out-File -FilePath "Вывод в файл"



####################################################
################## 3PAR CPU  #################
####################################################

    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $dataCPU = Get-StatCPU -SANConnection $Connection1 -Iteration 1
    $removessh = ($Connection1 | Close-Connection)
    $3parCPU = @{}
    $dataCPU | ForEach-Object {
        $NodeCPU = $_.node
        If ($_.cpu -eq "total"){

        If (-Not $3parCPU.ContainsKey($NodeCPU)) {
            $3parCPU[$NodeCPU] = @{
                "cpu" = $_.cpu
                "user" = $_.user
                "system" = $_.sys
                "idle" = $_.idle
            }
        }
      }
   }

     $3parCPU | ConvertTo-Json -Depth 10 -Compress | Out-File -FilePath "Вывод в файл"

Ports
    ####################################################
    ################## 3PAR port Check #################
    ####################################################

    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $dataPort = Get-HostPorts | Select-Object -SkipLast 1 
    $removessh = ($Connection1 | Close-Connection)

    $data = @()

    $dataPort | ForEach-Object {

        $3parexport = @{}

        $3parexport["{#DEVICE}"] = $_.Device
        $3parexport["{#MODE}"] = $_.Mode
        $3parexport["{#STATE}"] = $_.State
        $3parexport["{#NODEWWN}"] = $_.Node_WWN
        $3parexport["{#PORTWWN}"] = $_.Port_WWN
        $3parexport["{#TYPE}"] = $_.Type
        $3parexport["{#PROTOCOL}"] = $_.Protocol
        $3parexport["{#LABEL}"] = $_.Label
        $3parexport["{#PARTNER}"] = $_.Partner

        
        $data += $3parexport

    }

    $exportdata = @{}
    $exportdata["data"] = $data

    $exportdata | ConvertTo-Json -Depth 10 | Out-File -FilePath "Вывод в файл" 

    ####################################################
    ################## 3PAR port Data ##################
    ####################################################

    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $dataPort = Get-HostPorts | Select-Object -SkipLast 1
    $removessh = ($Connection1 | Close-Connection)

    $3parStatPort = @{}
    $dataPort | ForEach-Object {
        $portname = $_.Device
        If (-Not $3parStatPort.ContainsKey($portname)) {
            $3parStatPort[$portname] = @{
                "MODE" = $_.Mode
                "STATE" = $_.State
                "NODEWWN" = $_.Node_WWN
                "PORTWWN" = $_.Port_WWN
                "TYPE" = $_.Type
                "PROTOCOL" = $_.Protocol
                "LABEL" = $_.Label
                "PARTNER" = $_.Partner
            }
        }
    }
    $3parStatPort | ConvertTo-Json -Depth 10 | Out-File -FilePath "Вывод в файл"

    ####################################################
    ################## 3PAR stat port ##################
    ####################################################

    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $data = Get-StatPort -SANConnection $Connection1 -Iteration 1
    $removessh = ($Connection1 | Close-Connection)
    $3parStatPort = @{}
    $data | ForEach-Object {
        $portname = $_.Port
        If (-Not $3parStatPort.ContainsKey($portname)) {
            $3parStatPort[$portname] = @{
                "KBCur" = $_.KB_Cur
                "SvtCur" = $_.Svt_Cur
                "IOCur" = $_."I/O_Cur"
                "IOSzCur" = $_.IOSz_Cur
            }
        }
    }
    $3parStatPort | ConvertTo-Json -Depth 10 | Out-File -FilePath "Вывод в файл"

VV
    ####################################################
    ################## 3PAR VV check #################
    ####################################################


    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $dataVV = Get-VVList
    $removessh = ($Connection1 | Close-Connection)

    $data = @()

    $dataVV | ForEach-Object {

        $3parexport = @{}

        $3parexport["{#ID}"] = $_.Id
        $3parexport["{#PROV}"] = $_.Prov
        $3parexport["{#NAME}"] = $_.Name
        $3parexport["{#TYPE}"] = $_.Type
        $3parexport["{#COPYOF}"] = $_.CopyOf
        $3parexport["{#BSID}"] = $_.BsId
        $3parexport["{#RD}"] = $_.Rd
        $3parexport["{#STATE}"] = $_."-Detailed_State-"
        $3parexport["{#SNP}"] = $_.Snp
        $3parexport["{#USR}"] = $_.Usr
        $3parexport["{#VSIZE}"] = $_.VSize

        
        $data += $3parexport

    }

    $exportdata = @{}
    $exportdata["data"] = $data

    $exportdata | ConvertTo-Json -Depth 10 -Compress | Out-File -FilePath "Вывод в файл"


        ####################################################
        ################## 3PAR VV stat #################
        ####################################################



    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $dataVV = Get-StatVv -SANConnection $Connection1 -Iteration 1
    $removessh = ($Connection1 | Close-Connection)
    $3parStatVV = @{}
    $3parStatVV = @{}
    $dataVV | ForEach-Object {
        $VVname = $_.VVname
        If (-Not $3parStatVV.ContainsKey($VVname)) {
            $3parStatVV[$VVname] = @{
                "KBCUR" = $_.KB_Cur
                "SVTCUR" = $_.Svt_Cur
                "IOSZCUR" = $_.IOSz_Cur
                "IOCUR" = $_."I/O_Cur"
            }
        }
    }
    $3parStatVV | ConvertTo-Json -Depth 10 -Compress | Out-File -FilePath "Вывод в файл"


        ####################################################
        ################## 3PAR VV List #################
        ####################################################


    $Connection1 = New-PoshSshConnection -ArrayNameOrIPAddress $3paripaddress -SANUserName $VC_USER -SANPassword $VC_PASS
    $dataVVList = Get-VVList
    $removessh = ($Connection1 | Close-Connection)
    $3parVVList = @{}
    $dataVVList | ForEach-Object {
        $VVname = $_.Name
        If (-Not $3parVVList.ContainsKey($VVname)) {
            $3parVVList[$VVname] = @{
                "ID" = $_.Id
                "PROV" = $_.Prov
                "USED" = $_.Usr
                "TOTAL" = $_.VSize
                "ADM" = $_.Adm
                "SNP" = $_.Snp
                "STATE" = $_."-Detailed_State-"
                "RD" = $_.Rd
            }
        }
    }
    $3parVVList | ConvertTo-Json -Depth 10 -Compress | Out-File -FilePath "Вывод в файл"

Используем отдельный сервер или ВМ, на которой по расписанию будет запускаться и делать вывод в файлы наш скрипт, а после Zabbix agent будет передавать данные из файлов. В конфиг Zabbix agent необходимо добавить пользовательские параметры.

UserParameter=3par1StatVlunNewTotal[*],type Путь_до_файла 
UserParameter=3par1StatVlunNewRead[*],type Путь_до_файла
UserParameter=3par1StatVlunNewWrite[*],type Путь_до_файла
UserParameter=3par1StatVlunCheck[*],type Путь_до_файла

После перезапускаем агента, добавляем шаблон 3PAR на Zabbix server и пользуемся.

Это довольно простое решение, оно не оптимально, но работает. Если у вас есть идеи, как ещё можно реализовать процессы мониторинга, с интересом послушаю.

Спасибо за внимание!

Комментарии (0)