返回文章列表

SNMP網路裝置效能資料收集

本文介紹如何使用 SNMP 協定讀取和收集網路裝置的效能資料,涵蓋了 SNMP 的基礎知識、OID 的查詢方法,以及如何使用命令列工具和 Python 程式碼進行實際操作。文章詳細解釋了 SNMP GET、SET 和 GETNEXT 命令的使用方法,並提供了程式碼範例和結果分析,幫助讀者理解 SNMP

網路管理 效能監控

SNMP 是一種廣泛應用的網路管理協定,用於監控網路裝置的效能。要取得裝置的效能資料,首先需要了解 SNMP 的基礎知識,例如 OID(物件識別碼)的概念。OID 用於唯一標識裝置中的各種資訊,例如 CPU 使用率、記憶體使用量、網路流量等。透過 SNMP,管理系統可以向裝置傳送請求,取得指定的 OID 值。常用的命令列工具 snmpwalk 可以幫助我們快速查詢裝置的 OID 資訊。此外,也可以使用 Python 等程式語言,結合 PySNMP 函式庫,編寫程式碼來讀取和收集效能資料。

使用 SNMP 讀取與收集效能資料

簡介

SNMP(簡單網路管理協定)是一種廣泛使用的網路管理協定,用於監控和管理網路裝置的效能資料。本章節將介紹如何使用 SNMP 讀取和收集網路裝置的效能資料。

介面條目 SNMP OIDs

SNMP 使用 OID(物件識別碼)來識別網路裝置上的各種資訊。表 1-2 列出了與介面條目相關的 SNMP OIDs。

OID 清單

OID 字串OID 名稱描述
1.3.6.1.2.1.2.2.1.1ifIndex介面的唯一序號。
1.3.6.1.2.1.2.2.1.2ifDescr包含介面名稱和其他可用資訊的字串。
1.3.6.1.2.1.2.2.1.3ifType代表介面型別的數字,取決於介面的實體鏈路和協定。
1.3.6.1.2.1.2.2.1.4ifMtu此介面可以傳輸的最大網路資料報。
1.3.6.1.2.1.2.2.1.5ifSpeed介面的估計當前頻寬。如果無法計算當前頻寬,則此數字應包含介面的最大可能頻寬。
1.3.6.1.2.1.2.2.1.6ifPhysAddress介面的實體位址,通常是乙太網路介面上的 MAC 位址。
1.3.6.1.2.1.2.2.1.7ifAdminStatus此 OID 允許設定介面的新狀態。通常限於以下值:1(啟用)、2(停用)、3(測試)。
1.3.6.1.2.1.2.2.1.8ifOperStatus介面的目前狀態。通常限於以下值:1(啟用)、2(停用)、3(測試)。
1.3.6.1.2.1.2.2.1.9ifLastChange包含系統啟動時間(sysUpTime)讀取值,當此介面進入其目前狀態時。如果介面在上次系統重新初始化之前進入此狀態,則可能設定為零。
1.3.6…(省略)

詳細解說

這些 OID 提供有關網路裝置介面的詳細資訊,包括其狀態、頻寬、傳輸和接收的資料量等。

SNMP 認證

早期的 SNMP 實作使用簡單的認證機制,包括唯讀和讀寫兩種社群字串。管理系統必須使用其中一個有效的社群字串進行認證,才能對代理程式發出命令。

從命令列查詢 SNMP

在撰寫應用程式之前,可以使用命令列工具查詢 SNMP,以驗證 SNMP 代理程式傳回的資訊是否正確。Net-SNMP-Utils 軟體包提供了多種命令列工具,可以用於查詢和設定 SNMP 物件。

安裝 Net-SNMP-Utils

在根據 RedHat 的系統上,可以使用以下命令安裝:

$ sudo yum install net-snmp-utils

在根據 Debian 的系統上,可以使用以下命令安裝:

$ sudo apt-get install snmp

使用 snmpwalk 命令

snmpwalk 命令是一個非常有用的工具,它接受一個 OID 節點作為引數,並嘗試發現所有子節點 OID。該命令使用 SNMP 操作 getnext,傳回樹中的下一個節點,有效地允許您遍歷從指定節點開始的整個子樹。

程式碼範例

snmpwalk -v 1 -c public localhost .1.3.6.1.2.1.2.2

內容解密:

此命令使用 snmpwalk 對本地主機上的 SNMP 代理程式進行查詢,檢索與介面條目相關的資訊。其中,-v 1 指定 SNMP 版本,-c public 指定社群字串,localhost 是目標主機,.1... 是要查詢的 OID 節點。

使用SNMP讀取與收集效能資料

SNMP(簡單網路管理協定)是一種用於管理和監控網路裝置的標準協定。在本章中,我們將探討如何使用SNMP來讀取和收集網路裝置的效能資料。

SNMP基礎

SNMP允許管理站(Manager)與被管理裝置(Agent)之間進行通訊,以收集和修改被管理裝置的資訊。SNMP使用OID(物件識別符號)來唯一標識被管理裝置中的每個物件。

使用snmpwalk命令收集資料

snmpwalk是一個用於透過SNMP協定檢索網路實體的資訊的命令列工具。以下是使用snmpwalk命令的一個範例:

$ snmpwalk –v2c -c public -On 192.168.1.68

內容解密:

  • -v2c 指定使用的SNMP版本為v2c。
  • -c public 設定community字串為public,這是用於驗證的密碼。
  • -On 表示以數字形式顯示OID。
  • 192.168.1.68 是被管理裝置的IP地址。

分析snmpwalk輸出的結果

執行snmpwalk命令後,將輸出被管理裝置的多個OID及其對應的值。以下是輸出的部分內容:

.1.3.6.1.2.1.1.1.0 = STRING: Linux fedolin.example.com 2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686
.1.3.6.1.2.1.1.2.0 = OID: .1.3.6.1.4.1.8072.3.2.10
...
.1.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1
.1.3.6.1.2.1.2.2.1.1.2 = INTEGER: 2
...

內容解密:

  • 第一行顯示了系統的描述資訊,包括作業系統型別、版本和主機名稱。
  • .1.3.6.1.2.1.1.2.0 表示系統物件ID,通常用於識別裝置型別。
  • 後續的輸出顯示了網路介面的索引、名稱、型別等資訊,如.1.3.6.1.2.1.2.2.1.1.x.1.3.6.1.2.1.2.2.1.2.x

OID的意義與查詢

OID是SNMP中用於識別被管理物件的唯一識別符號。根據輸出結果,可以查詢相關OID的含義。例如:

  • .1.3.6.1.2.1.1 對應於系統資訊群組,提供了系統的基本資訊,如系統描述、聯絡資訊等。
  • .1.3.6.1.2.1.2 對應於網路介面群組,提供了網路介面的詳細資訊,如介面數量、介面狀態等。

內容解密:

  • 使用SNMP MIB瀏覽器或相關檔案可以查詢OID的具體含義。
  • 瞭解OID的含義有助於更好地理解和管理網路裝置。

練習與應用

嘗試使用提供的表格(Tables 1-1 和 1-2)來識別輸出的OID,並理解其含義。這有助於更深入地理解SNMP的工作原理和網路裝置的管理。

使用Python與SNMP進行效能資料收集

簡介

SNMP(簡單網路管理協定)是一種廣泛使用的網路管理協定,用於監控和管理網路裝置。在本章中,我們將探討如何使用Python與SNMP來收集網路裝置的效能資料。

設定應用程式

首先,我們需要設定應用程式的組態檔。我們將使用Windows INI-style的組態檔,因為它簡單易用。Python內建了組態檔解析模組,因此使用起來也很方便。

組態檔範例

[system_1]
description=My Laptop
address=192.168.1.68
port=161
communityro=public

[check_1]
description=WLAN incoming traffic
oid=1.3.6.1.2.1.2.2.1.10.3
system=system_1

[check_2]
description=WLAN incoming traffic
oid=1.3.6.1.2.1.2.2.1.16.3
system=system_1

建立SnmpManager類別

我們將建立一個名為SnmpManager的類別,用於管理SNMP裝置。該類別將具有兩個方法:add_systemadd_check

SnmpManager類別定義

import sys
from ConfigParser import SafeConfigParser

class SnmpManager:
    def __init__(self):
        self.systems = {}

    def add_system(self, id, descr, addr, port, comm_ro):
        self.systems[id] = {'description': descr,
                            'address': addr,
                            'port': int(port),
                            'communityro': comm_ro,
                            'checks': {}
                            }

    def add_check(self, id, oid, descr, system):
        oid_tuple = tuple([int(i) for i in oid.split('.')])
        self.systems[system]['checks'][id] = {'description': descr,
                                              'oid': oid_tuple,
                                              }

