Prometheus监控基础
一、 背景
与Kubernetes项目一样,Prometheus项目也源自于谷歌的Borg体系,原型系统叫作BorgMon;随着Kubernetes在社区越来越活跃,以及各个厂商使用kubernetes,容器的监控体系已经完全演变成以Prometheus项目为核心的一套统一的方案;
与传统zabbix、nagios相比,Prometheus可以自动发现K8S中的各类资源并配置对应的标签、查询速度更快的时序型数据库、监控系统自身的集群部署方案等。
Prometheus已经成为云原生领域监控的事实标准,所以本文会着重介绍Prometheus的安装使用以及告警配置。
二、监控
2.1 Prometheus介绍
Prometheus是一个拥有数据指标采集、数据查询、数据存储的工具;配合grafana进行图形化展示,配合AlertManager进行告警,组成一套完整的监控系统 Prometheus的特点:
- 多维的数据模型(基于时间序列的Key、Value键值对标签)
- 灵活的查询和聚合语言PromQL
- 提供本地存储和分布式存储
- 通过基于HTTP的Pull模型采集时间序列数据
- 可利用Pushgateway(Prometheus的可选中间件)实现Push模式
- 可通过动态服务发现或静态配置发现目标机器
架构如下:
从以上架构图中可知,Prometheus由以下组件构成:
- Prometheus Server:Prometheus Server是Prometheus组件中的核心部分,负责实现对监控数据的获取,存储以及查询。Prometheus Server可以从其他的Prometheus Server实例中获取数据。
- Exporter:Exporter将监控数据采集的端点通过HTTP服务的形式暴露给Prometheus Server,Prometheus Server通过访问该Exporter提供的restful api接口中获取实时数据
- AlertManager:在Prometheus Server中支持基于PromQL创建告警规则,如果满足PromQL定义的规则,则会产生一条告警,而告警的后续处理流程则由AlertManager进行管理,告警方式支持email、短信、钉钉、微信等。
- PushGateway:Prometheus默认采用pull的方式主动从exporter中拉去数据,但如果exporter对象是一个job类型的目标,就需要在job执行完成后主动将自己的数据推送到PushGateway中,PushGateway再将数据通过http服务暴露出来,Prometheus再去pull
指标数据类型:
Prometheus采集到的指标数据可分为以下4个类型:
- Counter:一种累加的数据,典型的应用如:http请求的次数,结束的任务数, 出现的错误数等等
- Gauge:瞬时数据,典型的应用如:CPU、内存使用率等
- Histogram:统计指定区间内数据,类似柱状图,比如成绩分布;不及格人数多少,60-80分的人数多少,80分以上的人有多少。
- Summary:和Histogram一样也是统计区间值,但Summary是统计百分比,比如分数小于60的占全班人数的百分之几。
在Exporter返回的样本数据中,其注释中也包含了该样本的类型。例如:
数据格式
样本数据格式由三个部分构成:
- 指标(metric):metric name和描述当前样本特征的labels;
- 时间戳(timestamp):一个精确到毫秒的时间戳(从1970开始计算,不写默认为当前时间);
- 样本值(value): 一个float64的浮点型数据表示当前样本的值。
这里的label和K8S中的label相似,后续通过PromQl查询指标数据的时候可以通过label排除指定的数据,比如:
只查询code为200的数据
在实际应用中,如果我们想统计所有pod的request配额总和,但是要排除kube-system命名空间下的pod,就可以通过namespace这个标签来完成.
发现方式
Prometheus拉取数据的方式是调用被监控目标的http restful接口,Prometheus会为每个监控目标设置三个隐藏标签 __scheme__:可选值为http/https,默认为http __address__:被监控目标的ip与端口,格式为ip:port __metrics_path__:被监控目标指标暴露的url路径,默认为/metrics Prometheus拉取指标数据时,将这三个字段组合成一个完整的api接口路径http://ip:port/metrics
- 静态发现: 直接在prometheus.yml文件中添加target的ip:port,并配置_metrics_path;每新增一个监控目标就要修改一次yml文件
# my global config global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'node' static_configs: - targets: ['localhost:9090','192.168.0.187:9100'] #每新增一个监控目标就需要添加对应的ip:port,这里配置的其实就是__address__标签的值
- 动态发现:通过服务发现(service discovery)模块实现,sd模块专门负责去发现需要监控的target信息,Prometheus去从sd模块订阅该信息,有target信息时会推送给Prometheus,然后Prometheus拿到target信息后通过pull http地址拉取监控指标数据(常见sd有kubernetes、dns等);kubernetes_sd是针对kubernetes的服务发现,它会监控kube-apiserver,如果有新node节点加入集群,kubernetes_sd就可以拿到新节点的信息并推送给Prometheus,配置样例如下
global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'prometheus' static_configs: #静态配置方式 - targets: ['localhost:9090'] #默认监控自己 - job_name: kubernetes-nodes kubernetes_sd_configs: #使用kubernetes_sd作为服务发现 - role: node #监控node资源,其他可选值为service,pod,endpoint api_server: https://192.168.0.182:5443 #被监控集群的kube-apiserver的地址 bearer_token: $token #访问集群需要的token认证信息,token可以通过describe指定的secret获取 tls_config: insecure_skip_verify: true #跳过客户端对服务端的认证 relabel_configs: #对标签进行操作 - regex: (.+) #用正则表达式匹配__meta_kubernetes_node_name标签的值,华为云nodename为ip形式,此处匹配ip replacement: $1:9100 #$1表示匹配结果,匹配结果只有ip,所以需要加上端口,并将$1:9100赋给__address__标签,其中9100是nodeexport服务端口,nodeexport为daemonset部署在每个节点上的监控组件,通过节点ip:9100暴露服务,9100可配置。 source_labels: - __meta_kubernetes_node_name target_label: __address__ #将__address__ label值修改为节点ip:9100。__scheme__值默认为http,__metrics_path__值默认为/metrics http://ip:9100/metrics - target_label: __metrics_path__ #示例 replacement: /metrics/cadvisor #示例 本结构效果为:__metrics_path__值修改为/metrics/cadvisor。 http://ip:9100/metrics/cadvisor - target_label: node #新增一个标签node,并将instance标签的值赋给node source_labels: [instance]
2.2 kubernetes集群监控实验
实验案例是在kubernetes集群外部安装Prometheus,获取集群内部指标。
- 监控指标说明
监控来源:cAdvisor ==> 监控url:https://节点ip:10250/metrics/cadvisor ==>监控目标:容器资源
监控来源:node_exporter ==> 监控url: http://节点ip:9100/metrics ==>监控目标: 节点资源
监控来源:kube-state-metrics ==> 监控url: http://该组件ip:8080/metrics ==>监控目标: pod ns service等k8s资源信息
- 安装Prometheus
tar zxvf prometheus-2.23.0.linux-amd64.tar.gz cd prometheus-2.23.0.linux-amd64 nohup ./prometheus --storage.tsdb.retention=90d --storage.tsdb.path=./data/ --web.enable-lifecycle> prometheus.log 2>&1 &
- 在目标集群配置Prometheus的权限和安装指标监控插件
- 创建ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: labels: app: prometheus component: server name: prometheus namespace: monitoring
- 创建clusterrolebinding
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app: prometheus component: server name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: prometheus namespace: monitoring
- 创建node-exporter
apiVersion: apps/v1 kind: DaemonSet metadata: labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.7.0 name: node-exporter namespace: monitoring spec: selector: matchLabels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus template: metadata: annotations: kubectl.kubernetes.io/default-container: node-exporter labels: app.kubernetes.io/component: exporter app.kubernetes.io/name: node-exporter app.kubernetes.io/part-of: kube-prometheus app.kubernetes.io/version: 1.7.0 spec: automountServiceAccountToken: true containers: - args: - --web.listen-address=127.0.0.1:9100 - --path.sysfs=/host/sys - --path.rootfs=/host/root - --path.udev.data=/host/root/run/udev/data - --no-collector.wifi - --no-collector.hwmon - --no-collector.btrfs - --collector.filesystem.mount-points-exclude=^/(dev|proc|sys|run/k3s/containerd/.+|var/lib/docker/.+|var/lib/kubelet/pods/.+)($|/) - --collector.netclass.ignored-devices=^(veth.*|[a-f0-9]{15})$ - --collector.netdev.device-exclude=^(veth.*|[a-f0-9]{15})$ image: quay.io/prometheus/node-exporter:v1.7.0 name: node-exporter resources: limits: cpu: 250m memory: 180Mi requests: cpu: 102m memory: 180Mi securityContext: allowPrivilegeEscalation: false capabilities: add: - SYS_TIME drop: - ALL readOnlyRootFilesystem: true volumeMounts: - mountPath: /host/sys mountPropagation: HostToContainer name: sys readOnly: true - mountPath: /host/root mountPropagation: HostToContainer name: root readOnly: true - args: - --secure-listen-address=[$(IP)]:9100 - --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 - --upstream=http://127.0.0.1:9100/ env: - name: IP valueFrom: fieldRef: fieldPath: status.podIP image: quay.io/brancz/kube-rbac-proxy:v0.15.0 name: kube-rbac-proxy ports: - containerPort: 9100 hostPort: 9100 name: https resources: limits: cpu: 20m memory: 40Mi requests: cpu: 10m memory: 20Mi securityContext: allowPrivilegeEscalation: false capabilities: drop: - ALL readOnlyRootFilesystem: true runAsGroup: 65532 runAsNonRoot: true runAsUser: 65532 seccompProfile: type: RuntimeDefault hostNetwork: true hostPID: true nodeSelector: kubernetes.io/os: linux priorityClassName: system-cluster-critical securityContext: runAsNonRoot: true runAsUser: 65534 serviceAccountName: node-exporter tolerations: - operator: Exists volumes: - hostPath: path: /sys name: sys - hostPath: path: / name: root updateStrategy: rollingUpdate: maxUnavailable: 10% type: RollingUpdate
- 创建ServiceAccount
- 加载Prometheus监控配置
-
获取token并存入文件,将文件移动到Prometheus的安装目录
在K8S集群节点上执行命令获取Prometheus访问K8S集群需要的token
kubectl get secrets -n monitoring|grep prometheus-token |awk '{print $1}' |xargs
kubectl -n monitoring describe secrets |grep -i token: |awk '{print $2}'
在1.25及以上k8s版本的集群中,ServiceAccount将不会自动创建对应的Secret。如果业务中需要一个永不过期的Token,可以选择手动管理ServiceAccount的Secret: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount -
修改Prometheus配置文件
# my global config global: scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - bearer_token: token #指定访问需要的token,在上一步骤中通过命令获取 job_name: kubernetes-cadvisor kubernetes_sd_configs: - role: node api_server: https://192.168.0.182:5443 #被监控集群的kube-apiserver地址 bearer_token: token #在上一步骤中获取的token tls_config: insecure_skip_verify: true #跳过对服务端的认证 relabel_configs: - replacement: 192.168.0.182:5443 #将__address__标签的值设为kube-apiserver的地址 target_label: __address__ - regex: (.+) replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor #该url路径为K8S集群对node上端口的代理路径 source_labels: - __meta_kubernetes_node_name target_label: __metrics_path__ metric_relabel_configs: - source_labels: [ pod ] target_label: pod_name - source_labels: [ container ] target_label: container_name scheme: https #表示监控目标的指标数据通过https暴露 tls_config: insecure_skip_verify: true - job_name: kubernetes-nodes kubernetes_sd_configs: - role: node api_server: https://192.168.0.182:5443 bearer_token_file: token_file tls_config: insecure_skip_verify: true relabel_configs: - regex: (.+) replacement: $1:9100 source_labels: - __meta_kubernetes_node_name target_label: __address__ - target_label: node source_labels: [instance]
-
使prometheus配置生效
curl -X POST http://localhost:9090/-/reload
查看监控页面:
-
- 点赞
- 收藏
- 关注作者
评论(0)