postgres_exporter并使用多个数据库监视PostgreSQL实例

UPD:该注释与0.8.0版本失去了联系。 所有创新都可以在文章中找到: 用于监控PostgreSQL的postgres_exporter的新功能


下午好,哈伯读者!


普罗米修斯及其出口商(代理商)生态系统是任何管理员和开发人员的好工具。 易于交付,简单(相对)设置以及使用自动检测服务的能力。
但这与Prometheus无关,而与著名的代理商之一postgres_exporter有关。 它允许您使用PostgreSQL收集指标。 但是如果一切都这么简单...


不幸的是,postgres_exporter文档是相当苦行的,只影响一般情况。 但是,如果您有一个包含多个数据库的DBMS集群实例,并且/或者想一次为该集群的多个实例收集指标,该怎么办?


目的


实际上,是关于文章的目的或更确切地说是注释。 我立即注意到,在这里我将不描述Prometheus和postgres_exporter的组装或配置过程以及它们之间的相互作用。 所有这些都在文档和许多其他来源中进行了描述。


我想谈谈使用postgres_exporter解决特定问题的一些特殊情况,即由一个代理通过以下方式收集指标:


  1. 一个实例中的多个数据库;
  2. 几份;
  3. 不同实例上的多个数据库。

postgres_exporter


主观上,利弊。


从优点:


  1. 第一个也是重要的优势是易于交付和配置代理。 代理-是可执行文件(可选,是具有一组用户指标的yaml文件)。 这是一个针对必需的分发和体系结构进行编译的自包含应用程序,不需要在服务器上安装其他软件包。 该代理既可以安装在与群集实例相同的节点上,也可以安装在单独的节点上。
  2. 代理作为常规sql客户端连接到DBMS。 可以通过inet或通过unix套接字进行连接;
  3. 一种代理从多个实例实例和/或一个实例的多个数据库接收度量的能力;
  4. 根据Prometheus或其他收集者的要求收集度量标准;
  5. 通过简单的HTTP请求接收指标的能力;
  6. 代理自动接收单个PostgreSQL实例上的数据库列表(具有postgres_exporter 0.5.0+版本)后,出现了--auto-discover-databases选项。

缺点:


  1. 缺乏授权;
  2. 仅通过HTTP进行数据传输。 所有指标将以明文形式传输。 这很不好,因为攻击者在被拦截时可以获得可靠的数据库和角色列表。
  3. 不缓存指标。 因此,例如,当代理对于网络不可用时,Prometheus将不会接收不可用时间段的数据。
  4. 使用--auto-discover-databases选项时,无法从列表中排除某些数据库。 这是暂时的,因为在下一个发行版中应该已经出现了这种可能性(选项--exclude-databases)。

一个实例中的多个数据库


好吧,让我们继续练习。 假设我们有一个带有多个数据库的PostgreSQL实例,我们需要组织实例指标和所有数据库的集合。
为什么我要分离数据库指标和集群实例的集合,一切都非常简单,postgres_exporter在同一集群上使用多个数据库的场景暗示了在不同数据库中执行同一组sql查询。 结果,当尝试从pg_stat_replication,pg_stat_activity,pg_stat_statement视图等中获取指标时。 对于集群来说是通用的,在理解postgres_exporter的过程中,我们总是得到相同的度量标准集,这将导致重复的键和值,从而导致错误。
让我们看看它在实际中的外观。


我们有一个带有一组数据库的测试实例:


List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+------------+------------+----------------------- dbtest1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | dbtest2 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | dbtest3 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | 

我们使用选项--auto-discover-databases启动postgres_exporter(如果未在连接字符串中指定数据库名称,则将使用用户名建立与数据库的连接):


 $ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/?sslmode=disable" ./postgres_exporter --auto-discover-databases --log.format=logger:stdout 

  • DATA_SOURCE_NAME-环境变量,包含用于连接到PostgreSQL实例的参数

在代理的输出中,我们观察到一幅田园诗般的图片,它已启动并能够连接到集群中的所有数据库(尽管它不会写入哪个数据库,但希望可以解决此问题):


 INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Starting Server: :9187 source="postgres_exporter.go:1490" 

我认为细心的读者会注意到集群中有四个基础(postgres,dbtest1,dbtest2和dbtest3,template0和template1被忽略),并且有五个连接。 在我们的例子中,postgres_exporter创建到postgres数据库的两个连接。 使用此功能时,您需要非常小心。 怎么了 我们将进一步了解这一点。


