Prometheus导出 prometheus中自带的查询指标定义解析
一、导出带的定义docker mesos在生产环境的中自指标实践
我们是一家做生鲜电商的公司,从系统搭建初期,查询我们就采用微服务的解析架构,基于DevOps体系来不断提高我们的导出带的定义交付的质量和效率,随着业务和团队规模的中自指标发展,服务逐渐进行拆分,查询服务之间的解析交互越来越复杂,目前整个微服务已经近几十个应用模块,导出带的定义整体架构上包括负载均衡、中自指标API网关、查询基于Dubbo的解析微服务模块、缓存、导出带的定义队列、中自指标数据库等,查询目前整个集群的资源利用率也没有一个合理的规划评估,虚拟机上部署多个应用服务隔离性也存在问题,考虑到越来越多门店以及第三方流量的接入,需要考虑系统的快速的伸缩能力,而基于统一资源管理的Docker容器技术在这些方面有一些天然的优势,并且和微服务架构、DevOps体系完美衔接。
经过调研和对比,最终我们采用Mesos作为底层资源的管理和调度,Marathon作为Docker执行的框架,配合ZooKeeper、Consul、Nginx作为服务注册发现。目前已经有部分的核心业务已经平稳的运行在基于Docker容器的Mesos资源管理平台上。
逻辑架构
部署架构
在发布流程中,在发布上线之前的环节是预发布,预发布环境验证完成后进行打包,生成Docker镜像和基于虚拟机部署的应用部署包,push到各自对应的仓库中,并打Tag。
生产环境发布过程中,同时发布到Mesos集群和原有的虚拟机集群上,两套集群网络是打通的。
网络架构
在网络架构选型时,会考虑一下几个原则:
docker bridge使用默认的docker0网桥,容器有独立的网络命名空间,跨主机的容器通信需要做端口NAT映射;Host的方式采用和宿主机一样的网络命名空间,网络无法做隔离,等等这些方式有非常多的端口争用限制,效率也较低。
Docker Overlay的方式,可以解决跨主机的通信,现有二层或三层网络之上再构建起来一个独立的网络,这个网络通常会有自己独立的IP地址空间、交换或者路由的实现。
Docker在libnetwork团队提供了multi-host网络功能,能完成Overlay网络,主要有隧道和路由两种方式,隧道原理是对基础的网络协议进行封包,代表是Flannel。
另外一种是在宿主机中实现路由配置实现跨宿主机的容器之间的通信,比如Calico。
Calico是基于大三层的BGP协议路由方案,没有使用封包的隧道,没有NAT,性能的损耗很小,支持安全隔离防护,支持很细致的ACL控制,对混合云亲和度比较高。经过综合对比考虑,我们采用calico来实现跨宿主机的网络通讯。
安装好ETCD集群,通过负载均衡VIP方式(LVS+keepalived)来访问ETCD集群。
ETCD_AUTHORITY=10.10.195.193:2379
export ETCD_AUTHORITY
构建Calico网络集群,增加当前节点到集群中,Calico节点启动后会查询 Etcd,和其他 Calico节点使用 BGP协议建立连接。
./calicoctl node–libnetwork–ip=10.10.3.210
增加可用的地址池ip pool
./calicoctl pool add 10.4.10.0/24–nat-outgoing
./calicoctl pool show
创建网络,通过Calico IPAM插件(Driver(包括IPAM)负责一个Network的管理,包括资源分配和回收),-d指定驱动类型为Calico,创建一个online_net的driver为Calico的网络:
docker network create-d calico–ipam-driver calico–subnet=10.4.10.0/24 online_net
启动容器,网络指定刚才创建的online_net,容器启动时,劫持相关 Docker API,进行网络初始化。查询 Etcd自动分配一个可用 IP,创建一对veth接口用于容器和主机间通讯,设置好容器内的 IP后,打开 IP转发,在主机路由表添加指向此接口的路由,宿主机10.10.3.210的路由表:
宿主机10.10.50.145的路由表:
容器包发送包的路由过程如上图,宿主机10.10.3.210上的容器IP 10.4.10.64通过路由表发送数据包给另外一个宿主机10.10.50.145的容器10.4.10.55。
对于有状态的数据库,缓存等还是用物理机(虚拟机),来的应用集群用的是虚拟机,Docker容器集群需要和它们打通,做服务和数据的访问交互。那么只需要在物理机(虚拟机)上把当前节点加入容器网络集群即可:
ETCD_AUTHORITY=10.10.195.193:2379
export ETCD_AUTHORITY
./calicoctl node–ip=10.10.16.201
服务自注册和发现
API网关提供统一的API访问入口,分为两层,第一层提供统一的路由、流控、安全鉴权、WAF、灰度功能发布等功能,第二层是Web应用层,通过调用Dubbo服务来实现服务的编排,对外提供网关的编排服务功能,屏蔽业务服务接口的变更;为了能够快速无缝的实现web层快速接入和扩容,我们用Consul作为服务注册中心实现Web服务的自动注册和发现。
对于Web服务注册,我们自己实现了Register,调用Consul的API进行注册,并通过TTL机制,定期进行心跳汇报应用的健康状态。
对于Web服务的发现,我们基于Netflix Zuul进行了扩展和改造,路由方面整合Consul的发现机制,并增加了基于域名进行路由的方式,对路由的配置功能进行了增强,实现配置的动态reload功能。API网关启动定时任务,通过Consul API获取Web服务实例的健康状态,更新本地的路由缓存,实现动态路由功能。
平台的微服务框架是基于Dubbo RPC实现的,而Dubbo依赖ZooKeeper做服务的发现和注册。
Consul在Mesos Docker集群的部署方案:
不建议把Consul Agent都和Container应用打包成一个镜像,因此Consul Agent部署在每个Mesos Slave宿主机上,那么Container如何获取宿主机的IP地址来进行服务的注册和注销,容器启动过程中,默认情况下,会把当前宿主机IP作为环境变量传递到Container中,这样容器应用的Register模块就可以获取Consul代理的IP,调用Consul的API进行服务的注册和卸载。
在日常应用发布中,需要保障发布过程对在线业务没有影响,做到无缝滚动的发布,那么在停止应用时应通知到路由,进行流量切换。
docker stop命令在执行的时候,会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强行kill掉进程。这样我们可以让程序在接收到SIGTERM信号后,有一定的时间处理、保存程序执行现场,优雅的退出程序,我们在应用的启动脚本中实现一段脚本来实现信号的接受和处理,接收到信号后,找到应用的PID,做应用进程的平滑kill。
应用的无缝滚动发布、宕机恢复
Marathon为运行中的应用提供了灵活的重启策略。当应用只有一个实例在运行,这时候重启的话,默认情况下Marathon会新起一个实例,在新实例重启完成之后,才会停掉原有实例,从而实现平滑的重启,满足应用无缝滚动发布的要求。
当然,可以通过Marathon提供的参数来设置自己想要的重启策略:
“upgradeStrategy”:{ “minimumHealthCapacity”: N1,“maximumOverCapacity”: N2}
如何判断新的实例是否启动完成可以提供服务,或者当前容器的应用实例是否健康,是否实例已经不可用了需要恢复,Marathon提供了healthchecks健康监测模块
"healthChecks": [{
"protocol":"COMMAND",
"command":{
"value":"sh/data/soft/healthcheck.sh app 10.10.195.193"
},
"gracePeriodSeconds": 90,
"intervalSeconds": 60,
"timeoutSeconds": 50,
"maxConsecutiveFailures": 3
}]
healthcheck.sh通过负载均衡调用HealthMonitor来获取应用实例的监控状态, HealthMonitor是我们的健康检查中心,可以获取应用实例的整个拓扑信息。
容器监控、日志
对于容器的监控,由于我们是采用Mesos Docker的容器资源管理的架构,因此采用mesos-exporter+Prometheus+Grafana的监控方案,mesos-exporter的特点是可以采集 task的监控数据,可以从task的角度来了解资源的使用情况,而不是一个一个没有关联关系的容器。mesos-exporter导出Mesos集群的监控数据到Prometheus,Prometheus是一套监控报警、时序数据库组合,提供了非常强大存储和多维度的查询,数据的展现统一采用Grafana。
二、prometheus中自带的查询指标定义解析
参考: prometheus中文手册
go_gc_duration_seconds:持续时间秒
go_gc_duration_seconds_sum:gc-持续时间-秒数-总和
go_memstats_alloc_bytes:Go内存统计分配字节
go_memstats_alloc_bytes_total:Go内存统计分配字节总数
go_memstats_buck_hash_sys_bytes:用于剖析桶散列表的堆空间字节
go_memstats_frees_total:内存释放统计
go_memstats_gc_cpu_fraction:垃圾回收占用服务CPU工作的时间总和
go_memstats_gc_sys_bytes:圾回收标记元信息使用的内存字节
go_memstats_heap_alloc_bytes:服务分配的堆内存字节数
go_memstats_heap_idle_bytes:申请但是未分配的堆内存或者回收了的堆内存(空闲)字节数
go_memstats_heap_inuse_bytes:正在使用的堆内存字节数
go_memstats_heap_objects:堆内存块申请的量
go_memstats_heap_released_bytes:返回给OS的堆内存
go_memstats_heap_sys_bytes:系统分配的作为运行栈的内存
go_memstats_last_gc_time_seconds:垃圾回收器最后一次执行时间
go_memstats_lookups_total:被runtime监视的指针数
go_memstats_mallocs_total:服务malloc的次数
go_memstats_mcache_inuse_bytes:mcache结构体申请的字节数(不会被视为垃圾回收)
go_memstats_mcache_sys_bytes:操作系统申请的堆空间用于mcache的字节数
go_memstats_mspan_inuse_bytes:用于测试用的结构体使用的字节数
go_memstats_mspan_sys_bytes:系统为测试用的结构体分配的字节数
go_memstats_next_gc_bytes:垃圾回收器检视的内存大小
go_memstats_other_sys_bytes:golang系统架构占用的额外空间
go_memstats_stack_inuse_bytes:正在使用的栈字节数
go_memstats_stack_sys_bytes:系统分配的作为运行栈的内存
go_memstats_sys_bytes:服务现在系统使用的内存
go_threads:线程
jvm_buffer_count_buffers:jvm缓冲区计数缓冲区:
jvm_buffer_memory_used_bytes:jvm缓冲区内存已用字节
jvm_buffer_total_capacity_bytes:jvm缓冲区总容量字节
jvm_classes_loaded_classes:jvm_classes加载的类
jvm_classes_unloaded_classes_total:自Java虚拟机开始执行以来已卸载的类总数
jvm_gc_max_data_size_bytes:jvm_gc_最大数据大小字节:
jvm_gc_memory_allocated_bytes_total:在一个GC之后到下一个GC之前增加年轻代内存池的大小
jvm_gc_memory_promoted_bytes_total:GC之前到GC之后,老年代的大小正向增加的计数
system_cpu_count:Java虚拟机可用的处理器数量
process_uptime_seconds:Java虚拟机的正常运行时间
jvm_threads_states_threads:当前处于NEW状态的线程数
jvm_memory_committed_bytes:可供Java虚拟机使用的已提交的内存量
system_cpu_usage:最近的cpu利用率
jvm_threads_peak_threads:自Java虚拟机启动或重置峰值以来的活动线程峰值
jvm_memory_used_bytes:已用内存量
jvm_threads_daemon_threads:当前活动的守护程序线程数
process_cpu_usage:JVM的CPU利用率
process_start_time_seconds:进程的开始时间
jvm_gc_max_data_size_bytes:老年代的最大内存量
jvm_gc_live_data_size_bytes:full GC老年代的大小
jvm_threads_live_threads:当前活动线程数,包括守护程序线程和非守护程序线程
jvm_buffer_memory_used_bytes:已使用缓冲池大小
jvm_buffer_count_buffers:缓冲区数量
logback_events_total:日志备份事件总计
net_conntrack_dialer_conn_attempted_total:网络连接拨号尝试次数总计
net_conntrack_dialer_conn_closed_total:网络连接拨号器关闭总计
net_conntrack_dialer_conn_established_total:网络连接拨号器建立网络连接总数
net_conntrack_dialer_conn_failed_total:网络连接拨号失败总计
net_conntrack_listener_conn_accepted_total:网络连接监听接受总计
net_conntrack_listener_conn_closed_total:网络连接监听关闭总计
prometheus_rule_evaluation_duration_seconds:所有的 rules(recording/alerting)的计算的时间(分位值),这个可以用来分析规则是否过于复杂以及系统的状态是否繁忙
prometheus_rule_evaluation_duration_seconds_count:执行所有的 rules的累积时长,没怎么用到
prometheus_rule_group_duration_seconds:具体的 rule group的耗时
prometheus_rule_group_interval_seconds:具体的 rule group的执行间隔(如果没有异常,应该和配置中的一致,如果不一致了,那很可能系统负载比较高)
prometheus_rule_group_iterations_missed_total:因为系统繁忙导致被忽略的 rule执行数量
prometheus_rule_group_last_duration_seconds:最后一次的执行耗时
prometheus_tsdb_blocks_loaded:当前已经加载到内存中的块数量
prometheus_tsdb_compactions_triggered_total:压缩操作被触发的次数(可能很多,但不是每次出发都会执行)
prometheus_tsdb_compactions_total:启动到目前位置压缩的次数(默认是 2小时一次)
prometheus_tsdb_compactions_failed_total:压缩失败的次数
prometheus_tsdb_head_chunks:head中存放的 chunk数量
prometheus_tsdb_head_chunks_created_total:head中创建的 chunks数量
prometheus_tsdb_head_chunks_removed_total:head中移除的 chunks数量
prometheus_tsdb_head_gc_duration_seconds:head gc的耗时(分位值)
prometheus_tsdb_head_max_time:head中的有效数据的最大时间(这个比较有价值)
prometheus_tsdb_head_min_time:head中的有效数据的最小时间(这个比较有价值)
prometheus_tsdb_head_samples_appended_total:head中添加的 samples的总数(可以看增长速度)
prometheus_tsdb_head_series:head中保存的 series数量
prometheus_tsdb_reloads_total:rsdb被重新加载的次数
prometheus_local_storage_memory_series:时间序列持有的内存当前块数量
prometheus_local_storage_memory_chunks:在内存中持久块的当前数量
prometheus_local_storage_chunks_to_persist:当前仍然需要持久化到磁盘的的内存块数量
prometheus_local_storage_persistence_urgency_score:紧急程度分数
prometheus_local_storage_memory_chunks:本地存储器内存块
process_resident_memory_bytes:进程内存字节
prometheus_notifications_total(针对Prometheus服务器)
process_cpu_seconds_total(由客户端库导出)
http_request_duration_seconds(用于所有HTTP请求)
system_cpu_usage:系统cpu使用率
tomcat_cache_access_total:tomcat缓存访问总计
tomcat_global_error_total:tomcat全局错误总计
tomcat_global_received_bytes_total:tomcat_全局接收到的字节总数
tomcat_global_request_max_seconds:tomcat全局请求最大秒数
tomcat_global_request_seconds_count:tomcat全局请求秒数
tomcat_global_request_seconds_sum:tomcat全局请求秒数求和
tomcat_global_sent_bytes_total:tomcat全局发送字节总计
tomcat_servlet_error_total:tomcat_servlet错误总计
tomcat_servlet_request_max_seconds:tomcat_servlet_请求最大秒数
tomcat_servlet_request_seconds_count:tomcat_servlet_请求秒数
tomcat_servlet_request_seconds_sum:tomcat_servlet_请求秒数求和
tomcat_sessions_active_current_sessions:tomcat_当前活跃会话数
tomcat_sessions_active_max_sessions:tomcat_活跃会话最大数量
tomcat_sessions_created_sessions_total:tomcat会话创建会话总数
tomcat_sessions_expired_sessions_total:tomcat过期会话数总计
tomcat_sessions_rejected_sessions_total:tomcat拒绝会话数总计
tomcat_threads_busy_threads:tomcat繁忙线程
tomcat_threads_current_threads:tomcat线程当前线程数
三、Flink Metrics指标采集方案
本文讨论的都是基于Flink On K8s场景下,该场景下存在几个特点,一是存在线上业务系统资源复用,二是调度节点存在"随机性",对现有的Flink Metrics采集及使用姿势提出了新的要求:
Flink任务自动扩缩容,智能诊断场景依赖Metrics指标进行加工分析处理,现有Prometheus存储方案不再适合。
既有的指标采集需要先落本地,再由nodeexporter或lancer导出到目标存储,强依赖于Local环境,线上业务系统资源环境差异较大,扩容等维护成本较高,资源隔离性不够好。
期望在Flink On K8s场景下,Flink Metrics指标采集,能够不依赖于基础环境,对扩缩容友好,,支持指标采集及分析数据存储统一,降低指标维护使用成本,对Flink Metrics指标采集方案进行调研
2.1.1、原理架构图如下
2.1.2、配置方式
将flink-metrics-prometheus-1.14.3.jar包放入到flink安装目录/lib下
修改flink-conf.yaml配置文件,设置属性
Example configuration:
metrics.reporter.promgateway.class: org.apache.flink.metrics.prometheus.PrometheusPushGatewayReporter
metrics.reporter.promgateway.host: localhost
metrics.reporter.promgateway.port: 9091
metrics.reporter.promgateway.jobName: myJob
metrics.reporter.promgateway.randomJobNameSuffix: true
metrics.reporter.promgateway.deleteOnShutdown: false
metrics.reporter.promgateway.groupingKey: k1=v1;k2=v2
metrics.reporter.promgateway.interval: 60 SECONDS
2.2.1、原理架构图如下
2.2.2、配置方式
将flink-metrics-prometheus-1.14.3.jar包放入到flink安装目录/lib下
修改flink-conf.yaml配置文件,设置属性
Example configuration:
metrics.reporter.prom.class: org.apache.flink.metrics.prometheus.PrometheusReporter
metrics.reporter.prom.port: 9250-9260
2.3..1、原理架构图如下
2.3.2、配置方式
将flink-metrics-influxdb-1.14.3.jar包放入到flink安装目录/lib下
修改flink-conf.yaml配置文件,设置属性
Example configuration:
metrics.reporter.influxdb.factory.class: org.apache.flink.metrics.influxdb.InfluxdbReporterFactory
metrics.reporter.influxdb.scheme: http
metrics.reporter.influxdb.host: localhost
metrics.reporter.influxdb.port: 8086
metrics.reporter.influxdb.db: flink
metrics.reporter.influxdb.username: flink-metrics
metrics.reporter.influxdb.password: qwerty
metrics.reporter.influxdb.retentionPolicy: one_hour
metrics.reporter.influxdb.consistency: ANY
metrics.reporter.influxdb.connectTimeout: 60000
metrics.reporter.influxdb.writeTimeout: 60000
metrics.reporter.influxdb.interval: 60 SECONDS
2.4.1、原理架构图如下
2.4.2、配置方式
将flink-metrics-jmx-1.14.3.jar包放入到flink安装目录/lib下
修改flink-conf.yaml配置文件,设置属性
Example configuration:
metrics.reporter.jmx.factory.class: org.apache.flink.metrics.jmx.JMXReporterFactory
metrics.reporter.jmx.port: 9250-9260
2.5.1、配置方式
将flink-metrics-slf4j-1.14.3.jar包放入到flink安装目录/lib下
修改flink-conf.yaml配置文件,设置属性
Example configuration:
metrics.reporter.slf4j.factory.class: org.apache.flink.metrics.slf4j.Slf4jReporterFactory
metrics.reporter.slf4j.interval: 60 SECONDS
GraphiteReporter、StatsDReporter、DatadogHttpReporter
指标采集到Kafka后,将全量指标实时写入ClickHouse.
指标采集到Kafka后,将全量指标实时写入ClickHouse同时满足监控大盘需求及指标数据长期存储和二次加工分析,该方式优势指标数据源统一,任务大盘及告警
参考资料:全景性能监控