使用PySNMP函式庫

在本專案中,我們將使用PySNMP函式庫,它是一個純Python實作的SNMP函式庫,不依賴任何預編譯的函式庫。

安裝PySNMP函式庫

您可以使用以下命令安裝PySNMP函式庫:

$ sudo yum install pysnmp
$ sudo yum install python-pyasn1

或者使用Python套件管理器(PiP)安裝:

$ sudo pip install pysnmp
$ sudo pip install pyasn1

SNMP GET命令

SNMP GET命令用於從SNMP代理程式取得特定的OID值。

SNMP GET命令範例

>>> from pysnmp.entity.rfc3413.oneliner import cmdgen
>>> cg = cmdgen.CommandGenerator()
>>> comm_data = cmdgen.CommunityData('my-manager', 'public')
>>> transport = cmdgen.UdpTransportTarget(('192.168.1.68', 161))
>>> variables = (1, 3, 6, 1, 2, 1, 1, 1, 0)
>>> errIndication, errStatus, errIndex, result = cg.getCmd(comm_data, transport, variables)
>>> print errIndication
None
>>> print errStatus
0
>>> print errIndex
0
>>> print result
[(ObjectName('1.3.6.1.2.1.1.1.0'), OctetString('Linux fedolin.example.com
2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686'))]
>>>

內容解密:

在這個範例中,我們使用了PySNMP函式庫的CommandGenerator類別來建立一個SNMP GET命令。首先,我們匯入了必要的模組並建立了一個CommandGenerator物件。然後,我們建立了一個CommunityData物件,用於指定SNMP共同體字串。接著,我們建立了一個UdpTransportTarget物件,用於指定SNMP代理程式的位址和埠號。最後,我們呼叫了getCmd方法來執行SNMP GET命令,並列印出了結果。

在結果中,我們可以看到OID值為1.3.6.1.2.1.1.1.0的對應值是一個字串,包含了Linux系統的版本資訊。

使用 SNMP 讀取與收集效能資料

SNMP GET 命令的執行細節

在 PySNMP 中,SNMP GET 命令對應到 getCmd() 方法的呼叫。當我們發起 SNMP GET 請求時,需要準備三個主要物件:CommunityDataUdpTransportTarget 和變數元組。

初始化 CommunityData 物件

當我們初始化 CommunityData 物件時,需要提供兩個字串:社群字串(community string)和代理或管理員安全名稱字串。在大多數情況下,安全名稱可以是任意字串。此外,還可以指定使用的 SNMP 版本(預設為 SNMP v2c)。如果需要查詢版本 1 裝置,可以使用以下命令:

comm_data = cmdgen.CommunityData('my-manager', 'public', mpModel=0)

Transport 物件的初始化

UdpTransportTarget 物件使用包含完整網域名稱或 IP 位址字串和整數埠號的元組進行初始化。

OID 的表示

最後一個引數是 OID,以包含所有節點 ID 的元組表示。因此,在讀取組態專案時,我們需要將點分隔的字串轉換為元組。

呼叫 getCmd() 方法

最後,我們呼叫 getCmd() 方法,該方法實作了 SNMP GET 命令,並將這三個物件作為引數傳遞。該命令傳回一個元組,每個元素描述如下:

元組元素描述
errIndication如果此字串不為空,則表示 SNMP 引擎錯誤。
errStatus如果此元素評估為 True,則表示 SNMP 通訊中發生錯誤;錯誤物件由 errIndex 元素指示。
errIndex如果 errStatus 指示發生錯誤,則可以使用此欄位查詢導致錯誤的 SNMP 物件。結果陣列中的物件位置是 errIndex-1。
result此元素包含所有傳回的 SNMP 物件元素的列表。每個元素是一個元組,包含物件名稱和物件值。

SNMP SET 命令的使用

SNMP SET 命令在 PySNMP 中對應到 setCmd() 方法的呼叫。所有引數都相同;唯一的區別是變數部分現在包含一個元組:OID 和新值。

示例:嘗試修改唯讀物件

from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto import rfc1902

cg = cmdgen.CommandGenerator()
comm_data = cmdgen.CommunityData('my-manager', 'public')
transport = cmdgen.UdpTransportTarget(('192.168.1.68', 161))
variables = ((1, 3, 6, 1, 2, 1, 1, 1, 0), rfc1902.OctetString('new system description'))
errIndication, errStatus, errIndex, result = cg.setCmd(comm_data, transport, variables)

結果分析

print(errIndication)  # None
print(errStatus)  # 6
print(errIndex)  # 1
print(errStatus.prettyPrint())  # noAccess(6)
print(result)  # [(ObjectName('1.3.6.1.2.1.1.1.0'), OctetString('new system description'))]

在這個例子中,我們嘗試寫入唯讀物件,導致錯誤。值得注意的是,我們需要將字串轉換為 SNMP 物件型別;否則,它們不會作為有效的引數傳遞。

SNMP GETNEXT 命令的使用

SNMP GETNEXT 命令實作為 nextCmd() 方法。語法和用法與 getCmd() 相同;唯一的區別是結果是指定 OID 節點的直接子節點的物件列表。

示例:查詢 SNMP 系統 OID 的直接子節點

from pysnmp.entity.rfc3413.oneliner import cmdgen

cg = cmdgen.CommandGenerator()
comm_data = cmdgen.CommunityData('my-manager', 'public')
transport = cmdgen.UdpTransportTarget(('192.168.1.68', 161))
variables = (1, 3, 6, 1, 2, 1, 1)
errIndication, errStatus, errIndex, result = cg.nextCmd(comm_data, transport, variables)

結果分析

for object in result:
    print(object)

輸出結果為:

[(ObjectName('1.3.6.1.2.1.1.1.0'), OctetString('Linux fedolin.example.com 2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686'))]
[(ObjectName('1.3.6.1.2.1.1.2.0'), ObjectIdentifier('1.3.6.1.4.1.8072.3.2.10'))]
[(ObjectName('1.3.6.1.2.1.1.3.0'), TimeTicks('340496'))]
[(ObjectName('1.3.6.1.2.1.1.4.0'), OctetString('Administrator ([email protected])'))]
[(ObjectName('1.3.6.1.2.1.1.5.0'), OctetString('fedolin.example.com'))]
[(ObjectName('1.3.6.1.2.1.1.6.0'), OctetString('MyLocation, MyOrganization, MyStreet, MyCity, MyCountry'))]

此圖示呈現了 SNMP GETNEXT 命令的執行結果:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title SNMP網路裝置效能資料收集

package "資料庫架構" {
    package "應用層" {
        component [連線池] as pool
        component [ORM 框架] as orm
    }

    package "資料庫引擎" {
        component [查詢解析器] as parser
        component [優化器] as optimizer
        component [執行引擎] as executor
    }

    package "儲存層" {
        database [主資料庫] as master
        database [讀取副本] as replica
        database [快取層] as cache
    }
}

pool --> orm : 管理連線
orm --> parser : SQL 查詢
parser --> optimizer : 解析樹
optimizer --> executor : 執行計畫
executor --> master : 寫入操作
executor --> replica : 讀取操作
cache --> executor : 快取命中

master --> replica : 資料同步

note right of cache
  Redis/Memcached
  減少資料庫負載
end note

@enduml

詳細解析此圖示

此圖示展示了 SNMP GETNEXT 命令的流程。首先,SNMP GETNEXT 命令會查詢指定 OID 的直接子節點。接著,傳回這些子節點的物件列表。每個物件都包含名稱和值,方便管理和監控網路裝置。

程式碼段作用與邏輯解析:

variables = (1, 3, 6, 1, 2, 1, 1)
errIndication, errStatus, errIndex, result = cg.nextCmd(comm_data, transport, variables)

此程式碼段的作用是使用 nextCmd() 方法查詢 OID (1, 3, 6, 1, 2, 1, 1) 的直接子節點。其中,variables 指定了要查詢的 OID,而 nextCmd() 方法則執行查詢並傳回結果。

邏輯解析:
  • variables 元組包含了 OID 的各個部分,這些部分組合起來形成完整的 OID。
  • nextCmd() 方法接收 comm_datatransportvariables 作為引數,分別代表社群資料、傳輸目標和查詢的 OID。
  • 方法傳回四個值:errIndicationerrStatuserrIndexresult,分別表示錯誤指示、錯誤狀態、錯誤索引和查詢結果。
  • 結果 result 是物件列表,每個物件包含名稱和值,用於描述查詢到的 OID 直接子節點的資訊。