好吧,让我们继续尝试获取指标:


 $ curl http://localhost:9178/metrics 

结果,在输出中,我们收到有关“以前用相同的名称和标签值收集的重复项”的警告(但在postgres_exporter日志中,我们将看不到警告):


 ... * collected metric pg_stat_activity_max_tx_duration label:<name:"datname" value:"dbtest1" > label:<name:"server" value:"127.0.0.1:5432" > label:<name:"state" value:"fastpath function call" > gauge:<value:0 > was collected before with the same name and label values * collected metric pg_stat_bgwriter_checkpoints_timed label:<name:"server" value:"127.0.0.1:5432" > counter:<value:1 > was collected before with the same name and label values ... 

摆脱错误的唯一方法是默认情况下禁用指标收集。 有两种方法可以执行此操作:首先将环境变量PG_EXPORTER_DISABLE_DEFAULT_METRICS和PG_EXPORTER_DISABLE_SETTINGS_METRICS设置为true或使用选项--disable-default-metrics和--disable-settings-metrics


使用其他选项重新启动postgres_exporter:


 $ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/?sslmode=disable" ./postgres_exporter --auto-discover-databases --log.format=logger:stdout --disable-default-metrics --disable-settings-metrics 

尝试获取指标:


 $ curl http://localhost:9178/metrics 

因此,一切都按计划进行,但是输出中没有与PostgreSQL相关的单个指标:


 # HELP go_gc_duration_seconds A summary of the GC invocation durations. # TYPE go_gc_duration_seconds summary go_gc_duration_seconds{quantile="0"} 0 go_gc_duration_seconds{quantile="0.25"} 0 go_gc_duration_seconds{quantile="0.5"} 0 go_gc_duration_seconds{quantile="0.75"} 0 go_gc_duration_seconds{quantile="1"} 0 go_gc_duration_seconds_sum 0 go_gc_duration_seconds_count 0 ... # HELP process_virtual_memory_bytes Virtual memory size in bytes. # TYPE process_virtual_memory_bytes gauge process_virtual_memory_bytes 1.3832192e+07 

此外,为了获得有效负载,我们需要创建一个文件来描述我们想要接收的指标(别忘了,我们只能收集特定于数据库的指标)。


对于测试,我们将从pg_statio_user_tables关系中收集指标。 为此,请创建一个具有以下内容的querys.yaml文件:


 pg_statio_user_tables: query: "SELECT current_database() as datname, schemaname, relname, heap_blks_read, heap_blks_hit FROM pg_statio_user_tables" metrics: - datname: usage: "LABEL" description: "Name of database" - schemaname: usage: "LABEL" description: "Name of the schema that this table is in" - relname: usage: "LABEL" description: "Name of this table" - heap_blks_read: usage: "COUNTER" description: "Number of disk blocks read from this table" - heap_blks_hit: usage: "COUNTER" description: "Number of buffer hits in this table" 

我认为在这里有必要澄清一点,即添加要在其中执行查询的数据库的名称。 这是一项强制性要求,并且至少有两个原因:


  1. 数据库可能具有同名的表,这将由于重复度量而导致错误;
  2. 否则,您将无法确定指标所引用的数据库,这将把收集到的数据变成垃圾。

因此,我们使用--extend.query-path选项启动代理(此处显示了带有指标描述的yaml文件的路径):


 DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432?sslmode=disable" ./postgres_exporter --log.format=logger:stdout --auto-discover-databases --disable-default-metrics --disable-settings-metrics --extend.query-path=./queries.yaml 

我们正在尝试获取指标(为清楚起见,我们仅采用pg_statio_user_tables_heap_blks_hit):


 curl -s http://localhost:9187/metrics | grep pg_statio_user_tables_heap_blks_hit 

结果,我们得到一组唯一解释的指标:


 # HELP pg_statio_user_tables_heap_blks_hit Number of buffer hits in this table # TYPE pg_statio_user_tables_heap_blks_hit counter pg_statio_user_tables_heap_blks_hit{datname="dbtest1",relname="t1",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest1",relname="t2",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest2",relname="t1",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest2",relname="t2",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest3",relname="t1",schemaname="public",server="127.0.0.1:5432"} 0 pg_statio_user_tables_heap_blks_hit{datname="dbtest3",relname="t2",schemaname="public",server="127.0.0.1:5432"} 0 

