python实现自动更新prometheus规则

由于公司需要监控目标类型较多,不能手动去改动prometheus规则然后reload,所以就通过python写了个程序自动更新prometheus配置

基本环境准备

  • python 3.10.10
  • flask 2.3.2
  • prometheus 2.52.0

基本流程

  1. 将接口传来的prometheus规则信息保存到数据表中
  2. 取数据表中所有prometheus规则生成规则文件保存到本地临时文件夹内
  3. 获取需要修改prometheus机器ip
  4. 根据第三步获取的ip读取之前的prometheus规则备用
  5. 根据第三部获取的ip删除之前prometheus规则文件
  6. 把第二步生成的规则文件上传到第三步获取ip机器上
  7. 通过调用http://{ip}:9090/-/reload接口让配置文件重新生效
  8. 如果新的规则文件未生效,把第四部备用规则文件上传
  9. 清除第二步中的临时文件夹

以上为开发流程,在基本环境准备好的前提下开始开发,本文涉及的kevin模块导入均为本人开发功。

1.数据表创建及模型开发

DROP TABLE IF EXISTS `prom_ruler`;
CREATE TABLE `prom_ruler` (`id` int(11) NOT NULL AUTO_INCREMENT,`expr` varchar(1023) DEFAULT NULL,`duration` varchar(16) DEFAULT NULL,`severity` varchar(15) DEFAULT NULL,`summary` text,`description` text,`datasource` int(11) DEFAULT NULL,`group` int(11) DEFAULT NULL,`updated_on` datetime DEFAULT NULL,`created_on` datetime DEFAULT NULL,`heal` int(11) DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
#!/usr/bin/env python
# -*- coding: UTF-8 -*-from sqlalchemy import Column, Integer, String, TEXTfrom kevin.sqlalchemy_utils.model import Modelclass PromRulerModel(Model):"""prom ruler"""__tablename__ = "prom_ruler"expr = Column(String(100))duration = Column(String(10))severity = Column(String)summary = Column(TEXT)description = Column(TEXT)datasource = Column(Integer)group = Column(Integer)heal = Column(Integer)

2.业务逻辑处理

#!/usr/bin/env python
# -*- coding: UTF-8 -*-import traceback
from typing import Listimport yamlimport requests
from flask import requestfrom kevin.common.http_code import HttpCode
from kevin.log import logger
from kevin.sqlalchemy_utils.model_utils import list_to_dictlist
from kevin.utils import pretty_resultfrom config import Config
from extensions.ssh_ext import read_remote_file, exec_ssh_one_cmd, upload_file_to_linux
from models.alarm_heal import AlarmHeal
from models.common import GroupModel, DataSourceModel
from models.prometheus import PromRulerModel, PromRuleClassifyModel
from resource.v1.dc2_monitor_mixin import MonitorMixinclass PrometheusDbView(MonitorMixin):@staticmethoddef generate_prometheus_rule_model(prometheus_rule: dict) -> PromRulerModel:prom_rule_model = PromRulerModel(expr=prometheus_rule["monitorMetrics"] + prometheus_rule["symbols"] + prometheus_rule["alarmThreshold"],duration=prometheus_rule["duration"],severity=prometheus_rule["severity"],summary=prometheus_rule["summary"],description=prometheus_rule["description"],datasource=prometheus_rule["datasource"],group=prometheus_rule["group"])if "heal" in prometheus_rule and prometheus_rule["heal"] and prometheus_rule["heal"] != "None":prom_rule_model.heal = prometheus_rule["heal"]else:prom_rule_model.heal = 0return prom_rule_model@staticmethoddef save_prometheus_rule(prom_rule_model) -> None:add_prom_rule_model_res = prom_rule_model.objects.add()if not add_prom_rule_model_res:raise Exception("prom rule was failed deposited into the database.")@staticmethoddef delete_prometheus_rule(prometheus_rule_id: int) -> dict:prom_rule = PromRulerModel.objects_().get_by_id(prometheus_rule_id).__dict__PromRulerModel.objects_().delete(PromRulerModel.id == prometheus_rule_id)return prom_ruledef save_prometheus_rule_to_db(self, prometheus_rule: dict) -> None:logger.info("Start save prometheus rule to db.")prom_rule_model = self.generate_prometheus_rule_model(prometheus_rule=prometheus_rule)self.save_prometheus_rule(prom_rule_model=prom_rule_model)logger.info("Success save prometheus rule to db.")@staticmethoddef get_prometheus_rule_by_db() -> List[dict]:prom_rule = PromRulerModel.objects_().list() or []prom_rule = list_to_dictlist(prom_rule)for rule in prom_rule:if "datasource" in rule and rule["datasource"] != 'None':rule["datasource_id"] = int(rule["datasource"])rule["datasource"] = DataSourceModel.objects_().get_by_id(int(rule["datasource"])).nameif "group" in rule:rule["group_id"] = int(rule["group"])try:rule["group"] = GroupModel.objects_().get_by_id(int(rule["group"])).nameexcept Exception as e:logger.error("group deleted!")return prom_ruledef update_prometheus_rule_by_db(self, prometheus_rule: dict) -> None:logger.info("Start update prometheus rule to db.")prom_rule_model = self.generate_prometheus_rule_model(prometheus_rule=prometheus_rule)self.delete_prometheus_rule(prometheus_rule_id=prometheus_rule["id"])self.save_prometheus_rule(prom_rule_model=prom_rule_model)logger.info("Finish update prometheus rule to db.")class PrometheusRuleView(MonitorMixin):@staticmethoddef generate_prometheus_ips(prometheus_rule: dict) -> list:datasource_id = int(prometheus_rule["datasource"])url = DataSourceModel.objects_().get_by_id(datasource_id).urlreturn url.split(",")def read_prom_config(self, ip: str) -> list:host_info = self._get_host_info(ip)prom_rule_old_yml = read_remote_file(host_info=host_info, remote_path=Config.PROMETHEUS_CONFIG_PATH)return prom_rule_old_ymldef generate_prometheus_yml(self) -> None:prometheus_yml = {"groups": [{"name": "default_group","rules": []}]}prom_rule_model = PromRulerModel.objects_().list() or []prom_rule_list = list_to_dictlist(prom_rule_model)for prom_rule in prom_rule_list:try:prom_rule_dict = {"alert": GroupModel.objects_().get_by_id(int(prom_rule["group"])).name,"annotations": {"summary": prom_rule["summary"],"description": prom_rule["description"],},"expr": prom_rule["expr"],"for": prom_rule["duration"],"labels": {"prom_id": prom_rule["id"],"severity": prom_rule["severity"]}}prometheus_yml["groups"][0]["rules"].append(prom_rule_dict)except Exception as e:logger.error(f"generate prom rule, error: {e}, {traceback.format_exc()}")logger.error(f"prom rule {prom_rule}")self.generate_conf_tmp_dir()with open(Config.PROMETHEUS_CONFIG_LOCAL_PATH, "w", encoding='utf-8') as f:yaml.dump(prometheus_yml, f, allow_unicode=True)@staticmethoddef generate_old_prometheus_yml(prom_rule_old_yml) -> None:with open(Config.PROMETHEUS_CONFIG_OLD_LOCAL_PATH, "w", encoding='utf-8') as f:yaml.dump(prom_rule_old_yml, f, allow_unicode=True)def remove_remote_prometheus_rules(self, ip: str) -> None:remove_remote_prometheus_rule_cmd = f"rm -f {Config.PROMETHEUS_CONFIG_PATH}"host_info = self._get_host_info(ip)exec_ssh_one_cmd(host_info=host_info, command=remove_remote_prometheus_rule_cmd)def upload_prometheus_rules_file(self, ip: str, local_host: str) -> None:host_info = self._get_host_info(ip)upload_file_to_linux(host_info=host_info,local_path=local_host,remote_path=Config.PROMETHEUS_CONFIG_PATH)@staticmethoddef reload_prometheus_rules(ip: str) -> bool:url = f"http://{ip}:9090/-/reload"resp = requests.post(url=url)if resp.status_code == 200:logger.info(f"Success reload prom rule {ip}")return Trueelse:logger.error(f"Failed to reload prom rule {ip}")return Falsedef reload_prometheus_conf(self, prometheus_rule: dict) -> None:# 2.生成新的规则文件到本地self.generate_prometheus_yml()prometheus_ips = self.generate_prometheus_ips(prometheus_rule=prometheus_rule)# 3.获取ipfor prometheus_ip in prometheus_ips:# 4.读取远程规则作为旧规则作保障prom_old_rule = self.read_prom_config(ip=prometheus_ip)# 5.删除远程规则文件self.remove_remote_prometheus_rules(ip=prometheus_ip)# 6.上传新的规则文件self.upload_prometheus_rules_file(ip=prometheus_ip, local_host=Config.PROMETHEUS_CONFIG_LOCAL_PATH)# 7.进行远程reloadreload_result = self.reload_prometheus_rules(ip=prometheus_ip)# 8.若失败把旧的规则文件生成并上传远程服务器if not reload_result:# 9.生成旧的prom配置文件self.generate_old_prometheus_yml(prom_old_rule)# 10.上传旧的文件self.upload_prometheus_rules_file(ip=prometheus_ip, local_host=Config.PROMETHEUS_CONFIG_OLD_LOCAL_PATH)self.reload_prometheus_rules(ip=prometheus_ip)# 清楚临时生成的文件夹self.clear_conf_tmp_dir()class PrometheusView(PrometheusDbView, PrometheusRuleView):def get(self):rule_classify_id = request.values.get("ruleClassifyId")page = request.values.get("page")pagesize = request.values.get("pageSize")# 规则分类页面获取规则,没有分页if rule_classify_id is None and page is None and pagesize is None:prom_rules = self.get_prometheus_rule_by_db()return pretty_result(code=HttpCode.OK, data=prom_rules)if rule_classify_id == "0" or rule_classify_id is None:prom_rules = self.get_prometheus_rule_by_db()else:prom_rule_classify = PromRuleClassifyModel.objects_().get_by_id(int(rule_classify_id))if prom_rule_classify is None:prom_rules = []else:rule_ids = prom_rule_classify.rule_ids.split(",")prom_rule_obj = PromRulerModel.objects_().list_by_ids(rule_ids)prom_rules = []for prom_rule in prom_rule_obj:rule = {"datasource_id": prom_rule.datasource,"datasource": DataSourceModel.objects_().get_by_id(prom_rule.datasource).name,"description": prom_rule.description,"duration": prom_rule.duration,"expr": prom_rule.expr,"group_id": prom_rule.group,"group": GroupModel.objects_().get_by_id(prom_rule.group).name,"id": prom_rule.id,"severity": prom_rule.severity,"summary": prom_rule.summary,"heal": prom_rule.heal}if prom_rule.heal and int(prom_rule.heal) != 0:rule["heal_title"] = AlarmHeal.objects_().get_by_id(int(prom_rule.heal)).titleelse:rule["heal_title"] = ""prom_rules.append(rule)total = len(prom_rules)prom_rules = prom_rules[(int(page) - 1) * int(pagesize): int(page) * int(pagesize)]return pretty_result(code=HttpCode.OK, data={"prom_rules": prom_rules, "total": total})def post(self):prometheus_rule = request.get_json(force=True)# 1.规则存入数据库self.save_prometheus_rule_to_db(prometheus_rule=prometheus_rule)self.reload_prometheus_conf(prometheus_rule=prometheus_rule)return pretty_result(code=HttpCode.OK)def put(self):prometheus_rule = request.get_json(force=True)self.update_prometheus_rule_by_db(prometheus_rule=prometheus_rule)self.reload_prometheus_conf(prometheus_rule=prometheus_rule)return pretty_result(code=HttpCode.OK)def delete(self):prometheus_rule_id = request.get_json(force=True)prometheus_rule = self.delete_prometheus_rule(prometheus_rule_id=int(prometheus_rule_id))self.reload_prometheus_conf(prometheus_rule=prometheus_rule)return pretty_result(code=HttpCode.OK)
#!/usr/bin/env python
# -*- coding: UTF-8 -*-import os
import shutil
import tracebackfrom flask_restful import Resourcefrom kevin.log import loggerfrom config import Config
from data_entity import HostInfoclass MonitorMixin(Resource):@staticmethoddef _get_host_info(ip):host_info = HostInfo(hostname=ip,username=Config.MONITOR_USERNAME, # prometheus机器用户名password=Config.MONITOR_PASSWORD, # prometheus机器密码port=22)return host_info@staticmethoddef clear_conf_tmp_dir() -> None:try:tmp_path = os.path.join(Config.PROJECT_DIR, "tmp")shutil.rmtree(tmp_path)logger.info(f"Success clear conf tmp dir: {tmp_path}")except Exception as e:logger.error(f"Failed to clear conf tmp dir, error: {e}, {traceback.format_exc()}")@staticmethoddef generate_conf_tmp_dir() -> None:yaml_dir = os.path.join(Config.PROJECT_DIR, "tmp")if not os.path.isdir(yaml_dir):os.mkdir(yaml_dir)

3.接口实现

#!/usr/bin/env python
# -*- coding: UTF-8 -*-from .v1 import *from flask_restful import Apiapi = Api(prefix="/api/v1")
api.add_resource(PrometheusView, "/prometheusconfigs")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/46635.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能算法工程师(高级)课程1-单类目标识别之人脸检测识别技术MTCNN模型介绍与代码详解

大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(高级)课程1-单类目标识别之人脸检测识别技术MTCNN模型介绍与代码详解。本文深入探讨了基于PyTorch的人脸检测与识别技术,详细介绍了MTCNN模型、Siamese network以及center loss、sof…

11、实现基于共享内存的二叉树set

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 实现数组肯定不是我们的目标&a…

从数据库查询数据 写入Excel 写出JAVA代码

以下是一个示例代码,演示了如何从数据库中查询数据,然后将数据写入到Excel文件中: import java.io.FileOutputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import org.apache.poi.ss.user…

PostgreSQL创建表和自增序列

一、创建表: 注意: 1、在mysql没有序列的概念,id自增通过auto_increment实现; 2、pgsql没有auto_increment的概念,如何实现id自增?有两种方式: 方式一:创建序列,绑定…

面经学习(杭州实在智能实习)

个人评价 秃狼觉得本次的面试是有史以来难度最大的,问了很多陌生的八股文,项目问的比较少,估计是项目本来就没有什么亮点,也是第一次被面试官说菜的面试。不过在后续的学习上还是收获颇丰的。 1.说说你在实习中遇到的难点吧&…

K8S内存资源配置

在 Kubernetes (k8s) 中,资源请求和限制用于管理容器的 CPU 和内存资源。配置 CPU 和内存资源时,使用特定的单位来表示资源的数量。 CPU 资源配置 CPU 单位:Kubernetes 中的 CPU 资源以 “核” (cores) 为单位。1 CPU 核心等于 1 vCPU/Core…

SpringBoot RestHighLevelClient 按版本更新

SpringBoot RestHighLevelClient 按版本更新 1 查询2 更新 RestHighLevelClient 是 Elasticsearch 提供的一个用于与 Elasticsearch 集群交互的高级 REST 客户端。它是基于 Java 的客户端,旨在提供一种简单且功能丰富的方式来执行各种 Elasticsearch 操作&#xff0…

2024年海峡两岸创业青年研学交流项目火热开展中

7月17日,由浙江外国语学院国际商学院、创业学院主办的“文化之舟系两岸,潮头勇立浙商旗”——2024年海峡两岸大学生(创业青年)研学交流项目持续进行中。 上午,邵波副教授带领学生代表接待来自台湾的二十多名学生参加“…

利用 PHP 解锁 1688 详情 API 接口的秘密

在电商领域的探索中,1688 平台的商品详情数据无疑是一座宝藏。而通过 PHP 语言来解锁 1688 详情 API 接口的秘密,将为我们开启获取这一宝藏的大门。 一、深入了解 1688 详情 API 接口 1688 详情 API 接口提供了丰富的商品信息,包括商品描述、…

Linux输出重定向到文件立即输出

./md.out > output.txt 2>&1程序中断时,文件为空的原因可能是由于缓冲机制。标准输出(stdout)和标准错误输出(stderr)默认是缓冲的,这意味着数据在写入文件之前会先存储在缓冲区中。如果程序在缓…

【人工智能】在未来智慧城市的建设及应用分析

作者主页: 知孤云出岫 目录 作者主页:案例分析:人工智能在未来智慧城市的建设及其影响和应用引言一、人工智能在智慧城市中的关键应用领域 案例分析:人工智能在未来智慧城市的建设及其影响和应用 引言 智慧城市是利用信息和通信技术(ICT&am…

电平的概念及应用(电路节点在某一时刻的电压状态)(高电平、低电平)(电压是推动电荷通过导体的力,而电平是这种力的表达形式)

文章目录 电平的概念及其在电子与电气应用中的应用1. 电平的基本概念1.1 电压与电平1.2 电流与电压的区分 2. 数字电路中的电平应用2.1 逻辑电平2.1.1 TTL电平2.1.2 CMOS电平 2.2 电平转换 3. 模拟电路中的电平应用3.1 信号表示3.2 信号放大 4. 电平在通信技术中的应用4.1 RS-4…

迁移学习在乳腺浸润性导管癌病理图像分类中的应用

1. 引言 乳腺癌主要有两种类型:原位癌:原位癌是非常早期的癌症,开始在乳管中扩散,但没有扩散到乳房组织的其他部分。这也称为导管原位癌(DCIS)。浸润性乳腺癌:浸润性乳腺癌已经扩散(侵入)到周围的乳腺组织。侵袭性癌症比原位癌更难治愈。将乳汁输送到乳…

Android Navigation 组件原理和使用教程

Android Navigation 组件是用于简化导航相关操作的框架,允许你在应用中管理应用内各个部分之间的导航。该组件是Android Jetpack的一部分,主要包含三个部分:导航图(NavGraph)、NavHost和NavController。 一、原理 Nav…

Kafka Producer之幂等性

文章目录 1. 启用幂等性2. 底层变化3. 数据不重复4. 数据有序 幂等性通过消耗时间和性能的方式&#xff0c;解决乱序和重复问题。 但是只能保证同一生产者在一个分区中的幂等性。 1. 启用幂等性 //创建producerHashMap<String, Object> config new HashMap<>();…

怎样在 PostgreSQL 中优化对大表的分区裁剪和索引选择?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样在 PostgreSQL 中优化对大表的分区裁剪和索引选择一、分区裁剪&#xff1a;精准切割&#xff0c;提…

SQL Server 和 MySQL 的主要区别

架构 SQL Server 微软开发&#xff0c;闭源商业数据库运行在 Windows 和 Linux单一数据库引擎架构支持多个数据库实例和多种数据存储机制&#xff08;行存储和列存储&#xff09;包含数据库引擎、SQL Server Agent、SQL Server Reporting Services (SSRS)、SQL Server Integrat…

【自学安全防御】三、企业双机热备和带宽管理的综合实验

实验拓扑&#xff1a; 实验任务&#xff1a; 12&#xff0c;对现有网络进行改造升级&#xff0c;将当个防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW3&#xff0c;生产区和办公区的流量走FW1 13&#xff0c;办公区上网用户限制流…

QML基本类型

QML基本数据类型之 int使用案例代码 <span style"color:#4b4b4b"><span style"background-color:#ffffff"><code class"language-JavaScript"><span style"color:#008000">// 定义 >> 整型&#xff08…

go-zero框架入门

go-zero框架环境的安装 goctl 若想用go-zero框架&#xff0c;还需要一些前置条件&#xff1a; 安装goctl go install github.com/zeromicro/go-zero/tools/goctllatest可以使用 goctl 命令查看是否安装成功 成功后安装protoc goctl env check --install --verbose --force…