knowledge-base

我的知识库 / Kubernetes / Prometheus

Prometheus

Intro

是一个面向云原生应用程序的开源的监控&报警工具。

Prometheus的监控对象

Prometheus优势

Prometheus组件

Architecture overview

Prometheus architecture

上图来源于官网

Installation & Start Up

1. 以服务进程运行Prometheus

​ 在ubuntu系统上安装Prometheus,一般有两种方式

Service Proxy

默认Prometheus的访问方式是http://{ip/domain-name}:9090,而服务器一般的是不会暴露9090端口的,而是暴露80端口,其他端口以nginx代理访问。

下面的步骤便是将http://{ip/domain-name}:9090代理为http://{ip/domain-name}/prometheus

停止Prometheus

sudo systemctl stop prometheus

2.Docker启动Prometheus

docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus

3. Kubernetes运行Prometheus

ConfigMap

Prometheus的配置文件

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: ns-prometheus
data:
  prometheus.yml: |
    global: 
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090']

Deployment

apiVersion: app/v1
kind: Deployment
metadata:
  name: prometheus
  namespace: ns-prometheus
  labels: 
    app: prometheus
spec:
  template:
    metadata: 
      labels: 
        app: prometheus
    spec: 
      containers:
      - image: prom/prometheus
        name: prometheus
        imagePullPolicy: IfNotPresent
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/prometheus"
        - "--storage.tsdb.retention=7d"
        - "--web.enable-admin-api"
        - "--web.enable-lifecycle"
        ports:
        - containerPort: 9090
          name: http
        volumeMounts:
        - mountPath: "/prometheus"
          subPath: prometheus
          name: data
        - mountPath: "/etc/prometheus"
          name: config
        resources:
          requests:
            cpu: 1000m
            memory: 2Gi
          limits:
            cpu: 1000m
            memory: 2Gi
      securityContext:
        runAsUser: 0
      volumes:
      - name: config
        configMap:
          name: prometheus-config
      - name: data
        persistentVolumeClaim:
          claimName: prometheus

PersistentVolumeClaim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: prometheus
  namespace: ns-prometheus
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: "rook-ceph-block"

ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
  namespace: ns-prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  - services
  - endpoints
  - pods
  - nodes/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - nodes/metrics
  verbs:
  - get
- nonResourceURLs:
  - /metrics
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: kube-ops

Service

apiVersion: v1
kind: Service
metadata:
  name: prometheus
  namespace: ns-prometheus
  labels:
    app: prometheus
spec:
  selector:
    app: prometheus
  type: NodePort
  ports:
    - name: web
      port: 9090
      targetPort: http

Apply

kubectl apply -f .

kubectl get svc -o wide -n ns-prometheus

4.官方kubernets运行Prometheus

参考:https://github.com/coreos/kube-prometheus

5.Kubernetes部署Prometheus+Grafana

git clone https://github.com/coreos/kube-prometheus.git
externalUrl: prometheus
routePrefix: prometheus
env:
- name: GF_SERVER_ROOT_URL
  value: "http://localhost:3000/grafana"
- name: GF_SERVER_SERVE_FROM_SUB_PATH
  value: "true"
# 可能需要运行多次以下命令,确保k8s资源都创建
kubectl create -f manifests/setup -f manifests

# !如果要删除以上创建的k8s资源,运行以下命令
kubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: prometheus
  namespace: monitoring
spec: 
  rules:
  - host: dp.example.tech
    http:
      paths:
      - path: /prometheus
        backend:
          serviceName: prometheus-k8s
          servicePort: 9090
      - path: /grafana
        backend:
          serviceName: grafana
          servicePort: 3000
      - path: /alertmanager
        backend:
          serviceName: alertmanager-main
          servicePort: 9093

Configuring Prometheus

​ 配置文件为prometheus.yml,文件格式为yaml。

Concepts

Metrics

存储

Prometheus 2.x 默认将时间序列数据库保存在本地磁盘中,同时也可以将数据保存到任意第三方的存储服务中。

本地存储

Prometheus 采用自定义的存储格式将样本数据保存在本地磁盘当中。

