可扩展遥测指南
可扩展遥测概述
设置开发环境
要访问遥测收集器(位于 aos_developer_sdk 存储库中),请联系 瞻博网络支持。将您开发的任何新收集器贡献到存储库中。
为了保持系统环境完整,我们建议您使用虚拟环境来隔离所需的 Python 包(用于开发和测试)。您可以从 https://support.juniper.net/support/downloads/?p=apstra/ 下载基本开发环境 aos_developer_sdk.run。要加载环境,请执行:
aos_developer_sdk$ bash aos_development_sdk.run 4d8bbfb90ba8: Loading layer [==================================================>] 217.6kB/217.6kB 7d54ea05a373: Loading layer [==================================================>] 4.096kB/4.096kB e2e40f457231: Loading layer [==================================================>] 1.771MB/1.771MB Loaded image: aos-developer-sdk:2.3.1-129 ================================================================================ Loaded AOS Developer SDK Environment Container Image aos-developer-sdk:2.3.1-129. Container can be run by docker run -it \ -v <path to aos developer_sdk cloned repo>:/aos_developer_sdk \ --name <container name> \ aos-developer-sdk:2.3.1-129 ================================================================================
此命令加载 aos_developer_sdk Docker 映像。映像加载完成后,将打印用于启动环境的命令。按照命令指定的方式启动容器环境。要安装依赖项,请执行:
root@f2ece48bb2f1:/# cd /aos_developer_sdk/ root@f2ece48bb2f1:/aos_developer_sdk# make setup_env ...
现在,已为开发和测试收集器设置了环境。环境中还安装了 Apstra SDK 包,例如设备驱动程序和 REST 客户端。
开发收集器
若要开发遥测收集器,请 按顺序指定以下内容。
写收集器
Collector 是一个必须派生自 aos.sdk.system_agent.base_telemetry_collector 的类。BaseTelemetryCollector。使用逻辑重写收集器的 收集 方法,以便:
从设备收集数据
收集器中的设备驱动程序实例提供对设备执行命令的方法。例如,大多数 Apstra 设备驱动程序都提供用于执行命令和返回输出的方法get_json
get_text
。
aos_developer_sdk环境的设备驱动程序已预安装。您可以探索可用于收集数据的方法。例如:
>>> from aos.sdk.driver.eos import Device >>> device = Device('172.20.180.10', 'admin', 'admin') >>> device.open() >>> pprint.pprint(device.get_json('show version')) {u'architecture': u'i386', u'bootupTimestamp': 1548302664.0, u'hardwareRevision': u'', u'internalBuildId': u'68f3ae78-65cb-4ed3-8675-0ff2219bf118', u'internalVersion': u'4.20.10M-10040268.42010M', u'isIntlVersion': False, u'memFree': 3003648, u'memTotal': 4011060, u'modelName': u'vEOS', u'serialNumber': u'', u'systemMacAddress': u'52:54:00:ce:87:37', u'uptime': 62620.55, u'version': u'4.20.10M'} >>> dir(device) ['AOS_VERSION_FILE', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'close', 'device_info', 'driver', 'execute', 'get_aos_server_ip', 'get_aos_version_related_info', 'get_device_aos_version', 'get_device_aos_version_number', 'get_device_info', 'get_json', 'get_text', 'ip_address', 'onbox', 'open', 'open_options', 'password', 'probe', 'set_device_info', 'upload_file', 'username']
解析数据
收集的数据需要根据 Apstra 框架和上面确定的服务模式进行解析和重新格式化。具有通用存储架构的收集器遵循以下结构:
{ "items": [ { "identity": <key goes here>, "value": <value goes here>, }, { "identity": <key goes here>, "value": <value goes here>, }, ... ] }
具有基于 IBA 的模式的收集器遵循以下结构:
[ { "key": <key goes here>, "value": <value goes here>, }, { "key": <key goes here>, "value": <value goes here>, }, ... ]
在上述结构中,发布的数据有多个项目。每个项目都有一个键和一个值。例如,要发布接口特定信息,要发布到框架的每个接口都有一个标识/键值对。
如果要使用第三方包解析从设备获取的数据,请在路径中列出 Python 包和版本。
<aos_developer_sdk>/aosstdcollectors/requirements_<NOS>.txt
.依赖项安装的软件包不会与 Apstra 软件使用的软件包冲突。Apstra 安装的软件包可在开发环境中找到 /etc/aos/python_dependency.txt
。
将数据发布到框架
根据所需的架构收集和分析数据时,将数据发布到框架。您可以使用 post_data
收集器中提供的方法。它接受一个参数,即应发布到框架的数据。
存储库中的文件夹 aos_developer_sdk/aosstdcollectors/aosstdcollectors
包含每个 NOS 的文件夹。将收集器添加到与 NOS 匹配的文件夹中。从 Apstra 版本 4.1.0 开始不再支持 Cumulus,但此示例仅供说明之用。例如,要为 Cumulus 编写收集器,请将收集器 aos_developer_sdk/aosstdcollectors/aosstdcollectors/cumulus
添加到 ,并以服务名称命名文件。例如,如果服务名称为 interface_in_out_bytes
,则将文件 interface_in_out_bytes.py
命名为 。
除了定义收集器类之外,还要在收集器文件中定义函数 collector_plugin
。该函数接受一个参数并返回实现的收集器类。
例如,基于通用存储架构的收集器如下所示:
""" Service Name: interface_in_out_bytes Schema: Key: String, represents interface name. Value: Json String with two possible keys: rx: integer value, represents received bytes. tx: integer value, represents transmitted bytes. DOS: eos Data collected using command: 'show interfaces' Type of Collector: BaseTelemetryCollector Storage Schema Path: aos.sdk.telemetry.schemas.generic Application Schema: { 'type': 'object', 'properties': { 'identity': { 'type': 'string', }, 'value': { 'type': 'object', 'properties': { 'rx': { 'type': 'number', }, 'tx': { 'type': 'number', } }, 'required': ['rx', 'tx'], } } } """ import json from aos.sdk.system_agent.base_telemetry_collector import BaseTelemetryCollector # Inheriting from BaseTelemetryCollector class InterfaceRxTxCollector(BaseTelemetryCollector): # Overriding collect method def collect(self): # Obtaining the command output using the device instance. collected_data = self.device.get_json('show interfaces') # Data is in the format # "interfaces": { # "<interface_name>": { # .... # "interfaceCounters": { # .... # "inOctets": int # "outOctets": int # .... # } # } # ... # } # Parse the data as per the schema and structure required. parsed_data = json.dumps({ 'items': [ { 'identity': intf_name, 'value': json.dumps({ 'rx': intf_stats['interfaceCounters'].get('inOctets'), 'tx': intf_stats['interfaceCounters'].get('outOctets'), }) } for intf_name, intf_stats in collected_data['interfaces'].iteritems() if 'interfaceCounters' in intf_stats ] }) # Post the data to the framework self.post_data(parsed_data) # Define collector_plugin class to return the Collector def collector_plugin(_device): return InterfaceRxTxCollector
基于 IBA 存储模式的收集器如下所示:
""" Service Name: iba_bgp Schema: Key: JSON String, specifies local IP and peer IP. Value: String. ‘1’ if state is established ‘2’ otherwise DOS: eos Data collected using command: 'show ip bgp summary vrf all' Storage Schema Path: aos.sdk.telemetry.schemas.iba_string_data Application Schema: { 'type': 'object', 'properties': { key: { 'type': 'object', 'properties': { 'local_ip': { 'type': 'string', }, 'peer_ip': { 'type': 'string', } }, 'required': ['local_ip', 'peer_ip'], }, 'value': { 'type': 'string', } } } """ from aos.sdk.system_agent.base_telemetry_collector import IBATelemetryCollector def parse_text_output(collected): result = [ {'key': {'local_ip': str(vrf_info['routerId']), 'peer_ip': str(peer_ip)}, 'value': str( 1 if session_info['peerState'] == 'Established' else 2)} for vrf_info in collected['vrfs'].itervalues() for peer_ip, session_info in vrf_info['peers'].iteritems()] return result # Inheriting from BaseTelemetryCollector class IbaBgpCollector(BaseTelemetryCollector): # Overriding collect method def collect(self): # Obtaining the command output using the device instance. collected_data = self.device.get_json('show ip bgp summary vrf all') # Parse the data as per the schema and structure required and # post to framework. self.post_data(parse_text_output(collected_data)) # Define collector_plugin class to return the Collector def collector_plugin(device): return IbaBgpCollector
单元测试收集器
存储库中的文件夹 aos_developer_sdk/aosstdcollectors/test
包含基于 NOS 的文件夹。将测试添加到与 NOS 匹配的文件夹中。例如,对积云收集器的测试将添加到 aos_developer_sdk/aosstdcollectors/test/cumulus
中。建议使用前缀 test_
命名单元测试。
现有基础结构实现用于模拟设备驱动程序命令响应的 Pytest 夹具 collector_factory
。测试开发的一般流程如下。
- 使用收集器工厂获取收集器实例和模拟的 Apstra 框架。收集器工厂将您编写的收集器类作为输入。
- 模拟设备响应。
- 调用收集方法。
- 验证发布到模拟 Apstra 框架的数据。
例如,测试如下所示:
import json from aosstdcollectors.eos.interface_in_out_bytes import InterfaceRxTxCollector # Test method with prefix 'test_' def test_sanity(collector_factory): # Using collector factory to retrieve the collector instance and mocked # Apstra framework. collector, mock_framework = collector_factory(InterfaceRxTxCollector) command_response = { 'interfaces': { 'Ethernet1': { 'interfaceCounters': { 'inOctets': 10, 'outOctets': 20, } }, 'Ethernet2': { 'interfaceCounters': { 'inOctets': 30, 'outOctets': 40, } } } } # Set the device get_json method to retrieve the command response. collector.device.get_json.side_effect = lambda _: command_response # Invoke the collect method collector.collect() expected_data = [ { 'identity': 'Ethernet1', 'value': json.dumps({ 'rx': 10, 'tx': 20, }), }, { 'identity': 'Ethernet2', 'value': json.dumps({ 'rx': 30, 'tx': 40, }) } ] # validate the data posted by the collector data_posted_by_collector = json.loads(mock_framework.post_data.call_args[0][0]) assert sorted(expected_data) == sorted(data_posted_by_collector["items"])
要运行测试,请执行:
root@1df9bf89aeaf:/aos_developer_sdk# make test root@1df9bf89aeaf:/aos_developer_sdk# make test
此命令执行存储库中的所有测试。
包收集器
所有收集器均基于 NOS 进行打包。要生成所有包,请在 执行 make aos_develop_sdk
。您可以在 上 aos_developer_sdk/dist
找到构建包。包构建大致可分为:
包 | 说明 |
---|---|
内置收集器包 | 这些包具有前缀 aosstdcollectors_builtin_。要根据参考设计从设备收集遥测数据,Apstra 需要本节 <deviceblah> 中列出的服务。内置收集器包包含这些服务的收集器。这些包是基于每个 NOS 生成的。 |
自定义收集器包 | 这些软件包的名称中带有前缀 aosstdcollectors_custom_ 。这些包是基于每个 NOS 生成的。名为 aosstdcollectors_custom_<NOS>-0.1.0-py2-none-any.whl 的软件包包含开发的收集器。 |
Apstra SDK 设备驱动程序包 | 这些包具有前缀 apstra_devicedriver_。这些包是基于每个 NOS 生成的。系统会为 NOS 生成在 Apstra 中默认不可用的软件包。 |
上传包
如果 Apstra 软件未提供适用于您的设备操作系统 (NOS) 的内置收集器包和 Apstra SDK 设备驱动程序,则必须将它们上传到 Apstra 服务器。
如果您使用的是异机解决方案,并且您的 NOS 不是 EOS,则必须上传内置收集器包。
上传包含收集器的软件包,并将其分配给设备系统代理或系统代理配置文件。
使用遥测收集器
设置遥测服务注册表
注册表将服务映射到其应用程序架构和存储架构路径。可以使用 REST 终结点 /api/telemetry-service-registry
管理遥测服务注册表。如果不为特定服务添加注册表项,则无法为服务启用收集器。在使用服务时,无法修改服务的注册表项。
执行 make
时,所有应用程序模式都打包到 dist 文件夹中的 tar 文件 (json_schemas.tgz) 中。使用 apstra-cli,您可以选择导入 .tgz 文件中的所有架构。
启动收集器
要启动服务,请将 POST API /api/systems/<system_id>/services
与以下三个参数一起使用:
参数 | |
---|---|
Input_data | 作为输入提供给收集器的数据。默认值为“无”。 |
区间 | 运行服务的时间间隔。默认为 120 秒。 |
名字 | 服务的名称。 |
您还可以通过 apstra-cli 实用程序管理收集器。
删除收集器
要删除服务,请使用 删除 API /api/systems/<system_id>/services/<service_name>
。
获取收集的数据
要检索收集的数据,请使用 GET API /api/systems/<system_id>/services/<service_name>/data
。仅保存上次迭代中收集的数据。数据不会在 Apstra 重启后保留。
列出正在运行的收集器服务
要检索设备上启用的服务列表,请使用 GET API /api/systems/<system_id>/services
。