prometheus概述
Prometheus 是一个开源的服务监控系统和时序数据库,其提供了通用的数据模型和快捷数据采集、存储和查询接口。它的核心组件 Prometheus server 会定期从静态配置的监控目标或者基于服务发现自动配置的目标中进行拉取数据,当新拉取到的数据大于配置的内存缓存区时,数据就会持久化到存储设备当中。每个采样数据占3.5 bytes左右,300万的时间序列,30s间隔,保留60天,消耗磁盘大概200G。
每个被监控的主机都可以通过专用的 exporter 程序提供输出监控数据的接口,它会在目标处收集监控数据,并暴露出一个 HTTP接口供 Prometheus server 查询,Prometheus 通过基于 HTTP 的 pull 的方式来(周期性)的采集数据。 如果存在告警规则,则抓取到数据之后会根据规则进行计算,满足告警条件则会生成告警,并发送到 Alertmanager 完成告警的汇总和分发。当被监控的目标有主动推送数据的需求时,可以以 Pushgateway 组件进行接收并临时存储数据,然后等待 Prometheus server 完成数据的采集。
任何被监控的目标都需要事先纳入到监控系统中才能进行时序数据采集、存储、告警和展示,监控目标可以通过(配置信息以静态形式指定),就是(手动配置),也可以让 Prometheus 通过服务发现的机制进行(动态管理)。Prometheus 能够直接把 API Server 作为服务发现系统使用,进而动态发现和监控集群中的所有可被监控的对象。
prometheus特性 Prometheus特性:
多维的数据模型(基于时间序列的Key、value键值对)
灵活的查询和聚合语言PromQL
提供本地存储和分布式存储
通过基于HTTP和HTTPS的Pull模型采集时间序列数据(pull数据的拉取,时间序列:每段 时间点的数据值指标,持续性的产生。横轴标识时间,纵轴为数据值,一段时间内数值的动态变化,所有的点连线形成大盘式的折线图)可利用Pushgateway (Prometheus的可选中间件)实现Push模式
可通过动态服务发现或静态配置发现目标机器(通过consul自动发现和收缩)
支持多种图表和数据大盘
prometheus的核心组件 整个Prometheus生态包含多个组件,除了Prometheus server组件其余都是可选的
Prometheus的核心组件:
Prometheus Server:主要的核心组件,用来收集和存储时间序列数据。
Client Library::客户端库,为需要监控的服务生成相应的 metrics 并暴露给 Prometheus server。当 Prometheus server 来 pull 时,直接返回实时状态的 metrics。
push gateway:主要用于短期的 jobs。由于这类 jobs 存在时间较短,可能在 Prometheus 来 pull 之前就消失了。为此,这次 jobs 可以直接向 Prometheus server 端推送它们的 metrics。这种方式主要用于服务层面的 metrics,对于机器层面的 metrices,需要使用 node exporter。
Exporters: 用于暴露已有的第三方服务的 metrics 给 Prometheus。
Alertmanager: 从 Prometheus server 端接收到 alerts 后,会进行去除重复数据,分组,并路由到对收的接受方式,发出报警。常见的接收方式有:电子邮件,pagerduty,OpsGenie, webhook 等。 各种支持工具。
组件说明:
Prometheus server:服务核心组件,采用 pull 方式收集 apiserver、scheduler、controller-manager、kubelet 组件数据, 通过 http 协议传输。并存储时间序列数据。
Exporters/Jobs:负责收集不支持Instrumentation的目标对象(host, container…)的性能数据,并通过 HTTP 接口供 Prometheus Server 获取。
Node-Exporter:用于收集k8s集群中各node节点的物理指标状态数据,如平均负载、CPU、内存、磁盘、网络等资源信息的指标数据,需要部署到所有运算节点。
Kube-State-Metrics:为prometheus采集k8s资源数据的exporter,通过监听APIServer收集kubernetes集群内资源对象的状态指标数据,例如pod、deployment、service等等。同时它也提供自己的数据,主要是资源采集个数和采集发生的异常次数统计。 需要注意的是kube-state-metrics只是简单的提供一个metrics数据,并不会存储这些指标数据,所以可以使用Prometheus来抓取这些数据然后存储,主要关注的是业务相关的一些元数据,比如Deployment、Pod、副本状态等;调度了多少个replicas?现在可用的有几个?多少个Pod是running/stopped/terminated状态?Pod重启了多少次?有多少job在运行中。
cadvisor:用来监控容器内部使用资源的信息,比如 CPU、内存、网络I/O、磁盘I/O。
blackbox-exporter:监控业务容器存活性。
Service Discovery:服务发现,Prometheus支持多种服务发现机制:文件,DNS,Consul,Kubernetes,OpenStack,EC2等等。 基于服务发现的过程并不复杂,通过第三方提供的接口,Prometheus查询到需要监控的Target列表,然后轮训这些Target获取监控数据。
Alertmanager:是一个独立的告警模块,从 Prometheus server 端接收到 alerts 后,会进行去重、分组, 并路由到相应的接收方,发出报警,常见的接收方式有:电子邮件,微信,钉钉等。
Pushgateway:类似一个中转站,Prometheus 的 server 端只会使用 pull 方式拉取数据,但是某些节点因为某些原因只能使用 push 方式推送数据,那么它就是用来接收 push 而来的数据并暴露给 Prometheus 的 server 拉取的中转站。 可以理解成目标主机可以上报短期任务的数据到 Pushgateway,然后 Prometheus server 统一从 Pushgateway 拉取数据。
Grafana:是一个跨平台的开源的度量分析和可视化工具,可以将采集的数据可视化的展示,并及时通知给告警接收方。其官方库中具有丰富的仪表盘插件。
prometheus工作流程
Prometheus 以 Prometheus Server 为核心,用于收集和存储时间序列数据。Prometheus Server 从监控目标中通过 pull 方式拉取指标数据,或通过 pushgateway 把采集的数据拉取到 Prometheus server 中。
Prometheus server 把采集到的监控指标数据通过 TSDB 存储到本地 HDD/SSD 中。
Prometheus 采集的监控指标数据按时间序列存储,通过配置报警规则,把触发的报警发送到 Alertmanager。
Alertmanager 通过配置报警接收方,通过告警媒介发送告警。
Prometheus 自带的 Web UI 界面提供 PromQL 查询语言,可查询监控数据。
Grafana 可接入 Prometheus 数据源,把监控数据以图形化形式展示。
K8S部署prometheus node-exporter 安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 # 创建 namespace kubectl create ns monitor # 部署 node-exporter mkdir /opt/prometheus cd /opt/prometheus/ vim node-export.yaml --- apiVersion: apps/v1 kind: DaemonSet metadata: name: node-exporter namespace: monitor 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.16.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: /
hostNetwork、hostIPC、hostPID都为True时,表示这个Pod里的所有容器,会直接使用宿主机的网络,直接与宿主机进行IPC(进程间通信)通信,可以看到宿主机里正在运行的所有进程。加入了hostNetwork:true会直接将我们的宿主机的9100端口映射出来,从而不需要创建service在我们的宿主机上就会有一个9100的端口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 # 通过 node-exporter 采集数据 node-exporter 默认的监听端口是 9100,可以执行 curl http://主机ip:9100/metrics 获取到主机的所有监控数据 # curl -Ls http://10.0.20.9:9100/metrics | grep node_cpu_seconds # HELP node_cpu_seconds_total Seconds the cpus spent in each mode. # TYPE node_cpu_seconds_total counter node_cpu_seconds_total{cpu="0",mode="idle"} 4.47878973e+06 node_cpu_seconds_total{cpu="0",mode="iowait"} 26232.28 node_cpu_seconds_total{cpu="0",mode="irq"} 0 node_cpu_seconds_total{cpu="0",mode="nice"} 10.24 node_cpu_seconds_total{cpu="0",mode="softirq"} 15960.81 node_cpu_seconds_total{cpu="0",mode="steal"} 0 node_cpu_seconds_total{cpu="0",mode="system"} 91055.91 node_cpu_seconds_total{cpu="0",mode="user"} 257706.46 node_cpu_seconds_total{cpu="1",mode="idle"} 4.49500089e+06 node_cpu_seconds_total{cpu="1",mode="iowait"} 28299.16 node_cpu_seconds_total{cpu="1",mode="irq"} 0 node_cpu_seconds_total{cpu="1",mode="nice"} 20.3 node_cpu_seconds_total{cpu="1",mode="softirq"} 5850.46 node_cpu_seconds_total{cpu="1",mode="steal"} 0 node_cpu_seconds_total{cpu="1",mode="system"} 92561.21 node_cpu_seconds_total{cpu="1",mode="user"} 256952.66 # curl -Ls http://10.0.20.9:9100/metrics | grep node_load # HELP node_load1 1m load average. # TYPE node_load1 gauge node_load1 0.03 # HELP node_load15 15m load average. # TYPE node_load15 gauge node_load15 0.24 # HELP node_load5 5m load average. # TYPE node_load5 gauge node_load5 0.09
创建 sa 账号,对 sa 做 rbac 授权 1 2 3 4 5 # 创建一个 sa 账号 monitor kubectl create serviceaccount monitor -n monitor # 把 sa 账号 monitor 通过 clusterrolebing 绑定到 clusterrole 上 kubectl create clusterrolebinding monitor-clusterrolebinding -n monitor --clusterrole=cluster-admin --serviceaccount=monitor-sa:monitor
配置prometheus.yml 配置prometheus.yml以获取监控数据到Prometheus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 --- kind: ConfigMap apiVersion: v1 metadata: labels: app: prometheus name: prometheus-config namespace: monitor data: prometheus.yml: | alerting: alertmanagers: - static_configs: - targets: ["alertmanager:9093"] rule_files: - /etc/prometheus/rules.yml global: #指定prometheus的全局配置,比如采集间隔,抓取超时时间等 scrape_interval: 15s #采集目标主机监控数据的时间间隔,默认为1m scrape_timeout: 10s #数据采集超时时间,默认10s evaluation_interval: 1m #触发告警生成alert的时间间隔,默认是1m scrape_configs: #配置数据源,称为target,每个target用job_name命名。又分为静态配置和服务发现 - job_name: 'kafka-exporter' static_configs: - targets: ['kafka-exporter:9308'] - job_name: 'kubernetes-node' kubernetes_sd_configs: # *_sd_configs 指定的是k8s的服务发现 - role: node #使用node角色,它使用默认的kubelet提供的http端口来发现集群中每个node节点 relabel_configs: #重新标记 - source_labels: [__address__] #配置的原始标签,匹配地址 regex: '(.*):10250' #匹配带有10250端口的url replacement: '${1}:9100' #把匹配到的ip:10250的ip保留 target_label: __address__ #新生成的url是${1}获取到的ip:9100 action: replace #动作替换 - action: labelmap regex: __meta_kubernetes_node_label_(.+) #匹配到下面正则表达式的标签会被保留,如果不做regex正则的话,默认只是会显示instance 标签 - job_name: 'k8s-cadvisor' #抓取cAdvisor数据,是获取kubelet上/metrics/cadvisor接口数据来获取容器的资源使用情况 kubernetes_sd_configs: - role: node 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: - action: labelmap #把匹配到的标签保留 regex: __meta_kubernetes_node_label_(.+) #保留匹配到的具有__meta_kubernetes_node_label的标签 - target_label: __address__ #获取到的地址:__address__="192.168.80.20:10250" replacement: kubernetes.default.svc:443 #把获取到的地址替换成新的地址kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) #把原始标签中__meta_kubernetes_node_name值匹配到 target_label: __metrics_path__ #获取__metrics_path__对应的值 replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor #把metrics替换成新的值api/v1/nodes/k8s-master1/proxy/metrics/cadvisor #${1}是__meta_kubernetes_node_name获取到的值 #新的url就是https://kubernetes.default.svc:443/api/v1/nodes/k8s-master1/proxy/metrics/cadvisor metric_relabel_configs: - source_labels: [instance] separator: ; regex: (.+) target_label: node replacement: $1 action: replace - job_name: 'kubernetes-apiserver' kubernetes_sd_configs: - role: endpoints #使用k8s中的endpoint服务发现,采集apiserver 6443端口获取到的数据 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] #[endpo int这个对象的名称空间,endpoint对象的服务名,exnpoint的端口名称] action: keep #采集满足条件的实例,其他实例不采集 regex: default;kubernetes;https #正则匹配到的默认空间下的service名字是kubernetes,协议是https的endpoint类型保留下来 - 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 #重新打标仅抓取到的具有"prometheus.io/scrape: true"的annotation的端点, 意思是说如果某个service具有prometheus.io /scrape = true的annotation声明则抓取,annotation本身也是键值结构, 所以这里的源标签设置为键,而regex设置值true,当值匹配到regex设定的 内容时则执行keep动作也就是保留,其余则丢弃。 - 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 #替换__meta_kubernetes_namespace变成kubernetes_namespace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] action: replace target_label: kubernetes_name - job_name: kube-state-metrics kubernetes_sd_configs: - role: endpoints namespaces: names: - ops-monit relabel_configs: - source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name] regex: kube-state-metrics replacement: $1 action: keep - job_name: 'k8s-kubelet' 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: - role: node relabel_configs: - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics
创建PV和PVC 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 # 将 prometheus 调度到对应节点,在节点创建 prometheus 数据存储目录 mkdir /home/prometheus && chmod 777 /home/prometheus # cat prometheus-pv.yamlapiVersion: v1 kind: PersistentVolume metadata: name: prometheus-pv namespace: monitor spec: accessModes: - ReadWriteOnce capacity: storage: 5Gi hostPath: path: /home/prometheus persistentVolumeReclaimPolicy: Retain storageClassName: manual # cat prometheus-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: prometheus-pvc namespace: monitor spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi storageClassName: manual
部署 prometheus 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 apiVersion: apps/v1 kind: Deployment metadata: name: prometheus-server namespace: monitor labels: app: prometheus spec: replicas: 1 selector: matchLabels: app: prometheus component: server #matchExpressions: #- {key: app, operator: In, values: [prometheus]} #- {key: component, operator: In, values: [server]} template: metadata: labels: app: prometheus component: server annotations: prometheus.io/scrape: 'false' spec: nodeName: vm-20-9-centos #指定pod调度到哪个节点上 serviceAccountName: monitor containers: - name: prometheus image: quay.io/prometheus/prometheus:v3.0.0 #image: docker.rainbond.cc/prom/prometheus:v2.2.1 imagePullPolicy: IfNotPresent command: - prometheus - --config.file=/etc/prometheus/prometheus.yml # - --storage.tsdb.path=/prometheus #数据存储目录 # - --storage.tsdb.retention=720h #数据保存时长 - --web.enable-lifecycle #开启热加载 ports: - containerPort: 9090 protocol: TCP resources: requests: cpu: 200m memory: 800Mi volumeMounts: - mountPath: /etc/prometheus/prometheus.yml name: prometheus-config subPath: prometheus.yml - mountPath: /etc/prometheus/rules.yml name: prometheus-config subPath: rules.yml - mountPath: /prometheus/ name: prometheus-storage-volume volumes: - name: prometheus-config configMap: name: prometheus-config items: - key: prometheus.yml path: prometheus.yml mode: 0644 - key: rules.yml path: rules.yml mode: 0644 - name: prometheus-storage-volume persistentVolumeClaim: claimName: prometheus-pvc
创建service 创建一个nodeport,prometheus运行正常后便可以通过kubernetes的节点IP:31000访问prometheus web界面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 --- apiVersion: v1 kind: Service metadata: name: prometheus namespace: monitor labels: app: prometheus spec: type: NodePort ports: - port: 9090 targetPort: 9090 protocol: TCP nodePort: 31000 selector: app: prometheus component: server
通过上面可以看到 service 在 node 节点上映射的端口是 31000,这样我们访问 k8s 集群的 node 节点的 ip:31000,就可以访问到 prometheus 的 web ui 界面了。
点击页面的Status->Targets,如看到所有 Target 状态都为 UP,说明配置的服务发现可以正常采集数据
Prometheus 热加载 查看prometheus svc的IP
# kubectl get svc prometheus -n monitor
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus NodePort 10.105.100.246 <none> 9090:31000/TCP 71d
通过接口调用来使prometheus配置热加载
1 curl -X POST -Ls http://10.105.100.246:9090/-/reload
可以查看prometheus中有关于热加载的日志
1 2 3 4 # kubectl logs prometheus-server-649ddb4cbd-44fpp -n monitor time=2025-02-18T08:03:56.283Z level=INFO source=main.go:1446 msg="Loading configuration file" filename=/etc/prometheus/prometheus.yml time=2025-02-18T08:03:56.321Z level=INFO source=main.go:1495 msg="Completed loading of configuration file" db_storage=4.566µs remote_storage=2.084µs web_handler=1.905µs query_engine=1.256µs scrape=2.95273ms scrape_sd=48.042µs notify=138.984µs notify_sd=5.922µs rules=11.240964ms tracing=8.405µs filename=/etc/prometheus/prometheus.yml totalDuration=37.917153ms
一般热加载速度比较慢,可以通过重启prometheus来快速生效配置
1 2 3 4 5 6 修改配置文件 prometheus-config.yaml 替换配置文件 kubectl replace -f prometheus-config.yaml 重启prometheus的deploy kubectl rollout restart deploy prometheus-server -n monitor
注意:线上环境建议使用热加载,删除可能造成监控数据的丢失
Grafana安装 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 --- apiVersion: apps/v1 kind: Deployment metadata: labels: app: grafana name: grafana namespace: kube-system spec: selector: matchLabels: app: grafana template: metadata: labels: app: grafana spec: nodeName: vm-20-9-centos securityContext: fsGroup: 472 supplementalGroups: - 0 containers: - name: grafana image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/grafana/grafana:9.5.12 imagePullPolicy: IfNotPresent ports: - containerPort: 3000 name: http-grafana protocol: TCP readinessProbe: failureThreshold: 3 httpGet: path: /robots.txt port: 3000 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 30 successThreshold: 1 timeoutSeconds: 2 livenessProbe: failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 tcpSocket: port: 3000 timeoutSeconds: 1 resources: requests: cpu: 250m memory: 750Mi volumeMounts: - mountPath: /var/lib/grafana name: grafana-pv volumes: - name: grafana-pv persistentVolumeClaim: claimName: grafana-pvc --- apiVersion: v1 kind: Service metadata: namespace: kube-system name: grafana spec: ports: - port: 3000 protocol: TCP targetPort: http-grafana nodePort: 32690 selector: app: grafana sessionAffinity: None type: NodePort
Grafana 配置 使用service的集群内部端口配置prometheus服务端地址
prometheus对应着服务名称
monitor为Service所在的命名空间
svc.cluster.local是在所有集群本地服务名称中使用的可配置集群后缀
k8s 部署 kube-state-metrics 组件 安装 kube-state-metrics 组件和 service 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 创建namespace kubectl create namespace ops-monit # cat cluster-role.yamlapiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/version: v2.11.0 name: kube-state-metrics rules: - apiGroups: - "" resources: - configmaps - secrets - nodes - pods - services - resourcequotas - replicationcontrollers - limitranges - persistentvolumeclaims - persistentvolumes - namespaces - endpoints verbs: - list - watch - apiGroups: - extensions resources: - daemonsets - deployments - replicasets - ingresses verbs: - list - watch - apiGroups: - apps resources: - statefulsets - daemonsets - deployments - replicasets verbs: - list - watch - apiGroups: - batch resources: - cronjobs - jobs verbs: - list - watch - apiGroups: - autoscaling resources: - horizontalpodautoscalers verbs: - list - watch - apiGroups: - authentication.k8s.io resources: - tokenreviews verbs: - create - apiGroups: - authorization.k8s.io resources: - subjectaccessreviews verbs: - create - apiGroups: - policy resources: - poddisruptionbudgets verbs: - list - watch - apiGroups: - certificates.k8s.io resources: - certificatesigningrequests verbs: - list - watch - apiGroups: - storage.k8s.io resources: - storageclasses - volumeattachments verbs: - list - watch - apiGroups: - admissionregistration.k8s.io resources: - mutatingwebhookconfigurations - validatingwebhookconfigurations verbs: - list - watch - apiGroups: - networking.k8s.io resources: - networkpolicies - ingresses verbs: - list - watch - apiGroups: - coordination.k8s.io resources: - leases verbs: - list - watch # cat cluster-role-binding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/version: v2.11.0 name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kube-state-metrics subjects: - kind: ServiceAccount name: kube-state-metrics namespace: ops-monit # cat service-account.yaml apiVersion: v1 kind: ServiceAccount metadata: labels: app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/version: v2.11.0 name: kube-state-metrics namespace: ops-monit # cat deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/version: v2.11.0 name: kube-state-metrics namespace: ops-monit spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: kube-state-metrics template: metadata: labels: app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/version: v2.11.0 spec: containers: - image: registry.cn-shenzhen.aliyuncs.com/starsl/kube-state-metrics:v2.11.0 livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 5 timeoutSeconds: 5 name: kube-state-metrics ports: - containerPort: 8080 name: http-metrics - containerPort: 8081 name: telemetry readinessProbe: httpGet: path: / port: 8081 initialDelaySeconds: 5 timeoutSeconds: 5 nodeSelector: kubernetes.io/os: linux serviceAccountName: kube-state-metrics # cat service.yaml apiVersion: v1 kind: Service metadata: # annotations: # prometheus.io/scrape: 'true' labels: app.kubernetes.io/name: kube-state-metrics app.kubernetes.io/version: v2.11.0 name: kube-state-metrics namespace: ops-monit spec: clusterIP: None ports: - name: http-metrics port: 8080 targetPort: http-metrics - name: telemetry port: 8081 targetPort: telemetry selector: app.kubernetes.io/name: kube-state-metrics
Prometheus JOB配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 - job_name: 'k8s-kubelet' 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: - role: node relabel_configs: - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics - job_name: 'k8s-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: - role: node relabel_configs: - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor metric_relabel_configs: - source_labels: [instance] separator: ; regex: (.+) target_label: node replacement: $1 action: replace - job_name: kube-state-metrics kubernetes_sd_configs: - role: endpoints namespaces: names: - ops-monit relabel_configs: - source_labels: [__meta_kubernetes_service_label_app_kubernetes_io_name] regex: kube-state-metrics replacement: $1 action: keep
grafana 导入K8S Dashboard CN 20240513 StarsL.cn模板
Prometheus报警处理流程 Prometheus报警处理流程:
Prometheus Server 监控目标主机上暴露的 http接口(假设接口A),通过Promethes配置的’scrape_interval’ 定义的时间间隔, 定期采集目标主机上监控数据。
当接口A不可用的时候,Server 端会持续的尝试从接口中取数据,直到 “scrape_timeout” 时间后停止尝试。 这时候把接口的状态变为 “DOWN”。
Prometheus 同时根据配置的 evaluation_interval 的时间间隔,定期(默认1min)的对 Alert Rule 进行评估; 当到达评估周期的时候,发现接口A为 DOWN,即 UP=0 为真,激活 Alert,进入 PENDING 状态,并记录当前 active 的时间;
当下一个 alert rule 的评估周期到来的时候,发现 UP=0 继续为真,然后判断警报 Active 的时间是否已经超出 rule 里的 for 持续时间,如果未超出,则进入下一个评估周期;如果时间超出,则 alert 的状态变为 FIRING;同时调用 Alertmanager 接口, 发送相关报警数据。
AlertManager 收到报警数据后,会将警报信息进行分组,然后根据 alertmanager 配置的 group_wait 时间先进行等待。等 wait 时间过后再发送报警信息。
属于同一个 Alert Group的警报,在等待的过程中可能进入新的 alert,如果之前的报警已经成功发出,那么间隔 group_interval 的时间间隔后再重新发送报警信息。比如配置的是邮件报警,那么同属一个 group 的报警信息会汇总在一个邮件里进行发送。
如果 Alert Group里的警报一直没发生变化并且已经成功发送,等待 repeat_interval 时间间隔之后再重复发送相同的报警邮件; 如果之前的警报没有成功发送,则相当于触发第6条条件,则需要等待 group_interval 时间间隔后重复发送。
同时最后至于警报信息具体发给谁,满足什么样的条件下指定警报接收人,设置不同报警发送频率,这里使用 alertmanager 的 route 路由规则进行配置。
Prometheus 及 Alertmanager 配置 创建 alertmanager 配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 apiVersion: v1 kind: ConfigMap metadata: name: alert-config namespace: monitor data: config.yml: |- global: # 当alertmanager持续多长时间未接收到告警后标记告警状态为 resolved resolve_timeout: 5m # 配置邮件发送信息 smtp_smarthost: 'smtp.163.com:465' smtp_from: '邮箱地址' smtp_auth_username: '用户名' smtp_auth_password: '密码' smtp_require_tls: false # 所有报警信息进入后的根路由,用来设置报警的分发策略 route: # 这里的标签列表是接收到报警信息后的重新分组标签,例如,接收到的报警信息里面有许多具有 cluster=A 和 alertname=LatncyHigh 这样的标签的报警信息将会批量被聚合到一个分组里面 group_by: ['alertname', 'cluster'] # 当一个新的报警分组被创建后,需要等待至少 group_wait 时间来初始化通知,这种方式可以确保您能有足够的时间为同一分组来获取多个警报,然后一起触发这个报警信息。 group_wait: 30s # 相同的group之间发送告警通知的时间间隔 group_interval: 30s # 如果一个报警信息已经发送成功了,等待 repeat_interval 时间来重新发送他们,不同类型告警发送频率需要具体配置 repeat_interval: 1h # 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器 receiver: default # 上面所有的属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。 routes: - receiver: email group_wait: 10s match: team: node receivers: - name: 'default' email_configs: - to: '邮箱地址' send_resolved: true # 接受告警恢复的通知 - name: 'email' email_configs: - to: '邮箱地址' send_resolved: true
安装alertmanager 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 apiVersion: apps/v1 kind: Deployment metadata: name: alertmanager namespace: monitor labels: app: alertmanager spec: selector: matchLabels: app: alertmanager template: metadata: labels: app: alertmanager spec: nodeName: vm-20-9-centos volumes: - name: alertcfg configMap: name: alert-config containers: - name: alertmanager image: quay.io/prometheus/alertmanager:v0.27.0 imagePullPolicy: IfNotPresent args: - "--config.file=/etc/alertmanager/config.yml" ports: - containerPort: 9093 name: http env: - name: TZ value: Asia/Shanghai volumeMounts: - mountPath: "/etc/alertmanager" name: alertcfg resources: requests: cpu: 100m memory: 256Mi limits: cpu: 100m memory: 256Mi
Prometheus增加告警配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 --- kind: ConfigMap apiVersion: v1 metadata: labels: app: prometheus name: prometheus-config namespace: monitor data: prometheus.yml: | alerting: alertmanagers: - static_configs: - targets: ["alertmanager:9093"] rule_files: - /etc/prometheus/rules.yml global: #指定prometheus的全局配置,比如采集间隔,抓取超时时间等 scrape_interval: 15s #采集目标主机监控数据的时间间隔,默认为1m scrape_timeout: 10s #数据采集超时时间,默认10s evaluation_interval: 1m #触发告警生成alert的时间间隔,默认是1m scrape_configs: .......
配置rule.yml 配置rule.yml以将后续告警分发推送到alertmanager实现告警
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 --- kind: ConfigMap apiVersion: v1 metadata: labels: app: prometheus name: prometheus-config namespace: monitor data: prometheus.yml: | alerting: alertmanagers: - static_configs: - targets: ["alertmanager:9093"] rule_files: - /etc/prometheus/rules.yml ...... rules.yml: | groups: - name: kubernetes-pod rules: - alert: KubernetesPodNotHealthy expr: sum by (namespace, pod) (kube_pod_status_phase{phase=~"Pending|Unknown|Failed"}) > 0 for: 15m labels: severity: critical annotations: summary: Kubernetes Pod not healthy (instance {{ $labels.instance }}) description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} non-running状态已超15分钟.\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - alert: ContainerHighCpuUtilization expr: (sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (pod, container) / sum(container_spec_cpu_quota{con tainer!=""}/container_spec_cpu_period{container!=""}) by (pod, container) * 100) > 80 for: 2m labels: severity: warning annotations: summary: Container High CPU utilization (instance {{ $labels.instance }}) description: "Container CPU 使用率超过 80%\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - alert: ContainerHighMemoryUsage expr: (sum(container_memory_working_set_bytes{name!=""}) BY (instance, name) / sum(container_spec_memory_limit_bytes > 0) BY (instance, name) * 100) > 80 for: 2m labels: severity: warning annotations: summary: Container High Memory usage (instance {{ $labels.instance }}) description: "Container 内存 使用率超过 80%\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - name: kubernetes-node rules: - alert: KubernetesNodeNotReady expr: kube_node_status_condition{condition="Ready",status="true"} == 0 for: 10m labels: severity: critical annotations: summary: Kubernetes Node not ready (instance {{ $labels.instance }}) description: "Node {{ $labels.node }} has been unready for a long time\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - alert: KubernetesNodeMemoryPressure expr: kube_node_status_condition{condition="MemoryPressure",status="true"} == 1 for: 2m labels: severity: critical annotations: summary: Kubernetes Node memory pressure (instance {{ $labels.instance }}) description: "Node {{ $labels.node }} has MemoryPressure condition\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - alert: KubernetesNodeDiskPressure expr: kube_node_status_condition{condition="DiskPressure",status="true"} == 1 for: 2m labels: severity: critical annotations: summary: Kubernetes Node disk pressure (instance {{ $labels.instance }}) description: "Node {{ $labels.node }} has DiskPressure condition\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - alert: KubernetesNodeNetworkUnavailable expr: kube_node_status_condition{condition="NetworkUnavailable",status="true"} == 1 for: 2m labels: severity: critical annotations: summary: Kubernetes Node network unavailable (instance {{ $labels.instance }}) description: "Node {{ $labels.node }} has NetworkUnavailable condition\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" - alert: KubernetesNodeNotReady expr: 'kube_node_status_condition{condition="Ready",status="true"} == 0' for: 10m labels: severity: critical annotations: summary: Kubernetes Node ready (node {{ $labels.node }}) description: "Node {{ $labels.node }} has been unready for a long time\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" .......