存储格式

Prometheus 按照两个小时为一个时间窗口,将两小时内产生的数据存储在一个块(Block)中。每个块都是一个单独的目录,里面含该时间窗口内的所有样本数据(chunks),元数据文件(meta.json)以及索引文件(index)。其中索引文件会将指标名称和标签索引到样板数据的时间序列中。此期间如果通过 API 删除时间序列,删除记录会保存在单独的逻辑文件 tombstone 当中。

当前样本数据所在的块会被直接保存在内存中,不会持久化到磁盘中。为了确保 Prometheus 发生崩溃或重启时能够恢复数据,Prometheus 启动时会通过预写日志(write-ahead-log(WAL))重新记录,从而恢复数据。预写日志文件保存在 wal 目录中,每个文件大小为 128MB。wal 文件包括还没有被压缩的原始数据,所以比常规的块文件大得多。一般情况下,Prometheus 会保留三个 wal 文件,但如果有些高负载服务器需要保存两个小时以上的原始数据,wal 文件的数量就会大于 3 个。

Prometheus保存块数据的目录结构如下所示:

rometheus 提供了几个参数来修改本地存储的配置,最主要的有:
启动参数
默认值
含义
--storage.tsdb.path
/data
数据存储路径
--storage.tsdb.retention.time
15d
样本数据在存储中保存的时间。超过该时间限制的数据就会被删除。
--storage.tsdb.retention.size
0
每个块的最大字节数(不包括 wal 文件)。如果超过限制,最早的样本数据会被优先删除。支持的单位有 KB, MB, GB, PB,例如:“512MB”。该参数只是试验性的,可能会在未来的版本中被移除。
--storage.tsdb.retention

该参数从 2.7 版本开始已经被弃用,使用 --storage.tsdb.retention.time 参数替代
在一般情况下,Prometheus 中存储的每一个样本大概占用1-2字节大小。如果需要对 Prometheus Server 的本地磁盘空间做容量规划时,可以通过以下公式计算:./data 
   |- 01BKGV7JBM69T2G1BGBGM6KB12 # 块
      |- meta.json  # 元数据
      |- wal        # 写入日志
        |- 000002
        |- 000001
   |- 01BKGTZQ1SYQJTR4PB43C8PD98  # 块
      |- meta.json  #元数据
      |- index   # 索引文件
      |- chunks  # 样本数据
        |- 000001
      |- tombstones # 逻辑数据
   |- 01BKGTZQ1HHWHV8FBJXW1Y3W0K
      |- meta.json
      |- wal
        |-000001

最初两个小时的块最终会在后台被压缩成更长的块。

[info] 注意

本地存储不可复制,无法构建集群,如果本地磁盘或节点出现故障,存储将无法扩展和迁移。因此我们只能把本地存储视为近期数据的短暂滑动窗口。如果你对数据持久化的要求不是很严格,可以使用本地磁盘存储多达数年的数据。

关于存储格式的详细信息,请参考 TSDB 格式

本地存储配置

rometheus 提供了几个参数来修改本地存储的配置,最主要的有:

启动参数 默认值 含义
–storage.tsdb.path /data 数据存储路径
–storage.tsdb.retention.time 15d 样本数据在存储中保存的时间。超过该时间限制的数据就会被删除。
–storage.tsdb.retention.size 0 每个块的最大字节数(不包括 wal 文件)。如果超过限制,最早的样本数据会被优先删除。支持的单位有 KB, MB, GB, PB,例如:“512MB”。该参数只是试验性的,可能会在未来的版本中被移除。
–storage.tsdb.retention   该参数从 2.7 版本开始已经被弃用,使用 –storage.tsdb.retention.time 参数替代

在一般情况下,Prometheus 中存储的每一个样本大概占用1-2字节大小。如果需要对 Prometheus Server 的本地磁盘空间做容量规划时,可以通过以下公式计算:

needed_disk_space = retention_time_seconds * ingested_samples_per_second * bytes_per_sample

