telemetry + python3 +prometheus

前言

疫情以来,居家办公,闲来无事,折腾下telemetry协议相关的监控,现有资料大都只是展示了,如何采集数据,对于数据的处理很少提及,本文将数据处理部分补齐,方便读者更快速理解,关于telemetry协议,这里不做过多概述。值得注意的是现有的open-telemetry和本文中的telemetry还是有所不同,前者较为广义,主要讲框架,是可观察性的主要框架之一,本次实验中的telemetry协议较为狭义,仅为可观测中的metric部分做参考,我们可以从中管中窥豹,网络人龙混杂。不喜勿喷!

整体思路

本文以华为交换机为客户端,通过telemetry协议发送数据至接收端(python编写),然后转发至prometheus的pushgateway,通过grafana进行展示


大致过程如下:

1. 配置设备telemetry 静态订阅,(采集内容,推送对象,推送间隔),网络设备为客户端,接收端为服务端

        静态订阅为推送模式(网络设备为客户端,向外推送),动态订阅为拉取模式(网络设备本身为服务端,需要设备上开启grpc服务)

2. 官网下载华为设备对应的proto文件(公共服务对应的proto文件,业务层对应的proto文件),编译proto文件得到服务器调用的方法。

3. 配置telemetry接收服务端

4. 数据推送至prometheus网关 -pushgateway

5. grafana 展示

配置过程

1.交换机配置(参考官网)

a.进入telemetry视图

b.配置推送目标

c.配置设备采样数据

d.创建静态订阅

2.proto文件使用

用途:根据proto文件用来解析服务调用及接收方法。

