带你读《Elastic Stack 实战手册》之76:——4.2.2.Elasticsearch智能巡检开发设计实践(1)
4.2.2.Elasticsearch智能巡检开发设计实践创作人:张妙成审稿人:田雪松?项目背景?PaaS 下管理了大量集群,监控和告警能快速的让开发维护人员,知道系统已经发生故障,并且辅助高效排障。?但是无法提前预知集群的健康状况,开发人员和维护人员均无法在故障前及时作出调整。为了帮助用户及时的知道集群的健康状态,更好使用 Elasticsearch 集群,可以定期对集群进行指标检查并给出相应报告。巡检作业及时发现集群的健康问题,集群的配置是否合理,提前主动发现问题,能有效保证集群的稳定性、健状性,从而减少业务中断时间保证服务质量。?为了解决集群健康状态提前预知困难的问题,可以通过抽取一些指标,进行定时检查达到健康诊断的目的。?巡检主要是对集群的各个指标检查,给出一份全方位的报告,并提供一定的推荐解决、优化方案。如阿里的 EYOU 平台(便宜云服务器 Elasticsearch 智能诊断系统)会系统的在 Elasticsearch 公有云进行各个指标的检查,并给出相应报告,极大的减小了风险,降低了维护成本。?智能管理系统不是一个独立的检查系统,而是一个与其他系统相结合的闭环系统,独立的巡检模块对各项指标进行检查分析,将结果通过 PaaS 系统展示给用户,并在 PaaS 中给予入口,用以帮助用户手动再次触发检查,增强实时性,提高用户体验。?本文将介绍智能巡检系统在整个 Elasticsearch 相关系统中的位置与意义,并从指标分析选取、异常标准的角度,主要阐述智能巡检系统的设计与实现。整个应用的框架如上:?l?Elasticsearch 集群在 K8S 环境中(实际生产大多是 K8S 环境与物理机、虚拟机环境共存,这里简化成最终要达到的统一环境),由 PaaS 平台进行统一管理。l?PaaS 的信息数据主要是与 DB 交互(PaaS 是与 DB 的唯一交互入口),用户主要与l?PaaS平台进行交互。智能巡检系统信息收集模块(一组 Python Job)主要是 K8S 环境中的 Elasticsearchl?cluster、宿主机进行交互,数据报告信息通过 PaaS 平台存入 DB。l?监控使用 VictoriaMetrics( Prometheus 的高可用方案)作为存储,grafana 作为前端展示页面。监控可以配置 Elasticsearch 各项指标,其中与智能巡检相关是巡检异常数量的监控面板,用来给 OPS 观察巡检亚健康集群异常点的修复(优化)情况。l?PaaS 提供入口手动触发再次检查。指标选取简介?巡检的指标、异常阈值与告警配置的主要区别是,检的指标项会更加关心可能引发故障的某些现象和配置,参考阈值相对告警配置会更加宽松。巡检主要是通过指标的采集分析,得出一份相对全面的报告和推荐解决方案。为了报告的全面性与分析的准确性,巡检的指标项会与告警配置有一定相似或重复。?告警与巡检需要解决的问题不同,告警的目的是将异常指标恢复到正常状态,响应的实时性要求较高,而巡检的目的是预防故障、消除隐患、优化集群性能,以报告的形式推到平台和用户,不需要用户主动响应,只需解决问题后重新触发巡检。为推进优化,可将巡检报告中非健康指标配置成监控面板、告警。?集群健康程度可以从几个方面表现:cluster 层面、node 层面、shard 层面、index 层面、jvm 层面、threadpool 层面。如下为参考指标:Elasticsearch 功能强大、使用方便,也就意味着对用户来说有很多的默认设置,用户使用的自由度很高,也就意味着开放的能力丰富,用户的使用对集群健康程度有着很大的影响。?所以指标选取需要从两个角度,一是现有的现象指标,二是常用不合理的配置指标。接下来对选取的指标进行简要逐一分析。??《Elastic Stack 实战手册》——四、应用实践——4.2 可观测性应用场景 ——4.2.2.Elasticsearch智能巡检开发设计实践(2) /article/1226094
带你读《Elastic Stack 实战手册》之75:——4.2.1.基于Elasticsearch实现预测系统(2)
《Elastic Stack 实战手册》——四、应用实践——4.2 可观测性应用场景 ——4.2.1.基于Elasticsearch实现预测系统(1) /article/1226137Prometheus 与 Elasticsearch 的数据同步?Prometheus 支持一种称为远程读写(Remote Read/Write)的功能,可以在 Prometheus 拉取监控数据时将数据写入到远程的数据源中,或者从远程数据源中读取监控数据做处理。?Prometheus 目前支持的远程数据源多达几十种,所有数据源都支持远程写入,但并不是所有数据源都同时支持远程读取,比如我们这里要使用的 Elasticsearch 就只支持远程写入。注:7.10版本是支持的,可以通过 Metricbeat 对 Prometheus 进行远程拉取,参见:https://www.elastic.co/guide/en/beats/metricbeat/current/metricbeat-metricset-prometheus-query.html?Prometheus 为远程读取和写入,分别定义了独立的通信与编码协议,第三方存储组件需要向Prometheus 提供兼容该协议的 HTTP 接口地址。但由于众多第三方存储组件接收数据的方式并不相同,支持 Prometheus 读写协议的接口地址并不一定存在。为此,Prometheus 采用了适配器的方式屏蔽不同存储组件之间的差异,?如图1-2所示: 图1-2 Prometheus 远程读写只要提供了适配器,Prometheus 读写数据就可以转换成第三方存储组件支持的协议和编码。Elasticsearch 也需要使用适配器,这个适配器就是由 Elastic Stack 家族中的 Beat 组件担任。早期 Prometheus 官方推荐的适配器是 Infonova 开发的 Prometheusbeat,而在最新版本中已经转而推荐 Elastic Stack 官方的 Metricbeat。?无论是 Prometheusbeat 还是 Metricbeat,它们都可以向 Prometheus 开放 HTTP 监听地址,并且在接收到 Prometheus 监控数据后将它们存储到 Elasticsearch 中。Metricbeat 采用Module 的形式开启面向 Prometheus 的 HTTP 接口,具体配置如示例 1.1 所示:- module: prometheus
metricsets: ["remote_write"]
host: "localhost"
port: "9201"示例1.1 Metricbeat 配置添加示例所示配置内容后重启 Metricbeat,它就会在本机 9201端口开始监听 Prometheus 的写入数据。与此同时还要将这个监听地址告诉 Prometheus,这样它才知道在拉取到数据后向哪里写入。具体来说就是在 prometheus.yml中 添加如下内容:?remote_write:
- url: "https://localhost:9201/write"示例1.2 Prometheus 配置使用 MetricBeat 组件保存监控数据,监控指标的标签(Label)会转换为 Elasticsearch 的文档字段。Metricbeat 还会附加一些 Metricbeat 自身相关的数据,所以文档中的字段会比实际监控指标的标签要多一些。?除了指标名称和标签以外,还包括主机地址、操作系统等信息,这可能会导致样本数据量急剧膨胀。但 Prometheus 并不支持在写入远程存储前过滤样本,所以只能通过 Beat 组件处理。?注:最高效的做法是在 metricbeat 上设置 drop_fields 的 processor,直接过滤,避免无效的网络传输。??比较理想的方法是将 Beat 组件的输出设置为 Logstash,然后再在 Logstash 中做数据过滤,最后再由 Logstash 转存到 Elasticsearch 中。在我们的系统中,除了要过滤以上 Metricbeat 附加的字段以外,还需要组合、修正一些业务相关的字段。所以为了更好的处理数据,我们在整个数据系统中加入了 Logstash 组件。?最终整个数据系统的大致结构如图 1-3 所示: Prometheus 在拉取到监控指标时,将数据同时发送给 Metricbeat 或 Prometheusbeat,它们在这里职责就是一个监控数据接收的端点。?Metricbeat 或 Prometheusbeat 再将数据发送给 Logstash,而 Logstash 则负责清洗和整理监控数据,并将它们存储到 Elasticsearch 中。我们将整个监控系统和数据系统部署在Kubernetes 集群中,而最终用于机器学习的数据源 Elasticsearch 则被部署为独立的集群。?这样就将监控系统与数据分析系统隔离开来,从而保证了监控系统,不会受到大量数据分析运算的影响而出现故障。实际上图 1-3 就是对图 1-1中 所展示的监控系统、数据系统以及Elasticsearch 集群的细化,但在实际应用中还有许多细节没有展现出来,需要读者根据项目实际情况做适当调整。?集成 Elasticsearch 与 Spark?事实上,新版 Kibana 组件中已经具备了非常强大的机器学习能力,但这项功能还未开放在基础授权中。此外我们的业务系统还有一些自身的特殊性,所以最终我们决定采用 Spark 编写代码实现这套智能预测系统。?一种显而易见的办法是利用 Elasticsearch 客户端接口,先将数据从 Elasticsearch 中读取出来再传给 Spark 进行分析处理。但 Spark 数据处理是先将任务分解成子任务,再将它们分发到不同计算节点上并行处理,以此提升海量数据分析处理的速度。而任务分解的同时是数据要分解,否则最终数据读取,就会成为所有子任务的瓶颈,这种分解后的数据在 Spark 中称为分区(Partition)。每个任务在各自的数据分区上运算处理,最终再将各自的处理结果按 Map/Reduce 的思想合并起来。Elasticsearch 中的分片(Shard)刚好与 Spark 分区相契合,如果能让任务运算于分片之上,这无疑可以更充分地利用 Elasticsearch 存储特征。但如果是先从 Elasticsearch 读取数据再发送给Spark做处理,数据就是经由分片合并后的数据,Spark 在运算时就需要对数据再次进行分区。?Elasticsearch 包含一个开源的 elasticsearch-hadoop 项目,可以很好地解决数据分区问题。elasticsearch-hadoop 可以与包括 Spark 在内的 Hadoop 生态良好集成,Spark 分区数据也可以与 Elasticsearch 分片数据直接对应起来。我们所要做只是将 elasticsearch-hadoop 的Spark 依赖添加到项目中,并使用其提供的接口将数据从 Elasticsearch 中读取进来即可。智能预测系统采用 Java 语言开发,所以使用 Maven 引入如下依赖: <dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-spark-${spark.major.version}_${scala.version}</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_${scala.version}</artifactId>
<version>${spark.version}</version>
</dependency>如示例 1.3 所示,elasticsearch-hadoop 的 Spark 依赖为 elasticsearch-spark。由于需要用到Spark ML 相关库,示例也将 spark-sql 和 spark-mllib 依赖也一并引入了进来。elasticsearch-spark 在 org.elasticsearch.spark.rdd.api.java?包中定义了类 JavaEsSpark,它提供了大量用于读取和写入 Elasticsearch 的静态方法。其中,静态方法 esRDD?用于从 Elasticsearch中读取索引,而 saveToEs?则用于向 Elasticsearch 中存储数据。?示例展示了从 Elasticsearch 中读取索引数据的代码片段: List<Row> jobs = esRDD(sparkContext, metricIndex, queryString).values().map(
map -> {
Object[] values = new Object[featureFields.length+1];
for (int i = 0; i < featureFields.length; i++) {
values[i] = map.get(featureFields[i]);
}
values[featureFields.length] = map.get(labelField);
return RowFactory.create(values);
}
).collect();
StructField[] structFields = new StructField[featureFields.length + 1];
for (int i = 0; i < featureFields.length; i++) {
structFields[i] = new StructField(featureFields[i], DataTypes.StringType, true, Metadata.empty());
}
structFields[featureFields.length] = new StructField(labelField, DataTypes.StringType, true, Metadata.empty());
StructType schema = new StructType(structFields);
Dataset<Row> dataset = sparkSession.createDataFrame(jobs, schema);示例1.4 使用 Spark 读入数据示例中,sparkContext?是 SparkContext?实例,代表了与 Spark 运算环境相关的一些基本信息。MetricIndex 则是?esRDD?方法要读取文档数据的索引名称,而 queryString 则是检索文档的查询条件。esRDD?返回的类型为 JavaPairRDD,这是类似于一个 Pair 的集合。?每一个 Pair 代表索引中的一个文档,Pair 的 key 是字符串类型,代表了当前文档的标识符;而 value 则是一个 Map?类型,代表了整个文档数据。通过 JavaPairRDD?的 keys 方法将只返回所有文档的标识符,而通过 values 方法则会只返回所有文档的 Map 对象。?Map 的键为文档字段名称,而值则为文档字段对应的具体数值。示例中的代码就是通过调用values 方法只获取文档的 Map 对象,然后再通过 Map 和 collect 方法将它们转换成 Row 的集合。?《Elastic Stack 实战手册》——四、应用实践——4.2 可观测性应用场景 ——4.2.1.基于Elasticsearch实现预测系统(3) /article/1226131
带你读《Elastic Stack 实战手册》之75:——4.2.1.基于Elasticsearch实现预测系统(1)
4.2.可观测性应用场景4.2.1.基于Elasticsearch实现预测系统创作人:田雪松审稿人:李捷?业务背景介绍?当代商业组织面临的最基本挑战,是互联网已经不再是一个替代或可选渠道,它已经成为许多企业最主要的、甚至是惟一的销售平台。网上店面在现实中往往比实体店面还要重要,所以人们就必须要像监视实体店面一样,监控网上应用。?监控系统通常会以推送(Push)或拉取(Pull)的方式,从服务或应用中获取监控指标(Metrics),并在监控指标出现异常时,发送警报或恢复服务,以实现网上店面实时可用的目标。?监控系统在提升了应用可用性同时,还在日积月累中形成海量监控数据,而从这些监控数据中可以挖掘出巨大的商业价值。监控指标会包含一些特定业务场景下的业务数据,借助大数据分析工具对它们进行处理和建模后,就可以辅助人们作出正确的市场决策。?本章要介绍的案例就是基于 Elasticsearch 对监控数据进行商业挖掘的一次尝试,我们内部称这套系统为 Prophet(大预言家)。Prophet 通过机器学习对历史监控数据进行处理,并创建预测模型,最终可以实现对单次用户请求处理的全面预测,包括处理结果是否成功、处理执行时长等等。?Prophet预测系统架构?Prophet 虽然只是监控数据最终的分析处理服务,但支撑 Prophet 实现智能预测的整个系统?却涵盖了四个主要部分:?l?第一部分是产生海量监控数据的监控系统,它从被监控的业务系统中拉取监控数据,并提供实时告警服务。l?第二部分则是将监控数据,从监控系统中导入到 Elasticsearch 集群的数据系统,它还负责对监控数据进行清洗、转换。l?第三部分是用于存储历史监控数据的 Elasticsearch 集群,我们借助 Elasticsearch 冷热模型,延长了监控数据的保存时间。l?而最后一个才是最终处理这些数据的 Prophet 服务,它通过 Spark 运算集群,实现智能预测功能,未来还会添加更多数据分析功能。?四个系统之间的数据流动关系如图 1-1 所示:图1-1 Prophet周边生态除了 Elasticsearch 以外,HDFS 也是存储历史监控数据的一种不错选项,并且 HDFS 更容易与 Hadoop 的大数据生态系统集成。?我们之所以采用 Elasticsearch 主要还是被 Elasticsearch 强大的检索能力所吸引。同时,Elastic Stack 家族中的 Kibana 还提供了强大的数据可视化能力,至于数据分析则可以利用 elasticsearch-hadoop 插件整合 Hadoop 生态。使用 Elasticsearch 存储监控数据在 Prophet 诞生之前,我们的业务系统已经使用 Prometheus 做到了实时监控,同时还通过 Grafana 对监控数据做了可视化处理。?但 Prometheus 监控数据存储,在其内置 TSDB(Time Serie Database)中,PrometheusTSDB 中并没有分片和副本等概念,而只是简单地将数据保存在本地硬盘上。这意味着 Prometheus 无法支持数据高可用,同时也意味着 Prometheus TSDB 中的数据不能保存太久,否则本地硬盘迟早会被积累的数据撑爆。所以 Prometheus 默认只保存监控数据 15 天,超过这个时间后监控数据就会被直接删除。?对于一个监控系统来说这并不算什么大的问题,因为监控系统通常对实时数据更感兴趣,它只要能够实时快速地反映,被监控系统的异常就足够了。而历史数据分析和处理,并不能算是监控系统的职责范畴,应该交由 Elasticsearch 这样更专业的数据检索与分析工具来实现。?从另一个角度来说,由于预测系统,必须要基于历史数据创建预测模型,而如果直接在 Prometheus TSDB 上进行高频度的模型运算,则有可能会对监控系统本身造成性能上的影响。从系统监控与数据分析的职责角度来看,监控系统的稳定性无疑比数据分析更为重要。所以预测系统使用的历史数据,应该与 Prometheus 隔离开来,这就要求监控数据得从 Prometheus 中同步到 Elasticsearch 。一旦数据从 Prometheus 进入到 Elasticsearch ,我们就可以利用Elasticsearch 冷热架构对数据进行优化以保存更长时间。?《Elastic Stack 实战手册》——四、应用实践——4.2 可观测性应用场景 ——4.2.1.基于Elasticsearch实现预测系统(2) /article/1226133?
带你读《Elastic Stack 实战手册》之41:——3.4.3.Kibana基础应用(13)
《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.3.Kibana基础应用(12) /article/1228972条件运算符查询?查询 http_code 的值是大于等于 400 的数据http_code >= 400逻辑运算符查询?查询 http_code 的值为大于 200 并且 method 的值是 POST 的数据http_code > 200 and method : POST查询 http_code 的值为大于 200 或者 method 的值是 GET 的数据http_code > 200 or method : GET通配符?查询某个字段的值存在的数据,存在则返回数据,不存在则返回为空?size: *name: *创作人简介:郭海亮,落魄的运维搬砖人,工作近四年,爱折腾,对 k8s、Jenkins、Prometheus等云原生技术有浓厚的兴趣,日拱一卒。 博客:https://github.com/ghl1024
带你读《Elastic Stack 实战手册》之15:——3.4.1.8. ECK 安装(20)
《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.1.Elastic Stack 安装部署——3.4.1.8. ECK 安装(19) /article/1231261部署 Elasticsearch 集群?默认情况下,Istio 会为具有 Istio Sidecar 代理的工作负载之间的所有流量启用双向 TLS,需要对 Elasticsearch 资源文件进行以下修改才能确保 Elasticsearch 集群正常工作:?l?1.禁用 elastic operator 使用自签名证书加密 Elasticsearch 集群的 HTTPS 流量,之后会在 Istio Gateway 加密 HTTPS 流量。??l?2.将 Elasticsearch 集群节点之前的传输端口 9300 排除在代理之外,目前 ECK 不支持关闭 Elasticsearch 传输端口的 X-Pack Security 和 TLS。如果允许 Istio 代理传输端口,则流量会被加密两次,会导致 Elasticsearch 节点之间的通信会中断。l?3.可选,仅当 Kubernetes 集群不支持发布第三方安全令牌时才需要设置 automountServiceAccountToken 为 true。apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: istio-elasticsearch
namespace: istio-demo
spec:
?#禁用 elaticsearch 本身的 https,通过 istio 管理 tls
http:
? tls:
? ? selfSignedCertificate:
? ? ? disabled: true
version: 7.14.0
nodeSets:
?#master节点
- name: master
? count: 3
? config:
? ? node.roles: ["master"]
? podTemplate:
? ? metadata:
? ? ? annotations:
? ? ? ? ?#将传输端口 9300 排除在代理之外
? ? ? ? traffic.sidecar.istio.io/includeInboundPorts: "*"
? ? ? ? traffic.sidecar.istio.io/excludeOutboundPorts: "9300"
? ? ? ? traffic.sidecar.istio.io/excludeInboundPorts: "9300"
? ? spec:
? ? ? ?#仅当 Kubernetes 集群不支持发布第三方安全令牌时才需要设置
? ? ? ?#automountServiceAccountToken: true
? ? ? containers:
? ? ? - name: elasticsearch
? ? ? ? resources:
? ? ? ? ? ?#限制资源使用
? ? ? ? ? limits:
? ? ? ? ? ? memory: 1Gi
? ? ? ? ? ? cpu: 1
? volumeClaimTemplates:
? - metadata:
? ? ? name: elasticsearch-data
? ? spec:
? ? ? accessModes:
? ? ? - ReadWriteOnce
? ? ? resources:
? ? ? ? requests:
? ? ? ? ? storage: 20Gi
? ? ? storageClassName: alicloud-disk-efficiency
?#data 节点
- name: data
? count: 3
? config:
? ? node.roles: ["data"]
? podTemplate:
? ? metadata:
? ? ? annotations:
? ? ? ? traffic.sidecar.istio.io/includeInboundPorts: "*"
? ? ? ? traffic.sidecar.istio.io/excludeOutboundPorts: "9300"
? ? ? ? traffic.sidecar.istio.io/excludeInboundPorts: "9300"
? ? spec:
? ? ? containers:
? ? ? - name: elasticsearch
? ? ? ? resources:
? ? ? ? ? limits:
? ? ? ? ? ? memory: 2Gi
? ? ? ? ? ? cpu: 2
? volumeClaimTemplates:
? - metadata:
? ? ? name: elasticsearch-data
? ? spec:
? ? ? accessModes:
? ? ? - ReadWriteOnce
? ? ? resources:
? ? ? ? requests:
? ? ? ? ? storage: 20Gi
? ? ? storageClassName: alicloud-disk-efficiency
?#ingest 节点
- name: ingest
? count: 3
? config:
? ? node.roles: ["ingest"]
? podTemplate:
? ? metadata:
? ? ? annotations:
? ? ? ? traffic.sidecar.istio.io/includeInboundPorts: "*"
? ? ? ? traffic.sidecar.istio.io/excludeOutboundPorts: "9300"
? ? ? ? traffic.sidecar.istio.io/excludeInboundPorts: "9300"
? ? spec:
? ? ? containers:
? ? ? - name: elasticsearch
? ? ? ? resources:
? ? ? ? ? limits:
? ? ? ? ? ? memory: 2Gi
? ? ? ? ? ? cpu: 1
volumeClaimTemplates:
? - metadata:
? ? ? name: elasticsearch-data
? ? spec:
? ? ? accessModes:
? ? ? - ReadWriteOnce
? ? ? resources:
? ? ? ? requests:
? ? ? ? ? storage: 20Gi
? ? ? storageClassName: alicloud-disk-efficiency
?#coordinating 节点
- name: coordinating
? count: 3
? config:
? ? node.roles: []
? podTemplate:
? ? metadata:
? ? ? annotations:
? ? ? ? traffic.sidecar.istio.io/includeInboundPorts: "*"
? ? ? ? traffic.sidecar.istio.io/excludeOutboundPorts: "9300"
? ? ? ? traffic.sidecar.istio.io/excludeInboundPorts: "9300"
? ? spec:
? ? ? containers:
? ? ? - name: elasticsearch
? ? ? ? resources:
? ? ? ? ? limits:
? ? ? ? ? ? memory: 2Gi
? ? ? ? ? ? cpu: 1
? volumeClaimTemplates:
? - metadata:
? ? ? name: elasticsearch-data
? ? spec:
? ? ? accessModes:
? ? ? - ReadWriteOnce
? ? ? resources:
? ? ? ? requests:
? ? ? ? ? storage: 20Gi
? ? ? storageClassName: alicloud-disk-efficiency使用以下命令应用资源文件部署 Elasticsearh 集群。kubectl create ns istio-demo
kubectl label namespace istio-demo istio-injection=enabled
kubectl apply -f elasticsearch.yaml
获取 Elasticsearch 集群密码:PASSWORD=$(kubectl get secret -n istio-demo \
istio-elasticsearch-es-elastic-user \
-o go-template='{{.data.elastic | base64decode}}')
echo $PASSWORD
#elastic 用户密码
L733hU98Y467IZMft4DzLq5mIstio 可视化组件部署?Istio 和几个遥测应用做了集成,遥测能帮你了解服务网格的结构、展示网络的拓扑结构、分析网格的健康状态。使用下面命令部署 Kiali 仪表板,以及 Prometheus、Grafana、Jaeger。kubectl apply -f istio/istio-1.11.1/samples/addons通过 kubectl port-forward 的方式将 Kiali Service 服务转发到本地 20001 端口,便于我们本地访问测试。kubectl port-forward -n istio-system service/kiali 20001浏览器输入 http://localhost:20001?访问 Kiali 页面。《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.1.Elastic Stack 安装部署——3.4.1.8. ECK 安装(21) /article/1231259
带你读《Elastic Stack 实战手册》之15:——3.4.1.8. ECK 安装(1)
3.4.1.8. ECK 安装创作人:程治玮审稿人:杨丛聿?ECK 简介?Kubernetes 是目前最受欢迎的容器编排技术,越来越多的应用开始往 Kubernetes 中迁移。Kubernetes 现有的 ReplicaSet、Deployment、Service 等资源对象已经可以满足无状态应用对于自动扩缩容、负载均衡等基本需求。但是对于有状态的、分布式的应用,通常拥有各自的一套模型定义规范,例如 Prometheus,Etcd,Zookeeper,Elasticsearch 等等。部署这些分布式应用往往需要熟悉特定领域的知识,并且在扩缩容和升级时需要考虑如何保证应用服务的可用性等问题。为了简化有状态、分布式应用的部署,Kubernetes Operator 应运而生。?Kubernetes Operator 是一种特定的应用控制器,通过 CRD(Custom Resource Definitions,自定义资源定义)扩展 Kubernetes API 的功能,可以用它来创建、配置和管理特定的有状态应用,而不需要直接去使用 Kubernetes 中最原始的一些资源对象,比如 Pod,Deployment,Service 等等。?Elastic Cloud on Kubernetes(ECK)是其中的一种 Kubernetes Operator,方便我们管理Elastic Stack 家族中的各种组件,例如 Elasticsearch,Kibana,APM,Beats 等等。比如只需要定义一个 Elasticsearch 类型的 CRD 对象,ECK 就可以帮助我们快速搭建出一套Elasticsearch 集群。通过 ECK 我们还可以轻松实现:?l?管理和监控多个集群。l?集群版本升级。l?自动扩缩容。l?冷热架构。l?备份和快照。l?自定义配置和插件。l?默认提供安全保护。?版本支持?ECK 支持在以下平台和版本中运行: ?l?Kubernetes 1.17-1.21l?OpenShift 3.11, 4.3-4.7l?Google Kubernetes Engine (GKE), Azure Kubernetes Service (AKS), and Amazonl?Elastic Kubernetes Service (EKS)?以下版本的 Elack Stack 组件支持通过 ECK 部署:?l?Elasticsearch, Kibana, APM Server: 6.8+, 7.1+l?Enterprise Search: 7.7+l?Beats: 7.0+l?Elastic Agent: 7.10+ (standalone), 7.14+ (Fleet)l?Elastic Maps Server: 7.11+?Kubernetes 环境准备?ECK 需要部署在 Kubernetes 集群中,因此我们首先为下面的实验准备一套 Kubernetes 集群,这里选择通过便宜云服务器 ACK 服务部署 Kubernetes 集群。便宜云服务器容器服务 Kubernetes 版(Alibaba Cloud Container Service for Kubernetes,ACK)提供高性能的容器应用管理服务,支持企业级 Kubernetes 容器化应用的生命周期管理,可以在几分钟内快速部署出一套高可用的 Kubernetes 集群。?《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.1.Elastic Stack 安装部署——3.4.1.8. ECK 安装(2) /article/1231279
运维面试题库之Prometheus
Prometheus
Q:什么是Prometheus?
A:Prometheus是一个开源的系统监控和警报工具集,用于收集、存储和查询时间序列数据。
Q:Prometheus的主要组件有哪些?
A:Prometheus由以下主要组件组成:
Prometheus Server:负责收集和存储时间序列数据。Exporters:用于收集特定应用或系统的指标数据,并将其暴露给Prometheus进行抓取。Alertmanager:用于定义和发送警报通知。
Q:Prometheus的数据模型是什么?
A:Prometheus使用时间序列数据模型,其中每个时间序列由唯一的标识符(metric name和一组标签)和对应的时间戳-值对组成。
Q:如何在Prometheus中定义监控指标?
A:可以使用Prometheus的自有查询语言PromQL来定义监控指标。通过指标名称和标签来唯一标识监控指标,并使用各种函数和操作符来进行数据查询和聚合。
Q:如何配置Prometheus进行目标抓取?
A:可以通过Prometheus的配置文件prometheus.yml来定义抓取配置。在配置文件中指定要抓取的目标(如Exporter的地址和端口),并设置抓取频率等参数。
Q:Prometheus如何处理数据存储和保留策略?
A:Prometheus使用本地磁盘存储时间序列数据。数据存储采用分块压缩格式,同时可以配置数据保留策略,以控制数据的存储时间和保留期限。
Q:如何设置警报规则并配置Alertmanager?
A:可以使用Prometheus的配置文件prometheus.yml来定义警报规则,并配置Alertmanager的通知方式和接收者。
Q:Prometheus支持哪些查询操作和聚合函数?
A:Prometheus支持丰富的查询操作和聚合函数,如过滤、计算率、求和、平均值、最大值、最小值等,以便对监控指标进行灵活的数据查询和分析。
Q:什么是Prometheus的服务发现机制?
A:Prometheus提供多种服务发现机制,如静态配置、文件发现、Consul、Kubernetes等,用于自动发现和抓取要监控的目标。
Q:Prometheus的可视化和查询界面是什么?
A:Prometheus提供一个内置的可视化和查询界面,称为Prometheus Web UI,可以在浏览器中访问,并通过PromQL进行数据查询和展示。
Q:什么是Prometheus的推模式(Push)和拉模式(Pull)抓取?
A:Prometheus的推模式抓取是指被监控的目标主动向Prometheus发送指标数据,而拉模式抓取是Prometheus主动从目标中拉取指标数据。
Q:如何在Prometheus中配置持久化存储?
A:可以使用Prometheus的--storage.tsdb.path参数来配置持久化存储路径,以便将时间序列数据持久化保存在磁盘上。
Q:Prometheus是否支持高可用性(HA)部署?如果是,如何实现?
A:是的,Prometheus支持高可用性部署。可以通过使用多个Prometheus实例并结合使用服务发现和联邦(Federation)来实现高可用性。
Q:什么是Prometheus的Alertmanager?它的作用是什么?
A:Prometheus的Alertmanager是用于处理和发送警报通知的组件。它能够根据预定义的警报规则接收来自Prometheus的警报,并根据配置的通知方式发送警报通知。
Q:什么是Prometheus的持续查询(Continuous Queries)?
A:Prometheus的持续查询是预定义的查询语句,定期计算和聚合时间序列数据,并将结果存储在新的时间序列中,以供后续查询和展示使用。
【夜莺监控】管理Kubernetes组件指标(下)
指标简介指标清单指标类型说明workqueue_adds_totalCounterWorkqueue 处理的 Adds 事件的数量。workqueue_depthGaugeWorkqueue 当前队列深度。workqueue_queue_duration_seconds_bucketHistogram任务在 Workqueue 中存在的时长。memory_utilization_byteGauge内存使用量,单位:字节(Byte)。memory_utilization_ratioGauge内存使用率=内存使用量/内存资源上限,百分比形式。cpu_utilization_coreGaugeCPU 使用量,单位:核(Core)。cpu_utilization_ratioGaugeCPU 使用率=CPU 使用量/内存资源上限,百分比形式。rest_client_requests_totalCounter从状态值(Status Code)、方法(Method)和主机(Host)维度分析 HTTP 请求数。rest_client_request_duration_seconds_bucketHistogram从方法(Verb)和 URL 维度分析 HTTP 请求时延。Queue 指标名称PromQL说明Workqueue 入队速率sum(rate(workqueue_adds_total{job="ack-kube-controller-manager"}[$interval])) by (name)无Workqueue 深度sum(rate(workqueue_depth{job="ack-kube-controller-manager"}[$interval])) by (name)无Workqueue 处理时延histogram_quantile($quantile, sum(rate(workqueue_queue_duration_seconds_bucket{job="ack-kube-controller-manager"}[5m])) by (name, le))无资源指标名称PromQL说明内存使用量memory_utilization_byte{container="kube-controller-manager"}内存使用量,单位:字节。CPU 使用量cpu_utilization_core{container="kube-controller-manager"}*1000CPU 使用量,单位:毫核。内存使用率memory_utilization_ratio{container="kube-controller-manager"}内存使用率,百分比。CPU 使用率cpu_utilization_ratio{container="kube-controller-manager"}CPU 使用率,百分比。QPS 和时延名称PromQL说明Kube API 请求 QPSsum(rate(rest_client_requests_total{job="ack-scheduler",code=~"2.."}[$interval])) by (method,code)sum(rate(rest_client_requests_total{job="ack-scheduler",code=~"3.."}[$interval])) by (method,code)sum(rate(rest_client_requests_total{job="ack-scheduler",code=~"4.."}[$interval])) by (method,code)sum(rate(rest_client_requests_totaljob="ack-scheduler",code=~"5.."}[$interval])) by (method,code)对 kube-apiserver 发起的 HTTP 请求,从方法(Method)和返回值(Code) 维度分析。 | | Kube API 请求时延 | histogram_quantile($quantile, sum(rate(rest_client_request_duration_seconds_bucket{job="ack-kube-controller-manager"[$interval])) by (verb,url,le)) | 对 kube-apiserver 发起的 HTTP 请求时延,从方法(Verb)和请求 URL 维度分析。 |KubeSchedulerScheduler 监听在10259端口,依然通过 Prometheus Agent 的方式采集指标。指标采集(1)编辑 Prometheus 配置文件apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'controller-manager'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-controller-manager;https-metrics
- job_name: 'scheduler'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-scheduler;https
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'然后配置 Scheduler 的 Service。apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: kube-scheduler
name: kube-scheduler
namespace: kube-system
spec:
clusterIP: None
ports:
- name: https
port: 10259
protocol: TCP
targetPort: 10259
selector:
component: kube-scheduler
sessionAffinity: None
type: ClusterIP将 YAML 的资源更新到 Kubernetes 中,然后使用curl -X POST "http://<PROMETHEUS_IP>:9090/-/reload"重载 Prometheus。但是现在我们还无法获取到 Scheduler 的指标数据,需要把 Scheduler 的bind-address改成0.0.0.0。修改完成过后就可以正常在夜莺UI中查看指标了。导入监控大盘(https://github.com/flashcatcloud/categraf/blob/main/k8s/scheduler-dash.json)。指标简介指标清单指标清单类型说明scheduler_scheduler_cache_sizeGauge调度器缓存中 Node、Pod 和 AssumedPod 的数量。scheduler_pending_podsGaugePending Pod 的数量。队列种类如下:unschedulable:表示不可调度的 Pod 数量。backoff:表示 backoffQ 的 Pod 数量。active:表示 activeQ 的 Pod 数量。 | | scheduler_pod_scheduling_attempts_bucket | Histogram | 调度器尝试成功调度 Pod 的次数,Bucket 阈值为 1、2、4、8、16。 | | memory_utilization_byte | Gauge | 内存使用量,单位:字节(Byte)。 | | memory_utilization_ratio | Gauge | 内存使用率=内存使用量/内存资源上限,百分比形式。 | | cpu_utilization_core | Gauge | CPU 使用量,单位:核(Core)。 | | cpu_utilization_ratio | Gauge | CPU 使用率=CPU 使用量/内存资源上限,百分比形式。 | | rest_client_requests_total | Counter | 从状态值(Status Code)、方法(Method)和主机(Host)维度分析 HTTP 请求数。 | | rest_client_request_duration_seconds_bucket | Histogram | 从方法(Verb)和 URL 维度分析 HTTP 请求时延。 |基本指标指标清单PromQL说明Scheduler 集群统计数据scheduler_scheduler_cache_size{job="ack-scheduler",type="nodes"}scheduler_scheduler_cache_size{job="ack-scheduler",type="pods"}scheduler_scheduler_cache_sizejob="ack-scheduler",type="assumed_pods"}调度器缓存中 Node、Pod 和 AssumedPod 的数量。 | | Scheduler Pending Pods | scheduler_pending_pods{job="ack-scheduler"| Pending Pod 的数量。队列种类如下:unschedulable:表示不可调度的 Pod 数量。backoff:表示 backoffQ 的 Pod 数量。active:表示 activeQ 的 Pod 数量。 | | Scheduler 尝试成功调度 Pod 次数 | histogram_quantile(interval])) by (pod, le)) | 调度器尝试调度 Pod 的次数,Bucket 阈值为 1、2、4、8、16。 |资源指标指标清单PromQL说明内存使用量memory_utilization_byte{container="kube-scheduler"}内存使用量,单位:字节。CPU 使用量cpu_utilization_core{container="kube-scheduler"}*1000CPU 使用量,单位:毫核。内存使用率memory_utilization_ratio{container="kube-scheduler"}内存使用率,百分比。CPU 使用率cpu_utilization_ratio{container="kube-scheduler"}CPU 使用率,百分比。QPS 和时延指标清单PromQL说明Kube API 请求 QPSsum(rate(rest_client_requests_total{job="ack-scheduler",code=~"2.."}[$interval])) by (method,code)sum(rate(rest_client_requests_total{job="ack-scheduler",code=~"3.."}[$interval])) by (method,code)sum(rate(rest_client_requests_total{job="ack-scheduler",code=~"4.."}[$interval])) by (method,code)sum(rate(rest_client_requests_totaljob="ack-scheduler",code=~"5.."}[$interval])) by (method,code)调度器对 kube-apiserver 发起的 HTTP 请求,从方法(Method)和返回值(Code) 维度分析。 | | Kube API 请求时延 | histogram_quantile($quantile, sum(rate(rest_client_request_duration_seconds_bucket{job="ack-scheduler"[$interval])) by (verb,url,le)) | 调度器对 kube-apiserver 发起的 HTTP 请求时延,从方法(Verb)和请求 URL 维度分析。 |EtcdEtcd 是 Kubernetes 的存储中心,所有资源信息都是存在在其中,它通过2381端口对外提供监控指标。指标采集由于我这里的 Etcd 是通过静态 Pod 的方式部署到 Kubernetes 集群中的,所以依然使用 Prometheus Agent 来采集指标。(1)配置 Prometheus 的采集配置apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'controller-manager'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-controller-manager;https-metrics
- job_name: 'scheduler'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-scheduler;https
- job_name: 'etcd'
kubernetes_sd_configs:
- role: endpoints
scheme: http
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;etcd;http
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'然后增加 Etcd 的 Service 配置。apiVersion: v1
kind: Service
metadata:
namespace: kube-system
name: etcd
labels:
k8s-app: etcd
spec:
selector:
component: etcd
type: ClusterIP
clusterIP: None
ports:
- name: http
port: 2381
targetPort: 2381
protocol: TCP部署 YAML 文件,并重启 Prometheus。如果获取不到指标,需要修改 Etcd 的listen-metrics-urls配置为0.0.0.0。image.png导入监控大盘(https://github.com/flashcatcloud/categraf/blob/main/k8s/etcd-dash.json)。指标简介指标清单指标类型说明cpu_utilization_coreGaugeCPU 使用量,单位:核(Core)。cpu_utilization_ratioGaugeCPU 使用率=CPU 使用量/内存资源上限,百分比形式。etcd_server_has_leaderGaugeetcd member 是否有 Leader。1:表示有主节点。0:表示没有主节点。 | | etcd_server_is_leader | Gauge | etcd member 是否是 Leader。1:表示是。0:表示不是。 | | etcd_server_leader_changes_seen_total | Counter | etcd member 过去一段时间切主次数。 | | etcd_mvcc_db_total_size_in_bytes | Gauge | etcd member db 总大小。 | | etcd_mvcc_db_total_size_in_use_in_bytes | Gauge | etcd member db 实际使用大小。 | | etcd_disk_backend_commit_duration_seconds_bucket | Histogram | etcd backend commit 延时。 Bucket 列表为:**[0.001 0.002 0.004 0.008 0.016 0.032 0.064 0.128 0.256 0.512 1.024 2.048 4.096 8.192]**。 | | etcd_debugging_mvcc_keys_total | Gauge | etcd keys 总数。 | | etcd_server_proposals_committed_total | Gauge | raft proposals commit 提交总数。 | | etcd_server_proposals_applied_total | Gauge | raft proposals apply 总数。 | | etcd_server_proposals_pending | Gauge | raft proposals 排队数量。 | | etcd_server_proposals_failed_total | Counter | raft proposals 失败数量。 | | memory_utilization_byte | Gauge | 内存使用量,单位:字节(Byte)。 | | memory_utilization_ratio | Gauge | 内存使用率=内存使用量/内存资源上限,百分比形式。 |基础指标名称PromQL说明etcd 存活状态etcd_server_has_leaderetcd_server_is_leader == 1 |etcd member 是否存活,正常值为 3。etcd member 是否是主节点,正常情况下,必须有一个 Member 为主节点。 | | 过去一天切主次数 | changes(etcd_server_leader_changes_seen_totaljob="etcd"}[1d])过去一天内 etcd 集群切主次数。 | | 内存使用量 | memory_utilization_byte{container="etcd"| 内存使用量,单位:字节。 | | CPU 使用量 | cpu_utilization_corecontainer="etcd"}*1000CPU 使用量,单位:毫核。 | | 内存使用率 | memory_utilization_ratio{container="etcd"| 内存使用率,百分比。 | | CPU 使用率 | cpu_utilization_ratio{container="etcd"} | CPU 使用率,百分比。 | | 磁盘大小 |etcd_mvcc_db_total_size_in_bytesetcd_mvcc_db_total_size_in_use_in_bytes |etcd backend db 总大小。etcd backend db 实际使用大小。 | | kv 总数 | etcd_debugging_mvcc_keys_total | etcd 集群 kv 对总数。 | | backend commit 延迟 | histogram_quantile(0.99, sum(rate(etcd_disk_backend_commit_duration_seconds_bucket{job="etcd"}[5m])) by (instance, le)) | db commit 时延。 | | raft proposal 情况 |rate(etcd_server_proposals_failed_total{job="etcd"}[1m])etcd_server_proposals_pending{job="etcd"}etcd_server_proposals_committed_total{job="etcd"} - etcd_server_proposals_applied_total{job="etcd"} |raft proposal failed 速率(分钟)。raft proposal pending 总数。commit-apply 差值。 |kubeletkubelet 工作节点的主要组件,它监听两个端口:10248和10250。10248是监控检测端口,10250是系统默认端口,通过它的/metrics接口暴露指标。指标采集这里依然通过 Prometheus Agent 的方式采集 kubelet 的指标。(1)修改 Prometheus 的配置文件apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'controller-manager'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-controller-manager;https-metrics
- job_name: 'scheduler'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-scheduler;https
- job_name: 'etcd'
kubernetes_sd_configs:
- role: endpoints
scheme: http
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;etcd;http
- job_name: 'kubelet'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-kubelet;https
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'然后配置 kubelet 的 Service 和 Endpoints,如下:apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: kubelet
name: kube-kubelet
namespace: kube-system
spec:
clusterIP: None
ports:
- name: https
port: 10250
protocol: TCP
targetPort: 10250
sessionAffinity: None
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
labels:
k8s-app: kubelet
name: kube-kubelet
namespace: kube-system
subsets:
- addresses:
- ip: 192.168.205.128
- ip: 192.168.205.130
ports:
- name: https
port: 10250
protocol: TCP这里是自定义的 Endpoints,添加了需要监控的节点。然后部署 YAML 文件并重启 Prometheus Agent,即可在夜莺 UI 中查询到具体的指标。导入监控大盘(https://github.com/flashcatcloud/categraf/blob/main/inputs/kubelet/dashboard-by-ident.json)。指标简介指标清单# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
gc的时间统计(summary指标)
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
goroutine 数量
# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
os的线程数量
# HELP kubelet_cgroup_manager_duration_seconds [ALPHA] Duration in seconds for cgroup manager operations. Broken down by method.
# TYPE kubelet_cgroup_manager_duration_seconds histogram
操作cgroup的时长分布,按照操作类型统计
# HELP kubelet_containers_per_pod_count [ALPHA] The number of containers per pod.
# TYPE kubelet_containers_per_pod_count histogram
pod中container数量的统计(spec.containers的数量)
# HELP kubelet_docker_operations_duration_seconds [ALPHA] Latency in seconds of Docker operations. Broken down by operation type.
# TYPE kubelet_docker_operations_duration_seconds histogram
操作docker的时长分布,按照操作类型统计
# HELP kubelet_docker_operations_errors_total [ALPHA] Cumulative number of Docker operation errors by operation type.
# TYPE kubelet_docker_operations_errors_total counter
操作docker的错误累计次数,按照操作类型统计
# HELP kubelet_docker_operations_timeout_total [ALPHA] Cumulative number of Docker operation timeout by operation type.
# TYPE kubelet_docker_operations_timeout_total counter
操作docker的超时统计,按照操作类型统计
# HELP kubelet_docker_operations_total [ALPHA] Cumulative number of Docker operations by operation type.
# TYPE kubelet_docker_operations_total counter
操作docker的累计次数,按照操作类型统计
# HELP kubelet_eviction_stats_age_seconds [ALPHA] Time between when stats are collected, and when pod is evicted based on those stats by eviction signal
# TYPE kubelet_eviction_stats_age_seconds histogram
驱逐操作的时间分布,按照驱逐信号(原因)分类统计
# HELP kubelet_evictions [ALPHA] Cumulative number of pod evictions by eviction signal
# TYPE kubelet_evictions counter
驱逐次数统计,按照驱逐信号(原因)统计
# HELP kubelet_http_inflight_requests [ALPHA] Number of the inflight http requests
# TYPE kubelet_http_inflight_requests gauge
请求kubelet的inflight请求数,按照method path server_type统计
注意与每秒的request数区别开
# HELP kubelet_http_requests_duration_seconds [ALPHA] Duration in seconds to serve http requests
# TYPE kubelet_http_requests_duration_seconds histogram
请求kubelet的请求时间统计,按照method path server_type统计
# HELP kubelet_http_requests_total [ALPHA] Number of the http requests received since the server started
# TYPE kubelet_http_requests_total counter
请求kubelet的请求数统计,按照method path server_type统计
# HELP kubelet_managed_ephemeral_containers [ALPHA] Current number of ephemeral containers in pods managed by this kubelet. Ephemeral containers will be ignored if disabled by the EphemeralContainers feature gate, and this number will be 0.
# TYPE kubelet_managed_ephemeral_containers gauge
当前kubelet管理的临时容器数量
# HELP kubelet_network_plugin_operations_duration_seconds [ALPHA] Latency in seconds of network plugin operations. Broken down by operation type.
# TYPE kubelet_network_plugin_operations_duration_seconds histogram
网络插件的操作耗时分布 ,按照操作类型(operation_type)统计
如果 --feature-gates=EphemeralContainers=false,否则一直为0
# HELP kubelet_network_plugin_operations_errors_total [ALPHA] Cumulative number of network plugin operation errors by operation type.
# TYPE kubelet_network_plugin_operations_errors_total counter
网络插件累计操作错误数统计,按照操作类型(operation_type)统计
# HELP kubelet_network_plugin_operations_total [ALPHA] Cumulative number of network plugin operations by operation type.
# TYPE kubelet_network_plugin_operations_total counter
网络插件累计操作数统计,按照操作类型(operation_type)统计
# HELP kubelet_node_name [ALPHA] The node's name. The count is always 1.
# TYPE kubelet_node_name gauge
node name
# HELP kubelet_pleg_discard_events [ALPHA] The number of discard events in PLEG.
# TYPE kubelet_pleg_discard_events counter
PLEG(pod lifecycle event generator) 丢弃的event数统计
# HELP kubelet_pleg_last_seen_seconds [ALPHA] Timestamp in seconds when PLEG was last seen active.
# TYPE kubelet_pleg_last_seen_seconds gauge
PLEG上次活跃的时间戳
# HELP kubelet_pleg_relist_duration_seconds [ALPHA] Duration in seconds for relisting pods in PLEG.
# TYPE kubelet_pleg_relist_duration_seconds histogram
PLEG relist pod时间分布
# HELP kubelet_pleg_relist_interval_seconds [ALPHA] Interval in seconds between relisting in PLEG.
# TYPE kubelet_pleg_relist_interval_seconds histogram
PLEG relist 间隔时间分布
# HELP kubelet_pod_start_duration_seconds [ALPHA] Duration in seconds for a single pod to go from pending to running.
# TYPE kubelet_pod_start_duration_seconds histogram
pod启动时间(从pending到running)分布
kubelet watch到pod时到pod中contianer都running后
(watch各种source channel的pod变更)
# HELP kubelet_pod_worker_duration_seconds [ALPHA] Duration in seconds to sync a single pod. Broken down by operation type: create, update, or sync
# TYPE kubelet_pod_worker_duration_seconds histogram
pod状态变化的时间分布, 按照操作类型(create update sync)统计
worker就是kubelet中处理一个pod的逻辑工作单位
# HELP kubelet_pod_worker_start_duration_seconds [ALPHA] Duration in seconds from seeing a pod to starting a worker.
# TYPE kubelet_pod_worker_start_duration_seconds histogram
kubelet watch到pod到worker启动的时间分布
# HELP kubelet_run_podsandbox_duration_seconds [ALPHA] Duration in seconds of the run_podsandbox operations. Broken down by RuntimeClass.Handler.
# TYPE kubelet_run_podsandbox_duration_seconds histogram
启动sandbox的时间分布
# HELP kubelet_run_podsandbox_errors_total [ALPHA] Cumulative number of the run_podsandbox operation errors by RuntimeClass.Handler.
# TYPE kubelet_run_podsandbox_errors_total counter
启动sanbox出现error的总数
# HELP kubelet_running_containers [ALPHA] Number of containers currently running
# TYPE kubelet_running_containers gauge
当前containers运行状态的统计
按照container状态统计,created running exited
# HELP kubelet_running_pods [ALPHA] Number of pods that have a running pod sandbox
# TYPE kubelet_running_pods gauge
当前处于running状态pod数量
# HELP kubelet_runtime_operations_duration_seconds [ALPHA] Duration in seconds of runtime operations. Broken down by operation type.
# TYPE kubelet_runtime_operations_duration_seconds histogram
容器运行时的操作耗时
(container在create list exec remove stop等的耗时)
# HELP kubelet_runtime_operations_errors_total [ALPHA] Cumulative number of runtime operation errors by operation type.
# TYPE kubelet_runtime_operations_errors_total counter
容器运行时的操作错误数统计(按操作类型统计)
# HELP kubelet_runtime_operations_total [ALPHA] Cumulative number of runtime operations by operation type.
# TYPE kubelet_runtime_operations_total counter
容器运行时的操作总数统计(按操作类型统计)
# HELP kubelet_started_containers_errors_total [ALPHA] Cumulative number of errors when starting containers
# TYPE kubelet_started_containers_errors_total counter
kubelet启动容器错误总数统计(按code和container_type统计)
code包括ErrImagePull ErrImageInspect ErrImagePull ErrRegistryUnavailable ErrInvalidImageName等
container_type一般为"container" "podsandbox"
# HELP kubelet_started_containers_total [ALPHA] Cumulative number of containers started
# TYPE kubelet_started_containers_total counter
kubelet启动容器总数
# HELP kubelet_started_pods_errors_total [ALPHA] Cumulative number of errors when starting pods
# TYPE kubelet_started_pods_errors_total counter
kubelet启动pod遇到的错误总数(只有创建sandbox遇到错误才会统计)
# HELP kubelet_started_pods_total [ALPHA] Cumulative number of pods started
# TYPE kubelet_started_pods_total counter
kubelet启动的pod总数
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
统计cpu使用率
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
允许进程打开的最大fd数
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
当前打开的fd数量
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
进程驻留内存大小
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
进程启动时间
# HELP rest_client_request_duration_seconds [ALPHA] Request latency in seconds. Broken down by verb and URL.
# TYPE rest_client_request_duration_seconds histogram
请求apiserver的耗时统计(按照url和请求类型统计verb)
# HELP rest_client_requests_total [ALPHA] Number of HTTP requests, partitioned by status code, method, and host.
# TYPE rest_client_requests_total counter
请求apiserver的总次数(按照返回码code和请求类型method统计)
# HELP storage_operation_duration_seconds [ALPHA] Storage operation duration
# TYPE storage_operation_duration_seconds histogram
存储操作耗时(按照存储plugin(configmap emptydir hostpath 等 )和operation_name分类统计)
# HELP volume_manager_total_volumes [ALPHA] Number of volumes in Volume Manager
# TYPE volume_manager_total_volumes gauge
本机挂载的volume数量统计(按照plugin_name和state统计
plugin_name包括"host-path" "empty-dir" "configmap" "projected")
state(desired_state_of_world期状态/actual_state_of_world实际状态)KubeProxyKubeProxy 主要负责节点的网络管理,它在每个节点都会存在,是通过10249端口暴露监控指标。指标采集(1)配置 Prometheus 配置apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'controller-manager'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-controller-manager;https-metrics
- job_name: 'scheduler'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-scheduler;https
- job_name: 'etcd'
kubernetes_sd_configs:
- role: endpoints
scheme: http
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;etcd;http
- job_name: 'kubelet'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-kubelet;https
- job_name: 'kube-proxy'
kubernetes_sd_configs:
- role: endpoints
scheme: http
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-proxy;http
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'然后配置 KubeProxy 的 Service。apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: proxy
name: kube-proxy
namespace: kube-system
spec:
clusterIP: None
selector:
k8s-app: kube-proxy
ports:
- name: http
port: 10249
protocol: TCP
targetPort: 10249
sessionAffinity: None
type: ClusterIP将 YAML 文件部署到集群中并重启 Prometheus Agent。然后就可以看到其监控指标了(如果没有采集到指标,查看 kube-proxy 的10249端口是否绑定到127.0.0.1了,如果是就修改成0.0.0.0,通过kubectl edit cm -n kube-system kube-proxy修改metricsBindAddress即可。)。image.png导入监控大盘(https://github.com/flashcatcloud/categraf/blob/main/inputs/kube_proxy/dashboard-by-ident.json)。指标简介指标清单# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
gc时间
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
goroutine数量
# HELP go_threads Number of OS threads created.
# TYPE go_threads gauge
线程数量
# HELP kubeproxy_network_programming_duration_seconds [ALPHA] In Cluster Network Programming Latency in seconds
# TYPE kubeproxy_network_programming_duration_seconds histogram
service或者pod发生变化到kube-proxy规则同步完成时间指标含义较复杂,参照https://github.com/kubernetes/community/blob/master/sig-scalability/slos/network_programming_latency.md
# HELP kubeproxy_sync_proxy_rules_duration_seconds [ALPHA] SyncProxyRules latency in seconds
# TYPE kubeproxy_sync_proxy_rules_duration_seconds histogram
规则同步耗时
# HELP kubeproxy_sync_proxy_rules_endpoint_changes_pending [ALPHA] Pending proxy rules Endpoint changes
# TYPE kubeproxy_sync_proxy_rules_endpoint_changes_pending gauge
endpoint 发生变化后规则同步pending的次数
# HELP kubeproxy_sync_proxy_rules_endpoint_changes_total [ALPHA] Cumulative proxy rules Endpoint changes
# TYPE kubeproxy_sync_proxy_rules_endpoint_changes_total counter
endpoint 发生变化后规则同步的总次数
# HELP kubeproxy_sync_proxy_rules_iptables_restore_failures_total [ALPHA] Cumulative proxy iptables restore failures
# TYPE kubeproxy_sync_proxy_rules_iptables_restore_failures_total counter
本机上 iptables restore 失败的总次数
# HELP kubeproxy_sync_proxy_rules_last_queued_timestamp_seconds [ALPHA] The last time a sync of proxy rules was queued
# TYPE kubeproxy_sync_proxy_rules_last_queued_timestamp_seconds gauge
最近一次规则同步的请求时间戳,如果比下一个指标 kubeproxy_sync_proxy_rules_last_timestamp_seconds 大很多,那说明同步 hung 住了
# HELP kubeproxy_sync_proxy_rules_last_timestamp_seconds [ALPHA] The last time proxy rules were successfully synced
# TYPE kubeproxy_sync_proxy_rules_last_timestamp_seconds gauge
最近一次规则同步的完成时间戳
# HELP kubeproxy_sync_proxy_rules_service_changes_pending [ALPHA] Pending proxy rules Service changes
# TYPE kubeproxy_sync_proxy_rules_service_changes_pending gauge
service变化引起的规则同步pending数量
# HELP kubeproxy_sync_proxy_rules_service_changes_total [ALPHA] Cumulative proxy rules Service changes
# TYPE kubeproxy_sync_proxy_rules_service_changes_total counter
service变化引起的规则同步总数
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
利用这个指标统计cpu使用率
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
进程可以打开的最大fd数
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
进程当前打开的fd数
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
统计内存使用大小
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
进程启动时间戳
# HELP rest_client_request_duration_seconds [ALPHA] Request latency in seconds. Broken down by verb and URL.
# TYPE rest_client_request_duration_seconds histogram
请求 apiserver 的耗时(按照url和verb统计)
# HELP rest_client_requests_total [ALPHA] Number of HTTP requests, partitioned by status code, method, and host.
# TYPE rest_client_requests_total counter
请求 apiserver 的总数(按照code method host统计)最后夜莺监控 Kubernetes 官方(https://flashcat.cloud/categories/kubernetes%E7%9B%91%E6%8E%A7%E4%B8%93%E6%A0%8F/)已经整理了专栏,我这里仅仅是做了加工整理以及测试,不论是指标整理还是监控大盘,社区都做的很到位了,拿来即用。参考文档[1] https://help.aliyun.com/document_detail/441320.html?spm=a2c4g.444711.0.0.15046e9958T2TG
【夜莺监控】管理Kubernetes组件指标(上)
开始之前Kubernetes 是一个简单且复杂的系统,简单之处在于其整体架构比较简单清晰,是一个标准的 Master-Slave 模式,如下:但是,它又是一个复杂的系统,不论是 Master 还是 Slave,都有多个组件组合而成,如上图所示:Master 组件apiserver:API 入口,负责认证、授权、访问控制、API 注册与发现等scheduler:负责资源调度controller-manager:维护集群状态Slave 组件kubelet:维护容器生命周期、CSI 管理以及 CNI 管理kube-proxy:负责服务发现和负载均衡container runtime(docker、containerd 等):镜像管理、容器运行、CRI 管理等数据库组件Etcd:保存集群状态,与 apiserver 保持通信对于如此复杂的简单系统,要时刻掌握里内部的运行状态,是一件挺难的事情,因为它的覆盖面非常的广,主要涉及:操作系统层面:Kubernetes 是部署在操作系统之上的,操作系统层面的监控非常重要。Kubernetes 本身:Kubernetes 涉及相当多的组件,这些组件的运行状态关乎整个集群的稳定性。Kubernetes 之上的应用:Kubernetes 是为应用提供运行环境的,企业的应用系统都是部署在集群中,这些应用的稳定关乎企业的发展。还有其他的比如网络、机房、机柜等等底层支柱。要监控的非常多,SLI 也非常多。不过,这篇文章只讨论 Kubernetes 本身的监控,而且只讨论如何在夜莺体系中来监控它们。对于 Kubernetes 本身,主要是监控其系统组件,如下:image.png!!?Ps:这里不在介绍夜莺监控是怎么安装的,如果不清楚的可以看《【夜莺监控】初识夜莺》这篇文章,本次实验也是使用是这篇文章中的安装方式。KubeApiServerApiServer 是 Kubernetes 架构中的核心,是所有 API 是入口,它串联所有的系统组件。为了方便监控管理 ApiServer,设计者们为它暴露了一系列的指标数据。当你部署完集群,默认会在default名称空间下创建一个名叫kubernetes的 service,它就是 ApiServer 的地址。# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 309d你可以通过curl -s -k -H "Authorization: Bearer $token" https://10.96.0.1:6443/metrics命令查看指标。其中$token是通过在集群中创建 ServerAccount 以及授予相应的权限得到。所以,要监控 ApiServer,采集到对应的指标,就需要先授权。为此,我们先准备认证信息。创建 namespacekubectl create ns flashcat创建认证授权信息创建0-apiserver-auth.yaml文件,内容如下:---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: categraf
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/metrics
- nodes/stats
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
- networking.k8s.io
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics", "/metrics/cadvisor"]
verbs: ["get"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: categraf
namespace: flashcat
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: categraf
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: categraf
subjects:
- kind: ServiceAccount
name: categraf
namespace: flashcat上面的内容主要是为categraf授予查询相关资源的权限,这样就可以获取到这些组件的指标数据了。指标采集指标采集的方式有很多种,建议通过自动发现的方式进行采集,这样是不论是伸缩、修改组件都无需再次来调整监控方式了。夜莺支持Prometheus Agent的方式获取指标,而且 Prometheus 在服务发现方面做的非常好,所以这里将使用Prometheus Agent方式来采集 ApiServer 的指标。(1)创建 Prometheus 配置apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'上面的内容主要是通过endpoints的方式主动发现在default名称空间下名字为kubernetes且端口为https的服务,然后将获取到的监控指标传输给夜莺服务端http://192.168.205.143:17000/prometheus/v1/write(这个地址根据实际情况做调整)。(2)部署 Prometheus AgentapiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-agent
namespace: flashcat
labels:
app: prometheus-agent
spec:
replicas: 1
selector:
matchLabels:
app: prometheus-agent
template:
metadata:
labels:
app: prometheus-agent
spec:
serviceAccountName: categraf
containers:
- name: prometheus
image: prom/prometheus
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--web.enable-lifecycle"
- "--enable-feature=agent"
ports:
- containerPort: 9090
resources:
requests:
cpu: 500m
memory: 500M
limits:
cpu: 1
memory: 1Gi
volumeMounts:
- name: prometheus-config-volume
mountPath: /etc/prometheus/
- name: prometheus-storage-volume
mountPath: /prometheus/
volumes:
- name: prometheus-config-volume
configMap:
defaultMode: 420
name: prometheus-agent-conf
- name: prometheus-storage-volume
emptyDir: {}其中--enable-feature=agent表示启动的是 agent 模式。然后将上面的所有 YAML 文件部署到 Kubernetes 中,然后查看 Prometheus Agent 是否正常。# kubectl get po -n flashcat
NAME READY STATUS RESTARTS AGE
prometheus-agent-78c8ccc4f5-g25st 1/1 Running 0 92s然后可以到夜莺UI查看对应的指标。获取到了指标数据,后面就是合理利用指标做其他动作,比如构建面板、告警处理等。比如夜莺Categraf提供了 ApiServer 的仪表盘(https://github.com/flashcatcloud/categraf/blob/main/k8s/apiserver-dash.json),导入后如下:但是,不论是做面板也好,还是做告警也罢,首先都要对 ApiServer 的指标有一个清晰的认识。下面做了一些简单的整理。指标简介以下指标来自便宜云服务器 ACK 官方文档,我觉得整理的比较全,比较细,就贴了一部分。想要了解更多的可以到官方网站去查看。指标清单指标类型解释apiserver_request_duration_seconds_bucketHistogram该指标用于统计 APIServer 客户端对 APIServer 的访问时延。对 APIServer 不同请求的时延分布。请求的维度包括 Verb、Group、Version、Resource、Subresource、Scope、Component 和 Client。Histogram Bucket 的阈值为:**{0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 50, 60}**,单位:秒。apiserver_request_totalCounter对 APIServer 不同请求的计数。请求的维度包括 Verb、Group、Version、Resource、Scope、Component、HTTP contentType、HTTP code 和 Client。apiserver_request_no_resourceversion_list_totalCounter对 APIServer 的请求参数中未配置 ResourceVersion 的 LIST 请求的计数。请求的维度包括 Group、Version、Resource、Scope 和 Client。用来评估 quorum read 类型 LIST 请求的情况,用于发现是否存在过多 quorum read 类型 LIST 以及相应的客户端,以便优化客户端请求行为。apiserver_current_inflight_requestsGaugeAPIServer 当前处理的请求数。包括 ReadOnly 和 Mutating 两种。apiserver_dropped_requests_totalCounter限流丢弃掉的请求数。HTTP 返回值是**429 'Try again later'**。apiserver_admission_controller_admission_duration_seconds_bucketGauge准入控制器(Admission Controller)的处理延时。标签包括准入控制器名字、操作(CREATE、UPDATE、CONNECT 等)、API 资源、操作类型(validate 或 admit)和请求是否被拒绝(true 或 false)。Bucket 的阈值为:**{0.005, 0.025, 0.1, 0.5, 2.5}**,单位:秒。apiserver_admission_webhook_admission_duration_seconds_bucketGauge准入 Webhook(Admission Webhook)的处理延时。标签包括准入控制器名字、操作(CREATE、UPDATE、CONNECT 等)、API 资源、操作类型(validate 或 admit)和请求是否被拒绝(true 或 false)。Bucket 的阈值为:**{0.005, 0.025, 0.1, 0.5, 2.5}**,单位:秒。apiserver_admission_webhook_admission_duration_seconds_countCounter准入 Webhook(Admission Webhook)的处理请求统计。标签包括准入控制器名字、操作(CREATE、UPDATE、CONNECT 等)、API 资源、操作类型(validate 或 admit)和请求是否被拒绝(true 或 false)。cpu_utilization_coreGaugeCPU 使用量,单位:核(Core)。cpu_utilization_ratioGaugeCPU 使用率=CPU 使用量/内存资源上限,百分比形式。memory_utilization_byteGauge内存使用量,单位:字节(Byte)。memory_utilization_ratioGauge内存使用率=内存使用量/内存资源上限,百分比形式。upGauge服务可用性。1:表示服务可用。0:表示服务不可用。 |关键指标名称PromQL说明API QPSsum(irate(apiserver_request_total[$interval]))APIServer 总 QPS。读请求成功率sum(irate(apiserver_request_total{code=~"20.*",verb=~"GET|LIST"}[interval]))APIServer 读请求成功率。写请求成功率sum(irate(apiserver_request_total{code=~"20.*",verb!~"GET|LIST|WATCH|CONNECT"}[interval]))APIServer 写请求成功率。在处理读请求数量sum(apiserver_current_inflight_requests{requestKind="readOnly"})APIServer 当前在处理读请求数量。在处理写请求数量sum(apiserver_current_inflight_requests{requestKind="mutating"})APIServer 当前在处理写请求数量。请求限流速率sum(irate(apiserver_dropped_requests_total[$interval]))Dropped Request Rate。资源指标名称PromQL说明内存使用量memory_utilization_byte{container="kube-apiserver"}APIServer 内存使用量,单位:字节。CPU 使用量cpu_utilization_core{container="kube-apiserver"}*1000CPU 使用量,单位:豪核。内存使用率memory_utilization_ratio{container="kube-apiserver"}APIServer 内存使用率,百分比。CPU 使用率cpu_utilization_ratio{container="kube-apiserver"}APIServer CPU 使用率,百分比。资源对象数量max by(resource)(apiserver_storage_objects)max by(resource)(etcd_object_counts) | Kubernetes 管理资源数量,不同版本名称可能不同。 |QPS 和时延名称PromQL说明按 Verb 维度分析 QPSsum(irate(apiserver_request_total{verb=~"verb"}[interval]))by(verb)按 Verb 维度,统计单位时间(1s)内的请求 QPS。按 Verb+Resource 维度分析 QPSsum(irate(apiserver_request_total{verb=~"resource"}[$interval]))by(verb,resource)按 Verb+Resource 维度,统计单位时间(1s)内的请求 QPS。按 Verb 维度分析请求时延histogram_quantile(interval])) by (le,verb))按 Verb 维度,分析请求时延。按 Verb+Resource 维度分析请求时延histogram_quantile(interval])) by (le,verb,resource))按 Verb+Resource 维度,分析请求时延。非 2xx 返回值的读请求 QPSsum(irate(apiserver_request_total{verb=~"GET|LIST",resource=~"resource",code!~"2.*"}[interval])) by (verb,resource,code)统计非 2xx 返回值的读请求 QPS。非 2xx 返回值的写请求 QPSsum(irate(apiserver_request_total{verb!~"GET|LIST|WATCH",verb=~"resource",code!~"2.*"}[$interval])) by (verb,resource,code)统计非 2xx 返回值的写请求 QPS。KubeControllerManagerControllerManager 也是 Kubernetes 的重要组件,它负责整个集群的资源控制管理,它有许多的控制器,比如 NodeController、JobController 等。ControllerManager 的监控思路和 ApiServer 一样,都使用 Prometheus Agent 进行采集。指标采集ControllerManager 是通过10257的/metrics接口进行指标采集,要访问这个接口同样需要相应的权限,不过我们在采集 ApiServer 的时候创建过相应的权限,这里就不用创建了。(1)添加 Prometheus 配置 在原有的 Prometheus 采集配置中新增一个 job 用于采集 ControllerManager,如下:apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'controller-manager'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-controller-manager;https-metrics
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'由于我的集群里没有相应的 endpoints,所以需要创建一个,如下:apiVersion: v1
kind: Service
metadata:
annotations:
labels:
k8s-app: kube-controller-manager
name: kube-controller-manager
namespace: kube-system
spec:
clusterIP: None
ports:
- name: https-metrics
port: 10257
protocol: TCP
targetPort: 10257
selector:
component: kube-controller-manager
sessionAffinity: None
type: ClusterIP将 YAML 的资源更新到 Kubernetes 中,然后使用curl -X POST "http://<PROMETHEUS_IP>:9090/-/reload"重载 Prometheus。但是现在我们还无法获取到 ControllerManager 的指标数据,需要把 ControllerManager 的bind-address改成0.0.0.0。然后就可以在夜莺 UI 中查看指标了。然后可以导入https://github.com/flashcatcloud/categraf/blob/main/k8s/cm-dash.json的是数据大盘。指标简介指标清单指标类型说明workqueue_adds_totalCounterWorkqueue 处理的 Adds 事件的数量。workqueue_depthGaugeWorkqueue 当前队列深度。workqueue_queue_duration_seconds_bucketHistogram任务在 Workqueue 中存在的时长。memory_utilization_byteGauge内存使用量,单位:字节(Byte)。memory_utilization_ratioGauge内存使用率=内存使用量/内存资源上限,百分比形式。cpu_utilization_coreGaugeCPU 使用量,单位:核(Core)。cpu_utilization_ratioGaugeCPU 使用率=CPU 使用量/内存资源上限,百分比形式。rest_client_requests_totalCounter从状态值(Status Code)、方法(Method)和主机(Host)维度分析 HTTP 请求数。rest_client_request_duration_seconds_bucketHistogram从方法(Verb)和 URL 维度分析 HTTP 请求时延。Queue 指标名称PromQL说明Workqueue 入队速率sum(rate(workqueue_adds_total{job="ack-kube-controller-manager"}[$interval])) by (name)无Workqueue 深度sum(rate(workqueue_depth{job="ack-kube-controller-manager"}[$interval])) by (name)无Workqueue 处理时延histogram_quantile($quantile, sum(rate(workqueue_queue_duration_seconds_bucket{job="ack-kube-controller-manager"}[5m])) by (name, le))无资源指标名称PromQL说明内存使用量memory_utilization_byte{container="kube-controller-manager"}内存使用量,单位:字节。CPU 使用量cpu_utilization_core{container="kube-controller-manager"}*1000CPU 使用量,单位:毫核。内存使用率memory_utilization_ratio{container="kube-controller-manager"}内存使用率,百分比。CPU 使用率cpu_utilization_ratio{container="kube-controller-manager"}CPU 使用率,百分比。QPS 和时延名称PromQL说明Kube API 请求 QPSsum(rate(rest_client_requests_total{job="ack-scheduler",code=~"2.."}[$interval])) by (method,code)sum(rate(rest_client_requests_total{job="ack-scheduler",code=~"3.."}[$interval])) by (method,code)sum(rate(rest_client_requests_total{job="ack-scheduler",code=~"4.."}[$interval])) by (method,code)sum(rate(rest_client_requests_totaljob="ack-scheduler",code=~"5.."}[$interval])) by (method,code)对 kube-apiserver 发起的 HTTP 请求,从方法(Method)和返回值(Code) 维度分析。 | | Kube API 请求时延 | histogram_quantile($quantile, sum(rate(rest_client_request_duration_seconds_bucket{job="ack-kube-controller-manager"[$interval])) by (verb,url,le)) | 对 kube-apiserver 发起的 HTTP 请求时延,从方法(Verb)和请求 URL 维度分析。 |KubeSchedulerScheduler 监听在10259端口,依然通过 Prometheus Agent 的方式采集指标。指标采集(1)编辑 Prometheus 配置文件apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-agent-conf
labels:
name: prometheus-agent-conf
namespace: flashcat
data:
prometheus.yml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'apiserver'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'controller-manager'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-controller-manager;https-metrics
- job_name: 'scheduler'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
insecure_skip_verify: true
authorization:
credentials_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: kube-system;kube-scheduler;https
remote_write:
- url: 'http://192.168.205.143:17000/prometheus/v1/write'然后配置 Scheduler 的 Service。apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: kube-scheduler
name: kube-scheduler
namespace: kube-system
spec:
clusterIP: None
ports:
- name: https
port: 10259
protocol: TCP
targetPort: 10259
selector:
component: kube-scheduler
sessionAffinity: None
type: ClusterIP将 YAML 的资源更新到 Kubernetes 中,然后使用curl -X POST "http://<PROMETHEUS_IP>:9090/-/reload"重载 Prometheus。但是现在我们还无法获取到 Scheduler 的指标数据,需要把 Scheduler 的bind-address改成0.0.0.0。修改完成过后就可以正常在夜莺UI中查看指标了。导入监控大盘(https://github.com/flashcatcloud/categraf/blob/main/k8s/scheduler-dash.json)。
【夜莺监控】从日志中提取指标的瑞士军刀
mtail是谷歌开源的一款从应用日志提取 metrics 的工具,它会实时读取应用程序的日志,然后通过自己编写的脚本分析日志,最终生成时间序列的指标夜莺的Categraf对日志指标的收集也是采用的 mtail,不过做了一些优化,具体优化了什么我们慢慢道来。现在,我们先从谷歌的mtail开始聊起,再慢慢聊到夜莺的 mtail 插件。mtail 的安装前面已经对mtail做了简短的介绍,其实那就是全部。所以,我们直接从安装开始。操作如下:# 下载
$ wget https://github.com/google/mtail/releases/download/v3.0.0-rc51/mtail_3.0.0-rc51_Linux_x86_64.tar.gz
$ tar xf mtail_3.0.0-rc51_Linux_x86_64.tar.gz
$ cp mtail /usr/local/bin
# 查看mtail版本
$ mtail --version
mtail version 3.0.0-rc51 git revision 6fdbf8ec96a63c674c53148eeb9ec96043a2ec9c go version go1.19.4 go arch amd64 go os linux
# mtail后台启动
$ nohup mtail -port 3903 -logtostderr -progs test.mtail -logs test.log &
# 默认端口是3903
$ nohup ./mtail -progs test.mtail -logs test.log &
# 查看是否启动成功
$ ps -ef | grep mtail
# 查看mtail的帮助文档
$ mtail -hmtail 参数详解安装完mtail之后,如果对mtail的参数一无所知的话,也就不知道如何下手了,本小节就带大家来了解一下 mtail 有哪些参数。我们可以通过mtail -h来查看mtail支持的参数列表,下面我对这些参数加一些中文注释,应该能够帮助你了解它们的意思了。$ mtail -h
mtail version 3.0.0-rc51 git revision 6fdbf8ec96a63c674c53148eeb9ec96043a2ec9c go version go1.19.4 go arch amd64 go os linux
Usage:
-address string # 绑定HTTP监听器的主机或者IP地址
-alsologtostderr # 记录标准错误和文件
-block_profile_rate int # 报告goroutine阻塞事件之前的阻塞时间的纳秒数。0表示关闭。
-collectd_prefix string # 发送给collectd的指标前缀
-collectd_socketpath string # collectd socket路径,用于向其写入metrics
-compile_only # 仅禅师编译mtail脚本程序,不执行
-disable_fsnotify # 是否禁用文件动态发现机制。为true时,不会监听动态加载发现的新文件,只会监听程序启动时的文件。
-dump_ast # 解析后dump程序的AST(默认到/tmp/mtail.INFO)
-dump_ast_types # 在类型检查之后dump带有类型注释的程序的AST(默认到/tmp/mtail.INFO)
-dump_bytecode # dump程序字节码
-emit_metric_timestamp # 发出metric的记录时间戳。如果禁用(默认设置),则不会向收集器发送显式时间戳。
-emit_prog_label # 在导出的变量里面展示prog对应的标签。默认为true
-expired_metrics_gc_interval duration # metric的垃圾收集器运行间隔(默认为1h0m0s)
-graphite_host_port string # graphite carbon服务器地址,格式Host:port。用于向graphite carbon服务器写入metrics
-graphite_prefix string # 发送给graphite指标的metrics前缀
-http_debugging_endpoint # 是否开启调式接口(/debug/*),默认开启
-http_info_endpoint # 是否开始info接口(/progz,/varz),默认开启
-ignore_filename_regex_pattern string # 需要忽略的日志文件名字,支持正则表达式。使用场景:当-logs参数指定的为一个目录时,可以使用ignore_filename_regex_pattern 参数来忽略一部分文件
-jaeger_endpoint string # 如果设为true,可以将跟踪导出到Jaeger跟踪收集器。使用–jaeger_endpoint标志指定Jaeger端点URL
-log_backtrace_at value # 当日志记录命中设置的行N时,发出堆栈跟踪
-log_dir string # mtail程序的日志文件的目录,与logtostderr作用类似,如果同时配置了logtostderr参数,则log_dir参数无效
-logs value # 监控的日志文件列表,可以使用,分隔多个文件,也可以多次使用-logs参数,也可以指定一个文件目录,支持通配符*,指定文件目录时需要对目录使用单引号。
-logtostderr # 直接输出标准错误信息,编译问题也直接输出
-max_recursion_depth int # 以解析的标记来衡量mtail语句的最大长度。过长的mtail表达式可能会导致编译和运行时的性能问题。(默认为100)
-max_regexp_length int # 一个mtail regexp表达式的最大长度。过长的模式可能会导致编译和运行时的性能问题。(默认为1024)
-metric_push_interval duration # metric推送时间间隔,单位:秒,默认60秒
-metric_push_interval_seconds int # 弃用,用--metric_push_interval代替
-metric_push_write_deadline duration # 在出现错误退出之前等待推送成功的时间。(默认10s)
-mtailDebug int # 设置解析器debug级别
-mutex_profile_fraction int # 报告的互斥争夺事件的比例。 0将关闭
-one_shot # 此参数将编译并运行mtail程序,然后从指定的文件开头开始读取日志(从头开始读取日志,不是实时tail),然后将收集的所有metrics打印到日志中。此参数用于验证mtail程序是否有预期输出,不用于生产环境。
-one_shot_format string # 与-one_shot一起使用的格式。这只是一个调试标志,不适合生产使用。支持的格式: json, prometheus. (默认为 "json")
-override_timezone string # 设置时区,如果使用此参数,将在时间戳转换中使用指定的时区来替代UTC
-poll_interval duration # 设置轮询所有日志文件以获取数据的间隔;必须为正,如果为零将禁用轮询。使用轮询模式,将仅轮询在mtail启动时找到的文件
-poll_log_interval duration # 设置找到所有匹配的日志文件进行轮询的时间间隔;必须是正数,或者是0来禁用轮询。 在轮询模式下,只有在mtail启动时发现的文件会被轮询。(默认250ms)
-port string # 监听的http端口,默认3903
-progs string # mtail脚本程序所在路径
-stale_log_gc_interval duration # stale的垃圾收集器运行间隔(默认为1h0m0s)
-statsd_hostport string # statsd地址,格式Host:port。用于向statsd写入metrics
-statsd_prefix string # 发送给statsd指标的metrics前缀
-stderrthreshold value # 严重性级别达到阈值以上的日志信息除了写入日志文件以外,还要输出到stderr。各严重性级别对应的数值:INFO—0,WARNING—1,ERROR—2,FATAL—3,默认值为2.
-syslog_use_current_year # 如果时间戳没有年份,则用当前年替代。(默认为true)
-trace_sample_period int # 用于设置跟踪的采样频率和发送到收集器的频率。将其设置为100,则100条收集一条追踪。
-unix_socket string # socket监控地址
-v value # v日志的日志级别,该设置可能被 vmodule标志给覆盖.默认为0.
-version # 打印mtail版本
-vm_logs_runtime_errors # 启用运行时错误的记录到标准日志。 如果设置为false,则只将错误打印到HTTP控制台。(默认为true)
-vmodule value # 按文件或模块来设置日志级别,如:-vmodule=mapreduce=2,file=1,gfs*=3配置参数非常多,一般情况下我们使用的也就那几个,如下:nohup ./mtail -progs test.mtail -logs test.log &指定 mtail 脚本以及日志目录即可。mtail 脚本语法脚本标准的格式如下:COND {
ACTION
}其中COND是一个条件表达式,可以是正则表达式,也可以是 boolean 类型的条件语句,如下:/foo/ {
ACTION1
}
variable > 0{
ACTION2
}
/foo/ && variable > 0{
ACTION3
}COND表达式可用的运算符如下:关系运算符:< , <= , > , >= , == , != , =~ , !~ , || , && , !算术运算符:| , & , ^ , + , - , * , /, << , >> , **另外,ACTION是具体的操作,如下表示从日志中匹配到 foo 字段,就给相应的指标 foo_total 的值就加 1:counter foo_total
/foo/ {
foo_total++
}对于指标,可以用= , += , ++ , –等运算符进行操作。mtail的目的是从日志中提取信息并将其传递到监控系统。因此,必须导出指标变量并命名,命名可以使用counter、histogram、gauge指标类型,并且命名的变量必须在COND脚本之前。Counter(计数器):用于记录单调递增的值,例如请求数、错误数等。Gauge(仪表):用于记录可增可减的值,例如 CPU 使用率、内存使用量等。Histogram(直方图):用于记录数据的分布情况,例如请求延迟、响应大小等。我们知道,拿 Prometheus 来说,除了上面的三种指标类型之外还有一个Summary的指标类型,为什么 mtail 没有呢?因为在 Prometheus 中,summary 指标类型用于记录数据的分布情况,并计算出更多的统计信息,例如平均值、中位数、标准差等。但是,由于 mtail 是从日志文件中提取指标,而不是直接从应用程序中提取指标,因此没有必要使用 summary 指标类型。高阶用法变量定义对于在一个脚本中需要重复使用的表达式,可以将其定义为一个变量,后续可以直接使用变量。counter duplicate_lease
const IP /\d+(\.\d+){3}/
const MATCH_IP /(?P<ip>/ + IP + /)/
/uid lease / + MATCH_IP + / for client .* is duplicate on / {
duplicate_lease++
}这是开发中常用的手段。解析时间戳mtail 会为每一个日志事件都赋予一个时间戳,如果日志里没有时间戳,mtail 会为本次日志事件赋予一个当前的日志时间。除此之外,如果日志里的时间戳不是标准时间或者其他情况,可以使用 strptime 对其进行解析,如下:/^/ +
/(?P<date>\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}) / +
/.*/ +
/$/ {
strptime($date, "2006/01/02 15:04:05")
}条件判断/pattern/ { action }是 mtail 程序中正常的条件控制流结构。如果模式匹配,那么该块中的动作就会被执行。如果模式不匹配,则跳过该块。else关键字允许程序在模式不匹配的情况下执行动作。/pattern/ {
action
} else {
alternative
}除此之外,还可以使用 otherwise 来处理没有匹配到的规则,如下:{
/pattern1/ { _action1_ }
/pattern2/ { _action2_ }
otherwise { _action3_ }
}这种语法类似于switch case default语法。精准匹配上面的/pattern/ { _action_ }形式隐含地匹配了当前的输入日志行。如果想与另一个字符串变量匹配,可以使用=~操作符,或者用!~来否定匹配,像这样:$1 =~ /GET/ {
...
}解析非数字类型的数字字段有时候遇到的日志里输出的数字是字符串,而非数字,mtail 可以对其进行解析,如下:counter total
/^[a-z]+ ((?P<response_size>\d+)|-)$/ {
$1 != "-" {
total = $response_size
}
}解析带有额外字符的数字一些日志包含除了包含数字,还包含分隔符,我们可以用 subst 函数删除它们:/sent (?P<sent>[\d,]+) bytes received (?P<received>[\d,]+) bytes/ {
# Sum total bytes across all sessions for this process
bytes_total["sent"] += int(subst(",", "", $sent))
bytes_total["received"] += int(subst(",", "", $received))
}过滤操作如果你想过滤一些不必要的日志被mtail采集,你可以使用stop,如下:getfilename() !~ /apache.access.?log/ {
stop
}重写操作一些日志,如网络服务器日志,描述了一些常见的元素,其中有独特的标识符,如果不加处理,会导致大量的度量衡键,而没有有用的计数。要重写这些捕获组,可以使用 subst(),将模式作为第一个参数:hidden text route
counter http_requests_total by method, route
/(?P<method\S+) (?P<url>\S+)/ {
route = subst(/\/d+/, "/:num", $url)
http_requests_total[method][route]++
}这里我们把$url中/后面的任何数字部分替换为字面字符串/:num,所以我们最终只计算 URL 路由的静态部分。mtail 实操说一千,道一万,不如真正来一遍。当然,我这里也不会把上面说的都来一次。为了方便阐述,我把本次操作的脚本都放到~/Desktop/mtail目录中。单日志采集# 创建prog1,里面用于保存日志处理的规则脚本
$ mkdir prog1
# 在prog1里创建prog1.mtail文件并写入以下内容
$ cat prog1.mtail
counter foo_count
/foo/{
foo_count++
}
# 创建log1目录
$ mkdir log1
# 在log1中创建a.log文件
¥ touch a.log
# 启动mtail
$ mtail -progs ~/Desktop/mtail/prog1 -logs ~/Desktop/mtail/log1/a.log
# 向a.log中写入foo
$ echo "foo" > ~/Desktop/mtail/log1/a.log
# 查看指标明细
$ curl 127.0.0.1:3903/metrics
# HELP foo_count defined at prog1.mtail:1:9-17
# TYPE foo_count counter
foo_count{prog="prog1.mtail"} 1 # 可以看到foo_count指标数为1了多日志采集如果多日志在同一个文件夹里,这时候采集的指标就可能混淆。# 在log1目录中创建b.log
$ touch b.log
# 然后为b.log重新创建一个指标脚本
$ cat prog1/prog2.mtail
counter bar_count
/bar/{
bar_count++
}
# 启动mtail
$ mtail -progs ~/Desktop/mtail/prog1 -logs ~/Desktop/mtail/log1/a.log -logs ~/Desktop/mtail/log1/b.log
# 向b.log写入日志
$ echo "bar" >> ~/Desktop/mtail/log1/b.log
# 查看指标
$ curl 127.0.0.1:3903/metrics
# HELP bar_count defined at prog2.mtail:1:9-17
# TYPE bar_count counter
bar_count{prog="prog2.mtail"} 2
# HELP foo_count defined at prog1.mtail:1:9-17
# TYPE foo_count counter
foo_count{prog="prog1.mtail"} 0可以看到能正常收集指标,但是如果我们向 a.log 也写入 bar 日志,指标会增加吗?# 向a.log写入日志
$ echo "bar" >> ~/Desktop/mtail/log1/a.log
# 查看指标
$ curl 127.0.0.1:3903/metrics
# HELP bar_count defined at prog2.mtail:1:9-17
# TYPE bar_count counter
bar_count{prog="prog2.mtail"} 3
# HELP foo_count defined at prog1.mtail:1:9-17
# TYPE foo_count counter
foo_count{prog="prog1.mtail"} 0可以看到指标依然会增加。其实我们的期望是prog1.mtail只收集a.log的日志指标,prog2.mtail只收集b.log的指标,不要相互影响。如果要解决这个问题,就需要启动不同的mtail才行。换句话说有多少日志文件,如果想分开收集,则要启动多少个mtail,可以想想这是一个非常恐怖的事情。鉴于此,Categraf 对 mtail 插件做了一些优化,优化后的 mtail 插件可以做到一个 Categraf 进程同时解析多个服务的日志,改造后的示例图如下:image.pngCategraf 操作在前面的夜莺监控系列中,对 Categraf 基本都有一个印象。默认情况下它的配置都在 conf 目录下,其中插件都在以 input 开头的文件夹里。我们进入input.mtail文件夹,编辑mtail.toml并增加如下配置:[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog1"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/a.log"]
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" #string type
[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog2"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/b.log"]
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" # string type然后添加需要的目录以及脚本:# 创建文件夹
$ mkdir {prog1,prog2,log1}
# 增加规则文件
$ cat prog1/a.mtail
counter foo_count
/foo/ {
foo_count++
}
$ cat prog2/b.mtail
counter bar_count
/bar/ {
bar_count++
}
# 增加日志文件
$ touch {log1/a.log,log1/b.log}启动 categraf:# 使用测试模式启动
$ ./categraf -test -inputs mtail然后往a.log写入foo日志。echo "foo" >> log1/a.log然后看到指标增加了:再往b.log写入bar日志。echo "bar" >> log1/b.logbar_count的指标也相应增加了。那如果我们向a.log增加bar的日志,bar_count会增加么?我们来测试一下:echo "bar" >> log1/a.log通过观察bar_count指标不会增加。Categraf 就完美解决了不同日志指标错乱的问题。除了正常的处理指标,如果想给不同的instance指定label,也是可以的,如下:[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog1"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/a.log"]
labels = {"app"= "foo"}
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" #string type
[[instances]]
progs = "/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/prog2"
logs = ["/home/jokerbai/Desktop/categraf-v0.2.38-linux-amd64/conf/input.mtail/log1/b.log"]
labels = {"app"= "bar"}
# override_timezone = "Asia/Shanghai"
# emit_metric_timestamp = "true" # string type重启 Categraf 就可以看到指标多了一个 label。其他的脚本语法和原生的 mtail 一致,这里不再追溯了。总结相比于谷歌的mtail,categraf对mtail做了一些优化,可以更好的处理多日志的问题。而且 categraf 本身集成了很多插件,都可以统一使用它实现。另外,还是相同的问题,假设插件开启比较多,categraf 的具体性能如何以及会不会影响主机的整体性能,这还有待研究。