结果,我们有机会使用--auto-discover-databases选项从集群的一个实例的所有数据库中收集指标。 一个不错的好处是,当您添加新数据库时,无需重新启动代理。
但是,尽管如此,我们仍然没有实例指标。 目前,解决方案只是一种-使用不同的代理来收集数据库和实例指标。
当然,它看起来不太好,但是可以通过对代理进行分组以收集来自多个实例的指标来消除这种麻烦。 我们将在下面考虑这另一个有趣的机会。


“额外”联系之谜的答案

请记住,在一开始,我们提请注意“额外”连接,因此,这是postgres_exporter的功能,带有--auto-discover-databases选项。
但是,为什么这会引起很多麻烦呢? 实际上,一切都很简单,并且已经在上面进行了描述,也就是说,问题在于postgres_exporter将两次从postgres数据库收集度量并开始复制度量。 在我们的案例中,只有--exclude-databases选项的外观才有帮助(因此我们期待下一个版本)。
是的,如果您在postgres数据库中有用户表,那么上面的示例将不起作用。


多个实例


好吧,继续前进。 我们找到了如何从多个数据库获取指标的方法,现在我们将考虑使用一个代理监视多个实例的选项。 非常简单,为此只需在环境变量DATA_SOURCE_NAME中将它们列出,并用逗号分隔就可以了:


 $ DATA_SOURCE_NAME="postgresql://postgres@127.0.0.1:5432/postgres?sslmode=disable,postgresql://postgres@127.0.0.1:5434/postgres?sslmode=disable" ./postgres_exporter --log.format=logger:stdout 

在这里,我们连接到在本地节点上运行的两个不同的集群实例。 这是日志中的样子:


 INFO[0000] Established new database connection to "127.0.0.1:5432". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5432": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Established new database connection to "127.0.0.1:5434". source="postgres_exporter.go:788" INFO[0000] Semantic Version Changed on "127.0.0.1:5434": 0.0.0 -> 11.5.0 source="postgres_exporter.go:1251" INFO[0000] Starting Server: :9187 source="postgres_exporter.go:1490" 

接下来,我们尝试获取指标(为清楚起见,我们将自己限制为pg_stat_database_blk_read_time指标):


 curl -s http://localhost:9187/metrics | grep pg_stat_database_blk_read_time 

结果,我们从一个代理获取了两个实例的指标:


 # HELP pg_stat_database_blk_read_time Time spent reading data file blocks by backends in this database, in milliseconds # TYPE pg_stat_database_blk_read_time counter pg_stat_database_blk_read_time{datid="1",datname="template1",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="1",datname="template1",server="127.0.0.1:5434"} 0 pg_stat_database_blk_read_time{datid="13116",datname="template0",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="13116",datname="template0",server="127.0.0.1:5434"} 0 pg_stat_database_blk_read_time{datid="13117",datname="postgres",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="13117",datname="postgres",server="127.0.0.1:5434"} 0 pg_stat_database_blk_read_time{datid="16384",datname="dbtest1",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="16385",datname="dbtest2",server="127.0.0.1:5432"} 0 pg_stat_database_blk_read_time{datid="16386",datname="dbtest3",server="127.0.0.1:5432"} 0 

在这种情况下,一切都比一个实例上的多个数据库要简单得多。 同时,我们仍然有机会从所有实例接收全局指标。


总结


因此,为达到目的而指出的第三种情况是上述两种情况的结合,因此我认为没有理由提出这一点。


因此,我认为最重要的是postgres_exporter,它是一个非常有趣且很有前途的管理员工具,用于监视PostgreSQL集群实例和在其上部署的数据库。 但是由于其年代久远,并非没有缺点可以理解和原谅。


资料来源


  • Prometheus [ 1 ]是用于监视和警报事件的开源应用程序。 它将实时指标写入到使用HTTP请求模型构建的时间序列数据库中,并具有灵活的查询和实时警报。
  • postgres_exporter是Prometheus的PostgreSQL指标的导出器。

撰写本文时,版本为0.5.1。 支持的PostgreSQL 9.4+版本(源代码中注明了9.1+版本的限制)。

Source: https://habr.com/ru/post/zh-CN468573/


All Articles