从上面公式中可以看出在保留时间(retention_time_seconds)和样本大小(bytes_per_sample)不变的情况下,如果想减少本地磁盘的容量需求,只能通过减少每秒获取样本数(ingested_samples_per_second)的方式。因此有两种手段,一是减少时间序列的数量,二是增加采集样本的时间间隔。考虑到 Prometheus 会对时间序列进行压缩效率,减少时间序列的数量效果更明显。

如果你的本地存储出现故障,最好的办法是停止运行 Prometheus 并删除整个存储目录。因为 Prometheus 的本地存储不支持非 POSIX 兼容的文件系统,一旦发生损坏,将无法恢复。NFS 只有部分兼容 POSIX,大部分实现都不兼容 POSIX。

除了删除整个目录之外,你也可以尝试删除个别块目录来解决问题。删除每个块目录将会丢失大约两个小时时间窗口的样本数据。所以,Prometheus 的本地存储并不能实现长期的持久化存储。

如果同时指定了样本数据在存储中保存的时间和大小,则哪一个参数的限制先触发,就执行哪个参数的策略。

远程存储

Prometheus 的本地存储无法持久化数据,无法灵活扩展。为了保持Prometheus的简单性,Prometheus并没有尝试在自身中解决以上问题,而是通过定义两个标准接口(remote_write/remote_read),让用户可以基于这两个接口对接将数据保存到任意第三方的存储服务中,这种方式在 Promthues 中称为 Remote Storage。

Prometheus 可以通过两种方式来集成远程存储。

Remote Write

用户可以在 Prometheus 配置文件中指定 Remote Write(远程写)的 URL 地址,一旦设置了该配置项,Prometheus 将采集到的样本数据通过 HTTP 的形式发送给适配器(Adaptor)。而用户则可以在适配器中对接外部任意的服务。外部服务可以是真正的存储系统,公有云的存储服务,也可以是消息队列等任意形式。

img

Remote Read

如下图所示,Promthues 的 Remote Read(远程读)也通过了一个适配器实现。在远程读的流程当中,当用户发起查询请求后,Promthues 将向 remote_read 中配置的 URL 发起查询请求(matchers,ranges),Adaptor 根据请求条件从第三方存储服务中获取响应的数据。同时将数据转换为 Promthues 的原始样本数据返回给 Prometheus Server。

当获取到样本数据后,Promthues 在本地使用 PromQL 对样本数据进行二次处理。

[info] 注意

启用远程读设置后,Prometheus 仅从远程存储读取一组时序样本数据(根据标签选择器和时间范围),对于规则文件的处理,以及 Metadata API 的处理都只基于 Prometheus 本地存储完成。这也就意味着远程读在扩展性上有一定的限制,因为所有的样本数据都要首先加载到 Prometheus Server,然后再进行处理。所以 Prometheus 暂时不支持完全分布式处理。

image

远程读和远程写协议都使用了基于 HTTP 的 snappy 压缩协议的缓冲区编码,目前还不稳定,在以后的版本中可能会被替换成基于 HTTP/2 的 gRPC 协议,前提是 Prometheus 和远程存储之间的所有通信都支持 HTTP/2。

配置文件

想知道如何在 Prometheus 中添加远程存储的配置,请参考前面的章节:配置远程写配置远程读

关于请求与响应消息的详细信息,可以查看远程存储相关协议的 proto 文件:

syntax = "proto3";
package prometheus;

option go_package = "prompb";

import "types.proto";
import "gogoproto/gogo.proto";

message WriteRequest {
  repeated prometheus.TimeSeries timeseries = 1 [(gogoproto.nullable) = false];
}

message ReadRequest {
  repeated Query queries = 1;
}

message ReadResponse {
  // In same order as the request's queries.
  repeated QueryResult results = 1;
}

message Query {
  int64 start_timestamp_ms = 1;
  int64 end_timestamp_ms = 2;
  repeated prometheus.LabelMatcher matchers = 3;
  prometheus.ReadHints hints = 4;
}

message QueryResult {
  // Samples within a time series must be ordered by time.
  repeated prometheus.TimeSeries timeseries = 1;
}

支持的远程存储

目前 Prometheus 社区也提供了部分对于第三方数据库的 Remote Storage 支持:

存储服务 支持模式
AppOptics write
Chronix write
Cortex read/write
CrateDB read/write
Elasticsearch write
Gnocchi write
Graphite write
InfluxDB read/write
IRONdb read/write
Kafka write
M3DB read/write
OpenTSDB write
PostgreSQL/TimescaleDB read/write
SignalFx write
Splunk write
TiKV read/write
VictoriaMetrics write
Wavefront write

联邦集群

联邦使得一个 Prometheus 服务器可以从另一个 Prometheus 服务器提取选定的时序。

使用场景

Prometheus 联邦有不同的使用场景。通常,联邦被用来实现可扩展的 Prometheus 监控设置,或者将相关的指标从一个服务的 Prometheus 拉取到另一个 Prometheus 中。

分层联邦

分层联邦允许 Prometheus 能够扩展到十几个数据中心和上百万的节点。在此场景下,联邦拓扑类似一个树形拓扑结构,上层的 Prometheus 服务器从大量的下层 Prometheus 服务器中收集和汇聚的时序数据。

例如,一个联邦设置可能由多个数据中心中的 Prometheus 服务器和一套全局 Prometheus 服务器组成。每个数据中心中部署的 Prometheus 服务器负责收集本区域内细粒度的数据(实例级别),全局 Prometheus 服务器从这些下层 Prometheus 服务器中收集和汇聚数据(任务级别),并存储聚合后的数据。这样就提供了一个聚合的全局视角和详细的本地视角。

跨服务联邦

在跨服务联邦中,一个服务的 Prometheus 服务器被配置来提取来自其他服务的 Prometheus 服务器的指定的数据,以便在一个 Prometheus 服务器中对两个数据集启用告警和查询。

例如,一个运行多种服务的集群调度器可以暴露在集群上运行的服务实例的资源使用信息(例如内存和 CPU 使用率)。另一方面,运行在集群上的服务只需要暴露指定应用程序级别的服务指标。通常,这两种指标集分别被不同的 Prometheus 服务器抓取。利用联邦,监控服务级别指标的 Prometheus 服务器也可以从集群中 Prometheus 服务器拉取其特定服务的集群资源使用率指标,以便可以在该 Prometheus 服务器中使用这两组指标集。

配置联邦

在 Prometheus 服务器中,/federate 节点允许获取服务中被选中的时间序列集合的值。至少一个 match[] URL 参数必须被指定为要暴露的序列。每个 match[] 变量需要被指定为一个不变的维度选择器up 或者 {job="api-server"}。如果有多个 match[] 参数,则所有符合的时序数据的集合都会被选择。

从一个 Prometheus 服务器联邦指标到另一个 Prometheus 服务器,配置你的目标 Prometheus 服务器从源服务器的 /federate 节点抓取指标数据,同时也使用 honor_lables 抓取选项(不重写源 Prometheus 服务暴露的标签)并且传递需要的 match[] 参数。例如,下面的 scrape_configs 联邦 source-prometheus-{1,2,3}:9090 三台 Prometheus 服务器,上层 Prometheus 抓取并汇总他们暴露的任何带 job="prometheus" 标签的序列或名称以 job: 开头的指标。

scrape_configs:
  - job_name: 'federate'
    scrape_interval: 15s

    honor_labels: true
    metrics_path: '/federate'

    params:
      'match[]':
        - '{job="prometheus"}'
        - '{__name__=~"job:.*"}'

    static_configs:
      - targets:
        - 'source-prometheus-1:9090'
        - 'source-prometheus-2:9090'
        - 'source-prometheus-3:9090'

Monitor App

MSSQL

参考

export MSSQL_PASS='xxx'
sudo docker run -e SERVER=db-dev-ms01.example.com -e USERNAME=starlightdba -e PASSWORD=$DEV_MSSQL_PASS -e DEBUG=app --rm -d -p 4000:4000 --name dev-mssql awaragi/prometheus-mssql-exporter

注意:Mssql账号需要有管理员权限。

prometheus.yaml新增监控 的配置

solved


« Prometheus-监控Kong完整操作

» PVC 扩容