使用run_codegen.py脚本编译proto文件(https://github.com/grpc/grpc/blob/v1.45.0/examples/python/route_guide/run_codegen.py)

解析前环境配置(服务端):

安装解析proto文件依赖

pip3 install grpcio grpcio-tools

run_codegen.py文件(华为proto中需解析huawei-telemetry.proto,huawei-grpc-dialout.proto,这两个文件提供公共的解析方法调用)

# Copyright 2015 gRPC authors.

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#     http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

"""Runs protoc with the gRPC plugin to generate messages and gRPC stubs."""

from grpc_tools import protoc

protoc.main((

       '',

           '-I./protos',

               '--python_out=.',

                   '--grpc_python_out=.',

                       './protos/huawei-ifm.proto',

                       ))

protoc.main((

       '',

           '-I./protos',

               '--python_out=.',

                   '--grpc_python_out=.',

                       './protos/huawei-debug.proto',

                       ))


protoc.main((

       '',

           '-I./protos',

               '--python_out=.',

                   '--grpc_python_out=.',

                       './protos/huawei-telemetry.proto',

                       ))

protoc.main((

       '',

           '-I./protos',

               '--python_out=.',

                   '--grpc_python_out=.',

                       './protos/huawei-grpc-dialout.proto',

                       ))

执行python3 run_codegen.py,同目录生成相应的包文件

3. 服务端配置:

prometheus及相关组件见后续章节:

server.py

#!/usr/bin/python3

# _*_ coding: UTF-8 _*_

# Copyright (c) 2021 GengYu.All rights reserved

# @Create by jerry

# @Create Time :2022/04/10

# @File Name : telemetry

"""

"""

__author__ = 'jerry'

# import doctest

from ast import parse

from email import contentmanager

import requests

import prometheus_client

from prometheus_client import Counter

from prometheus_client import Gauge

from prometheus_client.core import CollectorRegistry

import requests

from concurrent import futures

import time

import importlib

#pip 安装 pip3 install grpcio grpcio-tools

import grpc

#run_codegen.py 参考网站https://github.com/grpc/grpc/blob/v1.45.0/examples/python/route_guide/run_codegen.py)

import huawei_grpc_dialout_pb2_grpc

import huawei_telemetry_pb2 #generate_codes.py生成

registry = CollectorRegistry(auto_describe=False)

_ONE_DAY_IN_SECONDS = 60 * 60 * 24

def tele_server():

   #创建一个grpc server对象

   server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

   #注册huawei的telemetry 数据监听服务

   huawei_grpc_dialout_pb2_grpc.add_gRPCDataserviceServicer_to_server(

       Telemetry_Info(),server)

   #设置socket监听端口和PC的IP地址,与交换机中推送目标IP地址一致

   server.add_insecure_port('ip:端口')

   #启动 grpc server

   server.start()

   #死循环监听

   try:

       while True:

           time.sleep(_ONE_DAY_IN_SECONDS)

   except KeyboardInterrupt:

       server.stop(0)

def is_number(s):

   try:

       float(s)

       return True

   except ValueError:

       pass

   try:

       import unicodedata

       unicodedata.numeric(s)

       return True

   except (TypeError, ValueError):

       pass

   return False

#add,用于网关推送

def to_prom_gateway(labelValue,parsedata):

   labels=["product_name","subscription_id_str","sensor_path","instance"]

   jobName="pushgateway"

   url="http://prometheus网关IP:9091/metrics"

   param=''

   #telemetry数据格式处理

   for i in parsedata.split('\n'):

       if '{' in i:

           str="".join(i.replace('{','_').split())

           param+=str

           continue

       if ':' in i:

           key=param+i.split(':')[0].strip()

           value=i.split(':')[1].strip()

       # print(type(value))

           if is_number(value):


               g = Gauge(key,"" ,labels ,registry=registry)

               g.labels(product_name=labelValue[0],subscription_id_str=labelValue[1],sensor_path=labelValue[2],instance=labelValue[3]).inc(float(value))

               requests.post("%s/job/%s" %(url,jobName),data=prometheus_client.generate_latest(registry))

               # print(value)

               continue

#创建类继承huawei_grpc_dialout_pb2_grpc中的Servicer方法,参考官网

class Telemetry_Info(huawei_grpc_dialout_pb2_grpc.gRPCDataserviceServicer):

   def __init__(self):

       return

   def dataPublish(self, request_iterator, context):

       for i in request_iterator:

           # print('________________________ start ________________________')

           telemetry_data = huawei_telemetry_pb2.Telemetry.FromString(i.data)

           # print(telemetry_data)

           labels=[telemetry_data.product_name,telemetry_data.subscription_id_str,telemetry_data.sensor_path,telemetry_data.node_id_str]

           for row_data in telemetry_data.data_gpb.row:

               module_name = telemetry_data.proto_path.split('.')[0]

               root_class = telemetry_data.proto_path.split('.')[1]

               #动态加载telemetry 获取数据的对应模块.

               decode_module = importlib.import_module(module_name + '_pb2')

               #定义解码方法:getattr获取动态加载的模块中的属性值,调用此属性的解码方法FromString

               decode_func = getattr(decode_module,root_class).FromString

               parsedata=decode_func(row_data.content)


               to_prom_gateway(labelValue=labels,parsedata=parsedata)

               # timestamp=row_data.timestamp

if __name__ == "__main__":

   tele_server()

执行server.py

python3 server.py

附:telemetry数据格式如下

_ start -----------

node_id_str: "test-R1"

subscription_id_str: "subscription1"

sensor_path: "huawei-debug:debug/memory-infos/memory-info"

collection_id: 1647801

collection_start_time: 1649657530145

msg_timestamp: 1649657530303

data_gpb {

  row {

   timestamp: 1649657530287

   content: "\032_\n]\n\0011\020Z\030K \201\200\204\010(\X\257E`ah\324\201\001p\225gx\277\032\200\001O\212\001\0230

  }

  row {

   timestamp: 1649657530287

   content: "\032_\n]\n\0012\020Z\030K \201\200\210\010(\3X\241Q``h\351\202\001p\327gx\222\033\200\001O\212\001\023

  }

  row {

   timestamp: 1649657530287

   content: "\032`\n^\n\0014\020Z\030K \201\200\220\010(\56\252\001`\\h\362\254\001p\303Gx\257e\200\001)\212\001\02

  }

  row {

   timestamp: 1649657530287

   content: "\032_\n]\n\0015\020Z\030K \201\200\224\010(\225\301\001`Xh\257yp\254/x\203J\200\001\'\212\001\0230000-

  }

}

collection_end_time: 1649657530303

current_period: 1000

except_desc: "OK"

product_name: "NE40E"

proto_path: "huawei_debug.Debug"

________________________

The proto path is :huawei_debug.Debug

________________________

<module 'huawei_debug_pb2' from '/opt/telemetry/huawei_deb

________________________ content is ______________________

memory_infos {

  memory_info {

   position: "1"

   overload_threshold: 90

   unoverload_threshold: 75

   index: 16842753

   os_memory_total: 963496

   os_memory_use: 622712

   os_memory_free: 340784

   os_memory_usage: 64

   do_memory_total: 319607

   do_memory_use: 310728

   do_memory_free: 8879

   do_memory_usage: 97

   simple_memory_total: 16596

   simple_memory_use: 13205

   simple_memory_free: 3391

   simple_memory_usage: 79

   overload_state_change_time: "0000-00-00 00:00:00"

   current_overload_state: "Unoverload"

   memreli_notice_threshold: 85

   memreli_overload_threshold: 90

  }

}

________________________ done ________________________

________________________

效果查看:

prometheus 查看指标

4. grafana查看

grafana中添加prometheus数据源

登录grafana->explorer进行验证查看,后续可通过dashboard进行统一展示


后续可根据告警模块设置相应的告警。

部署Prometheus+grafana+pushGateway

docker部署Prometheus

docker 安装略

创建prometheus.yml

mkdir /opt/prom

touch /opt/prom/rules.yml

vi /pot/prom/prometheus.yml

global:

  scrape_interval:

  external_labels:

  monitor: 'codelab-monitor'

# 这里表示抓取对象的配置

scrape_configs:

  - job_name: 'prometheus'

   static_configs:

   - targets: ['localhost:9090']

  - job_name: 'node_exporter'

   static_configs:

     - targets: ['10.158.1.211:9100']

启动服务器

docker run --name prometheus -p 9090:9090 --restart=always \

-v /opt/prom/prometheus.yml:/etc/prometheus/prometheus.yml \

-v /opt/prom/rules.yml:/etc/prometheus/rules.yml \

-itd prom/prometheus \

--config.file=/etc/prometheus/prometheus.yml \

--web.enable-lifecycle

部署node_exporter-客户端安装(可选)

docker run --name=node-exporter -p 9100:9100 -itd prom/node-exporter

部署grafana

docker run --name=grafana -p 3000:3000 -itd grafana/grafana

docker cp grafana:/etc/grafana/grafana.ini /opt/prom/grafana/

docker rm -f grafana

chmod 777 /opt/prom/*

docker run -p 3000:3000 --name grafana  --restart=always \

-v /opt/grafana/grafana.ini:/etc/grafana/grafana.ini \

-v /opt/grafana/data:/var/lib/grafana \

-itd grafana/grafana

部署pushgateway

docker run -d --name=pgw -p 9091:9091 prom/pushgateway

服务端修改prometheus.yml文件

添加

- job_name: 'pushgateway'

   static_configs:

     - targets: ['10.158.1.211:9091']

       labels:

         instance: telepushgateway

验证

docker部署的组件可用docker ps进行查看容器是否启用。

或通过ip:port进行验证,查看端口等。

至此,基于telemetry协议的数据从采集->处理->展示基本结束,大家有兴趣可以更深一步交流

待改进

接收端侧需添加守护进程

添加通用规则用于处理prometheus的labels

时间的处理。prometheus时间与telemetry中的时间有差异

...

总结

通过对此协议的监控探索,因telemetry可以提供亚秒级数据,监控精度有了质的提升,对于敏感度要求较高的用户比较适用。telemetry同样需要专业的工具支持才能发挥其特长。

对于告警的支持,暂时还是分钟级比较适用点,至于数据存储及性能瓶颈,并没有相关说明,毕竟设备侧重心在如何产生数据,不关心后台存储的问题

总之,从监控侧来看,现在说telemetry的推广应用,除了厂商自己内部产品外,如果要做成通用的,还需要一段路。。。

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容