部署prometheus监控kubernetes集群并存储到ceph
简介
Prometheus 最初是 SoundCloud 构建的开源系统监控和报警工具,是一个独立的开源项目,于2016年加入了 CNCF 基金会,作为继 Kubernetes 之后的第二个托管项目。
特征
Prometheus 相比于其他传统监控工具主要有以下几个特点:
具有由 metric 名称和键/值对标识的时间序列数据的多维数据模型
有一个灵活的查询语言
不依赖分布式存储,只和本地磁盘有关
通过 HTTP 的服务拉取时间序列数据
也支持推送的方式来添加时间序列数据
还支持通过服务发现或静态配置发现目标
多种图形和仪表板支持
组件
Prometheus 由多个组件组成,但是其中许多组件是可选的:
Prometheus Server:用于抓取指标、存储时间序列数据
exporter:暴露指标让任务来抓
pushgateway:push 的方式将指标数据推送到该网关
alertmanager:处理报警的报警组件
adhoc:用于数据查询
大多数 Prometheus 组件都是用 Go 编写的,因此很容易构建和部署为静态的二进制文件。
prometheus组件架构图
如上图,每个被监控的主机都可以通过专用的exporter
程序提供输出监控数据的接口,并等待Prometheus
服务器周期性的进行数据抓取。如果存在告警规则,则抓取到数据之后会根据规则进行计算,满足告警条件则会生成告警,并发送到Alertmanager
完成告警的汇总和分发。当被监控的目标有主动推送数据的需求时,可以以Pushgateway
组件进行接收并临时存储数据,然后等待Prometheus
服务器完成数据的采集。
任何被监控的目标都需要事先纳入到监控系统中才能进行时序数据采集、存储、告警和展示,监控目标可以通过配置信息以静态形式指定,也可以让Prometheus通过服务发现的机制进行动态管理。下面是组件的一些解析:
- 监控代理程序:如node_exporter:收集主机的指标数据,如平均负载、CPU、内存、磁盘、网络等等多个维度的指标数据。
- kubelet(cAdvisor):收集容器指标数据,也是K8S的核心指标收集,每个容器的相关指标数据包括:CPU使用率、限额、文件系统读写限额、内存使用率和限额、网络报文发送、接收、丢弃速率等等。
- API Server:收集API Server的性能指标数据,包括控制队列的性能、请求速率和延迟时长等等
- etcd:收集etcd存储集群的相关指标数据
- kube-state-metrics:该组件可以派生出k8s相关的多个指标数据,主要是资源类型相关的计数器和元数据信息,包括制定类型的对象总数、资源限额、容器状态以及Pod资源标签系列等。
Prometheus 能够 直接 把 Kubernetes API Server 作为 服务 发现 系统 使用 进而 动态 发现 和 监控 集群 中的 所有 可被 监控 的 对象。 这里 需要 特别 说明 的 是, Pod 资源 需要 添加 下列 注解 信息 才 能被 Prometheus 系统 自动 发现 并 抓取 其 内建 的 指标 数据。
- 1) prometheus. io/ scrape: 用于 标识 是否 需要 被 采集 指标 数据, 布尔 型 值, true 或 false。
- 2) prometheus. io/ path: 抓取 指标 数据 时 使用 的 URL 路径, 一般 为/ metrics。
- 3) prometheus. io/ port: 抓取 指标 数据 时 使 用的 套 接 字 端口, 如 8080。
另外, 仅 期望 Prometheus 为 后端 生成 自定义 指标 时 仅 部署 Prometheus 服务器 即可, 它 甚至 也不 需要 数据 持久 功能。 但 若要 配置 完整 功能 的 监控 系统, 管理员 还需 要在 每个 主机 上 部署 node_ exporter、 按 需 部署 其他 特有 类型 的 exporter 以及 Alertmanager。
kube-state-metrics与metric-server的对比
metric-server(或heapster)是一个集群组件定期通过kubelet来获取集群节点的cpu、内存使用率这种监控指标,而且它只保留最新数据且存储在内存中,不负责发送给第三方,你可以通过其他方式把他们发送给存储后端,如influxdb或云厂商,他当前的核心作用是:为HPA等组件提供决策指标支持。
kube-state-metrics关注于获取k8s各种资源对象的最新状态,如deployment或者daemonset,它在内存中保留kubernetes集群状态的快照并且在随后的时间里基于这个快照生成新的指标,而且它也不负责发数据发给第三方。将kube-state-metrics作为单独的项目,还可以从Prometheus等监控系统访问这些指标。
之所以没有把kube-state-metrics纳入到metric-server的能力中,是因为他们的关注点本质上是不一样的。metric-server仅仅是获取、格式化现有数据,写入特定的存储,实质上是一个监控系统。而kube-state-metrics是将k8s的运行状况在内存中做了个快照,并且获取新的指标,但他没有能力导出这些指标 换个角度讲,kube-state-metrics本身是metric-server的一种数据来源,虽然现在没有这么做。 另外,像Prometheus这种监控系统,并不会去用metric-server中的数据,他都是自己做指标收集、集成的(Prometheus包含了metric-server的能力),但Prometheus可以监控metric-server本身组件的监控状态并适时报警,这里的监控就可以通过kube-state-metrics来实现,如metric-serverpod的运行状态。
部署前提
检查ceph集群状态
# ceph -s
......
health: HEALTH_OK
检查kubernetes集群状态
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
20.0.0.201 Ready,SchedulingDisabled master 4d9h v1.17.2
20.0.0.202 Ready,SchedulingDisabled master 4d9h v1.17.2
20.0.0.203 Ready,SchedulingDisabled master 4d9h v1.17.2
20.0.0.204 Ready node 4d9h v1.17.2
20.0.0.205 Ready node 4d9h v1.17.2
20.0.0.206 Ready node 4d9h v1.17.2
注:ceph 使用assembly pool,prometheus集群的名称空间为assembly
这里我只给出具体配置,有关详细的理论解释请自行google。
建议:学习本篇之前,先搞通此篇:https://www.cnblogs.com/zisefeizhu/p/12519658.html
部署总述
# pwd
/data/k8s/prometheus
# tree ./
./
├── altermanager
│?? ├── alertmanager-conf.yaml
│?? ├── alertmanager-deployment.yaml
│?? └── alertmanager-svc.yaml
├── ceph-prometheus-storageclass.yaml
├── grafana
│?? ├── grafana-deployment.yaml
│?? ├── grafana-ingressroute.yaml
│?? ├── grafana-pvc.yaml
│?? └── grafana-svc.yaml
├── node-exporter
│?? └── node-exporter.yaml
└── prometheus
├── prometheus-cm.yaml
├── prometheus-deploy.yaml
├── prometheus-ingressroute.yaml
├── prometheus-pvc.yaml
├── prometheus-rbac.yaml
└── prometheus-svc.yaml
4 directories, 15 files
# kubectl get pods -n assembly
NAME READY STATUS RESTARTS AGE
alertmanager-76fd475999-l9pdh 1/1 Running 0 54m
grafana-866bbc647-2kxkk 1/1 Running 0 3h50m
node-exporter-7x5wb 1/1 Running 0 4h2m
node-exporter-8gfsn 1/1 Running 0 4h30m
node-exporter-dsk89 1/1 Running 0 4h30m
node-exporter-jw7ck 1/1 Running 0 4h30m
node-exporter-rcw6c 1/1 Running 0 4h30m
node-exporter-w5sz6 1/1 Running 0 4h30m
prometheus-7d844f7645-x75rp 1/1 Running 0 4h31m
rbd-provisioner-9cf46c856-mvtx5 1/1 Running 15 34h
# kubectl get pvc -n assembly
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
grafana-pvc Bound pvc-8b1550f9-9b7d-4884-b41d-ea10106f9321 5Gi RWO ceph-prometheus 4h46m
prometheus-pvc Bound pvc-3ae3ac53-537f-4641-b626-b74da48db053 10Gi RWO ceph-prometheus 4h31m
部署prometheus
# ll
总用量 4
-rw-r--r-- 1 root root 1018 3月 20 08:33 ceph-prometheus-storageclass.yaml
drwxr-xr-x 2 root root 180 3月 20 20:51 prometheus
# cat ceph-prometheus-storageclass.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: ceph-prometheus-storageclass.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ceph-prometheus
namespace: assembly
annotations:
storageclass.kubernetes.io/is-default-class: "false"
provisioner: ceph.com/rbd
reclaimPolicy: Retain
parameters:
monitors: 20.0.0.205:6789,20.0.0.206:6789,20.0.0.207:6789
adminId: admin
adminSecretName: ceph-admin-secret
adminSecretNamespace: assembly
pool: assembly
fsType: xfs
userId: assembly
userSecretName: ceph-assembly-secret
imageFormat: "2"
imageFeatures: "layering"
# cat prometheus-cm.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: prometheus-cm.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: assembly
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_timeout: 15s
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
rule_files:
- /etc/prometheus/rules.yaml
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'traefik'
static_configs:
- targets: ['traefik.kube-system.svc.cluster.local:8080']
- job_name: "kubernetes-nodes"
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-kubelet'
kubernetes_sd_configs:
- role: node
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
- job_name: "kubernetes-apiserver"
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_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: "kubernetes-scheduler"
kubernetes_sd_configs:
- role: endpoints
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
rules.yaml: |
groups:
- name: test-rule
rules:
- alert: NodeMemoryUsage
expr: (sum(node_memory_MemTotal_bytes) - sum(node_memory_MemFree_bytes + node_memory_Buffers_bytes+node_memory_Cached_bytes)) / sum(node_memory_MemTotal_bytes) * 100 > 5
for: 2m
labels:
team: node
annotations:
summary: "{{$labels.instance}}: High Memory usage detected"
description: "{{$labels.instance}}: Memory usage is above 80% (current value is: {{ $value }}"
# cat prometheus-deploy.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: prometheus-deploy.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: assembly
labels:
app: prometheus
spec:
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
imagePullSecrets:
- name: k8s-harbor-login
serviceAccountName: prometheus
containers:
- image: harbor.linux.com/prometheus/prometheus:v2.4.3
name: prometheus
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention=24h"
- "--web.enable-admin-api" # 控制对admin HTTP API的访问,其中包括删除时间序列等功能
- "--web.enable-lifecycle" # 支持热更新,直接执行localhost:9090/-/reload立即生效
ports:
- containerPort: 9090
protocol: TCP
name: http
volumeMounts:
- mountPath: "/prometheus"
subPath: prometheus
name: data
- mountPath: "/etc/prometheus"
name: config-volume
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 100m
memory: 512Mi
securityContext:
runAsUser: 0
volumes:
- name: data
persistentVolumeClaim:
claimName: prometheus-pvc
- configMap:
name: prometheus-config
name: config-volume
nodeSelector: ## 设置node筛选器,在特定label的节点上启动
prometheus: "true"
# cat prometheus-ingressroute.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: prometheus-ingressroute.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: prometheus
namespace: assembly
spec:
entryPoints:
- web
routes:
- match: Host(`prometheus.linux.com`)
kind: Rule
services:
- name: prometheus
port: 9090
# cat prometheus-pvc.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: prometheus-pvc.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: prometheus-pvc
namespace: assembly
# labels:
# app: gitlab
spec:
storageClassName: ceph-prometheus
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# cat prometheus-rbac.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: prometheus-rbac.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: assembly
---
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: assembly
# cat prometheus-svc.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: prometheus-svc.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: assembly
labels:
app: prometheus
spec:
selector:
app: prometheus
type: NodePort
ports:
- name: web
port: 9090
targetPort: http
# kubectl get pods -n assembly
NAME READY STATUS RESTARTS AGE
prometheus-7d844f7645-x75rp 1/1 Running 0 4h14m
rbd-provisioner-9cf46c856-mvtx5 1/1 Running 14 34h
部署node-exporter
# cat node-exporter.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: node_exporter.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: assembly
labels:
name: node-exporter
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
hostPID: true
hostIPC: true
hostNetwork: true
containers:
- name: node-exporter
image: prom/node-exporter:v0.17.0
ports:
- containerPort: 9100
resources:
requests:
cpu: 0.15
securityContext:
privileged: true
args:
- --path.procfs
- /host/proc
- --path.sysfs
- /host/sys
- --collector.filesystem.ignored-mount-points
- '"^/(sys|proc|dev|host|etc)($|/)"'
volumeMounts:
- name: dev
mountPath: /host/dev
- name: proc
mountPath: /host/proc
- name: sys
mountPath: /host/sys
- name: rootfs
mountPath: /rootfs
tolerations:
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
volumes:
- name: proc
hostPath:
path: /proc
- name: dev
hostPath:
path: /dev
- name: sys
hostPath:
path: /sys
- name: rootfs
hostPath:
path: /
# kubectl get pods -n assembly
NAME READY STATUS RESTARTS AGE
node-exporter-7x5wb 1/1 Running 0 3h45m
node-exporter-8gfsn 1/1 Running 0 4h13m
node-exporter-dsk89 1/1 Running 0 4h13m
node-exporter-jw7ck 1/1 Running 0 4h13m
node-exporter-rcw6c 1/1 Running 0 4h13m
node-exporter-w5sz6 1/1 Running 0 4h13m
grafana部署
# cat grafana-deployment.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: grafana-deployment.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: assembly
labels:
app: grafana
spec:
selector:
matchLabels:
app: grafana
revisionHistoryLimit: 10
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:6.6.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
name: grafana
env:
- name: GF_SECURITY_ADMIN_USER
value: admin
- name: GF_SECURITY_ADMIN_PASSWORD
value: zisefeizhu
readinessProbe:
failureThreshold: 10
httpGet:
path: /api/health
port: 3000
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 30
livenessProbe:
failureThreshold: 10
httpGet:
path: /api/health
port: 3000
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
volumeMounts:
- mountPath: /var/lib/grafana
subPath: grafana
name: storage
securityContext:
fsGroup: 472
runAsUser: 472
volumes:
- name: storage
persistentVolumeClaim:
claimName: grafana-pvc
nodeSelector: ## 设置node筛选器,在特定label的节点上启动
grafana: "true"
# cat grafana-ingressroute.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: grafana-ingressroute.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: grafana
namespace: assembly
spec:
entryPoints:
- web
routes:
- match: Host(`grafana.linux.com`)
kind: Rule
services:
- name: grafana
port: 3000
# cat grafana-pvc.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: grafana-pvc.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: grafana-pvc
namespace: assembly
# labels:
# app: gitlab
spec:
storageClassName: ceph-prometheus
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
# cat grafana-svc.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: grafana-svc.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: assembly
labels:
app: grafana
spec:
type: NodePort
ports:
- port: 3000
selector:
app: grafana
# kubectl get pods -n assembly
NAME READY STATUS RESTARTS AGE
grafana-866bbc647-2kxkk 1/1 Running 0 3h41m
推荐模板
8919 9276 10000
altermanager部署
# cat alertmanager-conf.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: alertmanager-conf.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: ConfigMap
metadata:
name: alert-config
namespace: assembly
data:
config.yml: |-
global:
# 在没有报警的情况下声明为已解决的时间
resolve_timeout: 5m
# 配置邮件发送信息
smtp_smarthost: 'smtp.163.com:25'
smtp_from: '13xxxxxxx91@163.com'
smtp_auth_username: '13xxxxxxx91@163.com'
smtp_auth_password: 'lkxx3x23' #改成自己的密码
smtp_hello: '163.com'
smtp_require_tls: false
# 所有报警信息进入后的根路由,用来设置报警的分发策略
route:
# 这里的标签列表是接收到报警信息后的重新分组标签,例如,接收到的报警信息里面有许多具有 cluster=A 和 alertname=LatncyHigh 这样的标签的报警信息将会批量被聚合到一个分组里面
group_by: ['alertname', 'cluster']
# 当一个新的报警分组被创建后,需要等待至少group_wait时间来初始化通知,这种方式可以确保您能有足够的时间为同一分组来获取多个警报,然后一起触发这个报警信息。
group_wait: 30s
# 当第一个报警发送后,等待'group_interval'时间来发送新的一组报警信息。
group_interval: 30m
# 如果一个报警信息已经发送成功了,等待'repeat_interval'时间来重新发送他们
repeat_interval: 30m
# 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器
receiver: default
# 上面所有的属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。
routes:
- receiver: email
group_wait: 10s
match:
team: node
receivers:
- name: 'default'
email_configs:
- to: '23xxxxxx0@qq.com'
send_resolved: true
# cat alertmanager-deployment.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: alertmanager-deployment.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: apps/v1
kind: Deployment
metadata:
name: alertmanager
namespace: assembly
spec:
selector:
matchLabels:
app: alertmanager
replicas: 1
template:
metadata:
labels:
app: alertmanager
spec:
containers:
- name: alertmanager
image: prom/alertmanager:v0.15.3
imagePullPolicy: IfNotPresent
args:
- "--config.file=/etc/alertmanager/config.yml"
- "--storage.path=/alertmanager/data"
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 100m
memory: 256Mi
volumeMounts:
- name: alert-config
mountPath: /etc/alertmanager
ports:
- name: http
containerPort: 9093
volumes:
- name: alert-config
configMap:
name: alert-config
nodeSelector: ## 设置node筛选器,在特定label的节点上启动
alter: "true"
# cat alertmanager-svc.yaml
##########################################################################
#Author: zisefeizhu
#QQ: 2********0
#Date: 2020-03-20
#FileName: alertmanager-svc.yaml
#URL: https://www.cnblogs.com/zisefeizhu/
#Description: The test script
#Copyright (C): 2020 All rights reserved
###########################################################################
apiVersion: v1
kind: Service
metadata:
name: alertmanager
namespace: assembly
annotations:
prometheus.io/scrape: "true"
spec:
selector:
app: alertmanager
ports:
- name: http
port: 9093
Prometheus配置文件说明
# Kubernetes的API SERVER会暴露API服务,Promethues集成了对Kubernetes的自动发现,它有5种模式:Node、Service
# 、Pod、Endpoints、ingress,下面是Prometheus官方给出的对Kubernetes服务发现的实例。这里你会看到大量的relabel_configs,
# 其实你就是把所有的relabel_configs去掉一样可以对kubernetes做服务发现。relabel_configs仅仅是对采集过来的指标做二次处理,比如
# 要什么不要什么以及替换什么等等。而以__meta_开头的这些元数据标签都是实例中包含的,而relabel则是动态的修改、覆盖、添加删除这些标签
# 或者这些标签对应的值。而且以__开头的标签通常是系统内部使用的,因此这些标签不会被写入样本数据中,如果我们要收集这些东西那么则要进行
# relabel操作。当然reabel操作也不仅限于操作__开头的标签。
#
# action的行为:
# replace:默认行为,不配置action的话就采用这种行为,它会根据regex来去匹配source_labels标签上的值,并将并将匹配到的值写入target_label中
# labelmap:它会根据regex去匹配标签名称,并将匹配到的内容作为新标签的名称,其值作为新标签的值
# keep:仅收集匹配到regex的源标签,而会丢弃没有匹配到的所有标签,用于选择
# drop:丢弃匹配到regex的源标签,而会收集没有匹配到的所有标签,用于排除
# labeldrop:使用regex匹配标签,符合regex规则的标签将从target实例中移除,其实也就是不收集不保存
# labelkeep:使用regex匹配标签,仅收集符合regex规则的标签,不符合的不收集
#
global:
scrape_interval: 10s
evaluation_interval: 30s
scrape_configs:
# 用于发现API SERVER
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
# 发现endpoints,它是从列出的服务端点发现目标,这个endpoints来自于Kubernetes中的service,每一个service都有对应的endpoints,这里是一个列表
# 可以是一个IP:PORT也可以是多个,这些IP:PORT就是service通过标签选择器选择的POD的IP和端口。所以endpoints角色就是用来发现server对应的pod的IP的
# kubernetes会有一个默认的service,通过找到这个service的endpoints就找到了api server的IP:PORT,那endpoints有很多,我怎么知道哪个是api server呢
# 这个就靠source_labels指定的标签名称了。
- role: endpoints
# 通过什么形式来连接,默认是https
scheme: https
# 下面这个ca_file和token_file的路径都是默认的,你可能默认设置能用么?其实可以,因为每一个运行起来的POD kubernetes都会为其
# 创建一个serviceaccout的Secret并且挂载到下面的目录上,里面就有ca.crt和token这两个文件,你可以自己启动一个POD,然后通过
# kubectl describe pods 来查看,一定会在Volumes下面有一个default-token-XXX的东西,并且Mounts里面有下面的目录。
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
# 下面的含义是源标签__meta_kubernetes_namespace等如果其值为default;kubernetes;https标签顺序和值要对应。换句话说就是
# 当__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name三者对应的
# 值为default、kubernetes、https则进行保留,而且该endpoints对应的地址为api server的地址。
#
# __meta_kubernetes_namespace 端点对象的命名空间,在不同对象上这个标签的含义不同,在角色是endpoints中这个是端点对象的名称空间
# __meta_kubernetes_service_name 端点对象的服务名称
# __meta_kubernetes_endpoint_port_name 端点的端口名称
#
# kubernetes默认在default名称空间有一个叫做kubernetes的service,所以这个service的有3个设置对应的就是下面三个标签
# __meta_kubernetes_namespace 值为default
# __meta_kubernetes_service_name 值为kubernetes
# __meta_kubernetes_endpoint_port_name 值为https
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
# 配置针对kubelet的服务发现以及对标签的处理,是获取kubelet上/metrics接口数据来获取node的资源使用情况
- job_name: 'kubernetes-nodes-kubelet'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# 跳过CA验证
# insecure_skip_verify: true
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
# 使用node角色,它使用默认的kubelet提供的http端口来发现集群中每个node节点。那具体地址是什么呢?
# 地址类型有四种NodeInternalIP, NodeExternalIP, NodeLegacyHostIP 和 NodeHostName,默认为这四个中第一个可用的地址。
# 那么这里为什么使用node角色呢?因为node角色就是用来发现kubelet的
# __meta_kubernetes_node_name:节点对象的名字
# __meta_kubernetes_node_label_<labelname>:表示节点对象上的每一个标签
# __meta_kubernetes_node_annotation_<annotationname>:表示节点对象上的每一个annotation
# __meta_kubernetes_node_address_<address_type>:如果存在,那么将是每一个节点地址类型的第一个地址
# Node模式,Prometheus会自动发现Kubernetes中所有Node节点的信息并作为监控的目标Target。
# 而这些Target的访问地址实际上就是Kubelet的访问地址,并且Kubelet实际上直接内置了对Promtheus的支持
- role: node
relabel_configs:
# 保留(.+)匹配到的内容,去掉__meta_kubernetes_node_label_,实际上就是把(.+)当做新标签,然后老标签的值给这个新标签,
# 这里没有设置source_labels,则表示匹配所有标签
- action: labelmap
# 匹配节点对象上的每一个标签
regex: __meta_kubernetes_node_label_(.+)
# 抓取cAdvisor数据,是获取kubelet上/metrics/cadvisor接口数据来获取容器的资源使用情况
- job_name: 'kubernetes-nodes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
# 使用角色为node
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
# 把__metrics_path__的值替换为/metrics/cadvisor,因为默认是/metrics
- target_label: __metrics_path__
replacement: /metrics/cadvisor
# 抓取服务端点,整个这个任务都是用来发现node-exporter和kube-state-metrics-service的,这里用的是endpoints角色,这是通过这两者的service来发现
# 的后端endpoints。另外需要说明的是如果满足采集条件,那么在service、POD中定义的labels也会被采集进去
- job_name: 'kubernetes-service-endpoints'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
# 重新打标仅抓取到的具有 "prometheus.io/scrape: true" 的annotation的端点,意思是说如果某个service具有prometheus.io/scrape = true annotation声明则抓取
# annotation本身也是键值结构,所以这里的源标签设置为键,而regex设置值,当值匹配到regex设定的内容时则执行keep动作也就是保留,其余则丢弃.
# node-exporter这个POD的service里面就有一个叫做prometheus.io/scrape = true的annotations所以就找到了node-exporter这个POD
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
# 应用中自定义暴露的指标,也许你暴露的API接口不是/metrics这个路径,那么你可以在这个POD对应的service中做一个
# "prometheus.io/path = /mymetrics" 声明,下面的意思就是把你声明的这个路径赋值给__metrics_path__
# 其实就是让prometheus来获取自定义应用暴露的metrices的具体路径,不过这里写的要和service中做好约定
# 如果service中这样写 prometheus.io/app-metrics-path: '/metrics' 那么你这里就要
# __meta_kubernetes_service_annotation_prometheus_io_app_metrics_path这样写
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
# 暴露自定义的应用的端口,就是把地址和你在service中定义的 "prometheus.io/port = <port>" 声明做一个拼接
# 然后赋值给__address__,这样prometheus就能获取自定义应用的端口,然后通过这个端口再结合__metrics_path__来获取
# 指标,如果__metrics_path__值不是默认的/metrics那么就要使用上面的标签替换来获取真正暴露的具体路径
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
# 重新设置scheme
# 匹配源标签__meta_kubernetes_service_annotation_prometheus_io_scheme也就是prometheus.io/scheme annotation
# 如果源标签的值匹配到regex则把值替换为__scheme__对应的值
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
# 下面主要是为了给样本添加额外信息
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
# 下面是自动发现service,不过如果要想监控service则需要安装blackbox-exporter
- job_name: 'kubernetes-services-http'
metrics_path: /probe
# 生成__param_module="http_2xx"的label,如果是TCP探测则使用 module: [tcp_connect]
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: service
relabel_configs:
# 为了让service可以被探测到,那需要在service的annotation中增加 prometheus.io/scrape: true 声明
# 也就是只保留prometheus.io/scrape: true的service
- action: keep
regex: true
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_scrape
# 用__address__这个label的值创建一个名为__param_target的label为blackbox-exporter,值为内部service的访问地址,作为blackbox-exporter采集用
- source_labels: [__address__]
target_label: __param_target
# 用blackbox-exporter的service地址值”prometheus-blackbox-exporter:9115"替换原__address__的值
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
# 下面主要是为了给样本添加额外信息
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
target_label: kubernetes_name
# 下面是对ingresses监控,不过如果要想监控ingresses则需要安装blackbox-exporter
- job_name: 'kubernetes-ingresses'
metrics_path: /probe
# 生成__param_module="http_2xx"的label
params:
module: [http_2xx]
kubernetes_sd_configs:
- role: ingress
relabel_configs:
# Example relabel to probe only some ingresses that have "example.io/should_be_probed = true" annotation
# - source_labels: [__meta_kubernetes_ingress_annotation_example_io_should_be_probed]
# action: keep
# regex: true
- source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
regex: (.+);(.+);(.+)
replacement: ${1}://${2}${3}
target_label: __param_target
- target_label: __address__
replacement: blackbox-exporter.example.com:9115
- source_labels: [__param_target]
target_label: instance
# 下面主要是为了给样本添加额外信息
- action: labelmap
regex: __meta_kubernetes_ingress_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_ingress_name]
target_label: kubernetes_name
# 抓取POD进行监控
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
# POD的 annotation 中含有"prometheus.io/scrape: true" 的则保留,意思就是会被Prometheus抓取,不具有这个的POD则不会被抓取
- action: keep
regex: true
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_scrape
# 获取POD的 annotation 中定义的"prometheus.io/path: XXX"定义的值,这个值就是你的程序暴露符合prometheus规范的metrics的地址
# 如果你的metrics的地址不是 /metrics 的话,通过这个标签说,那么这里就会把这个值赋值给 __metrics_path__这个变量,因为prometheus
# 是通过这个变量获取路径然后进行拼接出来一个完整的URL,并通过这个URL来获取metrics值的,因为prometheus默认使用的就是 http(s)://X.X.X.X/metrics
# 这样一个路径来获取的。
- action: replace
regex: (.+)
source_labels:
- __meta_kubernetes_pod_annotation_prometheus_io_path
target_label: __metrics_path__
# 这里是端口信息,因为你的程序很有可能在容器中并不是以80端口运行的,那么就需要做一个拼接http(s)://x.x.x.x:xx/metrics
# __address__在prometheus中代表的就是实例的IP地址,而POD中的annotation 中定义的"prometheus.io/port: XX"就是你程序
# 被访问到的端口,最终在prometheus中将会被显示为 instance=X.X.X.X:XX这样
- action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
source_labels:
- __address__
- __meta_kubernetes_pod_annotation_prometheus_io_port
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
后续:
本篇严格来说是完成了一部分,还有些监控项、监控策略、告警平台没有加入,会补的。