Привет! На связи Андрей Лебедев, системный администратор 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 и пользуемся.
Это довольно простое решение, оно не оптимально, но работает. Если у вас есть идеи, как ещё можно реализовать процессы мониторинга, с интересом послушаю.
Спасибо за внимание!