Prometheus官网地址:https://prometheus.io/
GitHub地址:https://github.com/prometheus/prometheus
一、prometheus的安装
Prometheus是最初由SoundCloud开发的监控和警报工具,于2016年加入了 Cloud Native Computing Foundation,这是继Kubernetes之后的第CNC的二个托管项目。
1、prometheus的特征
(1)具有由metric名称和键/值对标识的时间序列数据的多维数据模型
(2)有⼀个灵活的查询语⾔
(3)不依赖分布式存储,只和本地磁盘有关
(4)通过HTTP的服务拉取时间序列数据
(5)⽀持推送的⽅式来添加时间序列数据
(6)⽀持通过服务发现或静态配置发现⽬标
(7)多种图形和仪表板⽀持
2、prometheus的组件
Prometheus生态系统包含许多组件,部分组件是可选组件,主要的组件如下:
(1)Prometheus Server:⽤于抓取指标、存储时间序列数据
(2)exporter:暴露指标让任务来抓
(3)pushgateway:push的⽅式将指标数据推送到该⽹关
(4)alertmanager:处理报警的报警组件
(5)adhoc:⽤于数据查询的组件
3、prometheus的安装
Prometheus的二进制安装非常简单,只需要在prometheus的官方网站下载对应版本的二进制包,可通过prometheus的程序制定配置文件即可启动。此处我的prometheus运行在k8s集群中,所以我通过deployment控制器去运行prometheus运行。
(1)创建prometheus配置文件
默认的prometheus的配置为如下:
~]# cat prometheus-2.21.0.linux-386/prometheus.yml | grep -Ev "^#|^[[:space:]]{1,}#|^$"
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.
alerting:
alertmanagers:
- static_configs:
- targets:
rule_files:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
Prometheus的主要几个配置参数说明如下:
1)scrape_interval:表示 prometheus 抓取指标数据的频率,默认是15s
2)evaluation_interval:⽤来控制评估规则的频率,prometheus使⽤规则产⽣新的时间序列数据或者产⽣警报
3)rule_files 模块制定了规则所在的位置,prometheus可以根据这个配置加载规则,⽤于⽣成新的时间 序列数据或者报警信息
4)scrape_configs:⽤于控制prometheus监控哪些资源。由于 prometheus通过HTTP的⽅式来暴露的它本身的监控数据,prometheus也能够监控本身的健康情况。在默认的配置⾥有⼀个单独的job叫 做prometheus,它采集prometheus 服务本身的时间序列数据。这个job包含了⼀个单独的、静态配 置的⽬标:监听localhost上的9090端⼝。prometheus 默认会通过⽬标的/metrics路径采集metrics。
为了方便在k8s中prometheus使用配置文件,我们需要将配置文件通过ConfigMap的形式进行管理
# 定义所有的资源之前先创建一个名称空间
~]# kubectl create namespace prometheus
# 定义prometheus的configmap资源
]# cat prometheus-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: prometheus
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 创建资源
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config created
(2)为prometheus中的数据库创建存储资源
为了防止prometheus所在的pod故障导致数据丢失,我们需要为prometheus的TSDB创建一个pvc。这里使用之前创建的基于nfs的存储类实现动态的pv供给。
# 定义pvc资源
]# cat prometheus-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: prometheus
namespace: prometheus
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
# 创建资源
]# kubectl apply -f prometheus-pvc.yaml
persistentvolumeclaim/prometheus created
(3)通过rbac为prometheus授权
由于prometheus需要访问Kubernetes集群中的相关信息,所以我们需要为prometheusc创建一个ServiceAccount,并授予相关的权限。
# 定义sa资源
]# cat prometheus-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
namespace: 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
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: prometheus
namespace: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: prometheus
namespace: Prometheus
# 创建sa资源
]# kubectl apply -f prometheus-sa.yaml
serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
(4)为prometheus创建deployment控制器
相关的配置文件及依赖的存储资源定义好之后就可以为prometheus创建deployment控制器。
# 定义deployment控制器资源
]# cat prometheus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: prometheus
labels:
app: prometheus
spec:
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
containers:
- image: prom/prometheus:v2.21.0
name: prometheus
command:
- "/bin/prometheus"
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention=24h"
#控制对adminHTTPAPI的访问,其中包括删除时间序列等功能
- "--web.enable-admin-api"
#⽀持热更新,直接执⾏localhost:9090/-/reload⽴即⽣效
- "--web.enable-lifecycle"
ports:
- containerPort: 9090
protocol: TCP
name: http
volumeMounts:
- mountPath: "/prometheus"
subPath: prometheus
name: data
- mountPath: "/etc/prometheus"
name: config-volume
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 200m
memory: 512Mi
# 由于prometheusdocker中是以nobody身份运行,所以要定义该项
securityContext:
runAsUser: 0
volumes:
- name: data
persistentVolumeClaim:
claimName: prometheus
- configMap:
name: prometheus-config
name: config-volume
# 创建并查看运行状态
]# kubectl apply -f prometheus-deployment.yaml
deployment.apps/prometheus created
]# kubectl get pods -n prometheus
NAME READY STATUS RESTARTS AGE
prometheus-97bf69799-64n7w 1/1 Running 0 9s
(5)定义service资源通过集群外部访问
Prometheus的pod控制器创建成功后,为了便于在k8s集群外部访问prometheus,我们需要为k8s集群创建nodeport类型的service资源。
# 定义service资源
]# cat prometheus-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: prometheus
labels:
app: prometheus
spec:
selector:
app: prometheus
type: NodePort
ports:
- name: web
port: 9090
targetPort: 9090
# 创建并查看service资源
]# kubectl apply -f prometheus-svc.yaml
service/prometheus created
]# kubectl get svc -n prometheus
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus NodePort 10.111.61.27 <none> 9090:31736/TCP 16s
至此,prometheus监控已经在k8s集群中安装完毕,可以通过node节点ip加映射至node节点的端口号去访问设置prometheus监控。
二、prometheus的使用
Prometheus的监控数据指标是通过⼀个公开的(HTTP(S))数据接⼝获取到的,不需要单独安装监控的agent,只需要暴露⼀个metrics接⼝,Prometheus就会定期去拉取数据; 对于⼀些普通的HTTP服务,我们完全可以直接给这个服务添加⼀个/metrics接⼝暴露给 Prometheus;⽽且获取到的指标数据格式是⾮常易懂的,不需要太⾼的学习成本。现在很多服务从⼀开始就内置了⼀个/metrics 接⼝,⽐如Kubernetes的各个组件;有⼀些服务即使没有原⽣集成该接⼝,也完全可以使⽤⼀些exporter来获取到指标数据⽐如mysqld_exporter、node_exporter,类似于传统监控服务中的agent。
1、kubernetes集群节点的监控
(1)集群节点需要监控的内容
1)kubernetes集群node几点的监控,包括cpu,内存,负载、磁盘等
2)内部系统组件的状态:⽐如kube-scheduler、kube-controller-manager、kubedns/coredns等组件的详细运⾏状态
3)编排级的资源:⽐如Deployment的状态、资源请求、调度和API 延迟等数据指标
(2)kubernetes集群的监控方案
1)Heapster:Heapster是⼀个集群范围的监控和数据聚合⼯具,以 Pod 的形式运⾏在集群中,目前Heapster已经被metrics-server所代替。
2)cAdvisor:cAdvisor是 Google 开源的容器资源监控和性能分析⼯具,它是专⻔为容器⽽⽣,本身也⽀持 Docker 容器,在 Kubernetes 中,我们不需要单独去安装,cAdvisor 作为 kubelet 内置的⼀部分程序可以直接使⽤。
3)Kube-state-metrics:kube-state-metrics通过监听API Server⽣成有关资源对象的状态指标,⽐如Deployment、Node、Pod,需要注意的是kube-state-metrics只是简单提供⼀个metrics数据,并不会存储这些指标数据,所以我们可以使⽤Prometheus 来抓取这些数据然后存储。
4)metrics-server:metrics-server也是⼀个集群范围内的资源数据聚合⼯具,是Heapster的替代品,同样metrics-server也只是显示数据,并不提供数据存储服务。
在上述监控方案中,kube-state-metrics主要关注的是业务相关的⼀些元数据,⽐如Deployment、Pod、副本状态等,而metrics-server主要关注的是资源度量API的实现,⽐如CPU、⽂件描述符、内存、请求延时等指标
(3)使用Prometheus监控集群节点
使用Prometheus监控node节点,可以通过node_exporter服务来获取监控数据, node_exporter就是抓取⽤于采集服务器节点的各种运⾏指标,⽬前 node_exporter⽀持⼏乎所有常⻅的监控点。
node_exporter服务监控各节点可通过DaemonSet 控制器来部署,这样可以保证每个节点都可以运行一个该服务,即使节点扩容,也可保证在新节点上运行该服务。
# node_exporter服务的DaemonSet控制器资源清单
]# cat prome-node-exporter.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: prometheus
labels:
name: node-exporter
spec:
selector:
matchLabels:
name: node-exporter
template:
metadata:
labels:
name: node-exporter
spec:
# 使用宿主机pid、ipc、network命名空间
hostPID: true
hostIPC: true
hostNetwork: true
containers:
- name: node-exporter
image: prom/node-exporter:v1.0.1
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 apply -f prome-node-exporter.yaml
]# kubectl get pods -n prometheus
NAME READY STATUS RESTARTS AGE
node-exporter-dxbfn 1/1 Running 0 4m54s
node-exporter-fncvm 1/1 Running 0 4m54s
node-exporter-s6jbf 1/1 Running 0 4m51s
通过DaemonSet控制器管理的node-exporter服务是共享了宿主机的网络名称空间,所以该pod运行起来后,各node节点会监听9100端口,所以我们可通过9100端口去获取监控数据。
# 查看各节点node-export监听端口
]# netstat -lntp | grep node_exporter
tcp6 0 0 :::9100 :::* LISTEN 41458/node_exporter
# 查看监控数据
]# curl localhost:9100/metrics | more
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 0
go_gc_duration_seconds{quantile="0.25"} 0
go_gc_duration_seconds{quantile="0.5"} 0
go_gc_duration_seconds{quantile="0.75"} 0
go_gc_duration_seconds{quantile="1"} 0
go_gc_duration_seconds_sum 0
go_gc_duration_seconds_count 0
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 6
(4)配置服务发现
各节点的node-exporter服务运行起来后,我们需要配置prometheus去发现这些服务,并获取数据;配置prometheus发现服务是通过修改ConfigMap配置实现的,我们需要将监控的服务加入配置,并重新创建该配置文件使之生效。
# node服务发现配置如下
]# cat prometheus-cm.yaml
……
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
# 使配置生效
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
上面的操作完成后,登录prometheus发现prometheus已经发现了三个节点,但是获取不到数据,这是因为prometheus去发现Node服务的时候,访问的端⼝默认是10250,但是此处我们指定了hostNetwork=true,所以在每个节点上就会绑定⼀个端⼝9100获取数据,我们需要将10250替换成9100。
此处可使用Prometheus的relabel_configs中的replace进行替换。relabel可以在Prometheus采集数据之前,通过Target实例的 Metadata信息,动态重新写⼊Label的值。
# 匹配__address__Label标签,替换端⼝
]# cat prometheus-cm.yaml
……
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
# 重新加载使配置生效
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
上面操作完成之后,再去查看prometheus就可以正常获取数据。
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
# 将 Kubernetes的Label标签添加为Prometheus的指标标签:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+*)
# 使配置生效并重新加载
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
我们监控的node的节点在prometheus中只显示一个标签,这对于后续的查询等操作不提便利,如果需要显示个node节点的所有标签,可通过labelmap 这个属性将Kubernetes节点的Label标签添加为 Prometheus的指标标签:
- job_name: 'kubernetes-nodes'
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: '(.*):10250'
replacement: '${1}:9100'
target_label: __address__
action: replace
# 将 Kubernetes的Label标签添加为Prometheus的指标标签:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+*)
# 使配置生效并重新加载
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config configured
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
__meta_kubernetes_node_label 只是 kubernetes_sd_configs其中一个标签,更多的标签可参考官方文档(https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Ckubernetes_sd_config%3E)
(5)常用服务的监控
很多服务内置了⼀个/metrics接⼝,针对这类服务的监控我们可以通过接口获取相关的监控指标数据。有些服务没有该接口,我们需要利⽤exporter服务来为Prometheus提供指标数据。Prometheus官⽅为许多应⽤就提供了exporter应⽤,也有许多第三⽅的实现具体可参考prometheus官方文档(https://prometheus.io/docs/instrumenting/exporters/)。
# nginx的基于exporter监控的deployment的资源配置文件
]# cat redis-exporter.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: redis-exporter
template:
metadata:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9121"
labels:
app: redis-exporter
spec:
containers:
- name: redis
image: redis:4
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 6379
- name: redis-exporter
image: oliver006/redis_exporter:latest
resources:
requests:
cpu: 100m
memory: 100Mi
ports:
- containerPort: 9121
---
kind: Service
apiVersion: v1
metadata:
name: redis
spec:
selector:
app: redis-exporter
ports:
- name: redis
port: 6379
targetPort: 6379
- name: prom
port: 9121
targetPort: 9121
上面的资源创建完成后就可以通过9121端口去采集/metric数据。然后在prometheus配置文件中追加redis的配置并重新加载下配置就可在prometheus中获取redis的监控指标。
# Prometheus的configmap中追加redis配置
]# cat prometheus-cm.yaml
. . . . . .
- job_name: "redis"
static_configs:
- targets: ['redis.default.svc:9121']
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config unchanged
# 使配置生效
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
2、监控kubernetes常用资源对象
(1)容器的监控
对于容器的监控,则使用cAdvisor,而cAdvisor则已经内置在了 kubelet 组件之
中,所以不需要单独去安装, cAdvisor 的数据路径为 /api/v1/nodes/<node>/proxy/metrics。
对于容器的监控我们同样使用node 的服务发现模式,因为每⼀个节点下⾯都有 kubelet,⾃然都有cAdvisor采集到的数据指标。而使用cAdvisor监控kubernetes集群资源时需要使用https 的协议,https协议需要用到ca.cart 和 token 这两个⽂件,这两个文件在所有的pod启动时,kubernetes已经注入到了该pod中。
监控容器的configmap配置文件如下:
]# cat prometheus-cm.yaml
. . . . . .
- job_name: 'kubernetes-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_(.+)
- 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
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config unchanged
# 使配置生效
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
(2)监控kubelet
由于cAdvisor集成在了kubelet组件内,所以kubelet的监控也可通过cAdvisor来实现,kubelet的数据路径为:/api/v1/nodes/[节点名称]/proxy/metrics。监控configmap的configmap配置文件通监控容器的配置基本是一致的。
# 监控kubelet的configmap配置文件
]# cat prometheus-cm.yaml
. . . . . .
- job_name: 'kubernetes-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_(.+)
- 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
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config unchanged
# 使配置生效
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
(3)监控apiserver
apiserver作为Kubernetes最核⼼的组件,是非常有必要对其进行监控的,对于apiserver的监控可以直接通过kubernetes 的Service来获取
# 查看默认的svc
]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 132d
mysqlendpoints ClusterIP 10.102.60.55 <none> 3306/TCP 124d
要⾃动发现Service类型的服务,我们就需要⽤到role为Endpoints的kubernetes_sd_configs,我们可以在 ConfigMap对象中添加上⼀个Endpoints 类型的服务的监控任务。然后将我们自己需要的服务过滤出来。
Apiserver的svc默认为namespace为default的,服务名为 kubernetes的元数据。所以可以通过可以根据对应的__meta_kubernetes_namespace和__meta_kubernetes_service_name这两个元数据来过滤保留相关的svc。而此处则通过keep而非replace这个动作把符合我们要求的给保留下。
# 监控apiservice的configmap配置
]# cat prometheus-cm.yaml
- job_name: 'apiservers'
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
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config unchanged
# 使配置生效
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
(4)service的监控
K8s中的apiserver是⼀种特殊的svc,如果需要监控其他的svc,需要在role为Endpoints的kubernetes_sd_configs中根据需求帅选出符合条件的svc进行监控。
# 监控符合条件的svc
- job_name: kubernetes-service-endpoints
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- action: keep
regex: true
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_scrape
- action: replace
regex: (https?)
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_scheme
target_label: __scheme__
- action: replace
regex: (.+)
source_labels:
- __meta_kubernetes_service_annotation_prometheus_io_path
target_label: __metrics_path__
- action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
source_labels:
- __address__
- __meta_kubernetes_service_annotation_prometheus_io_port
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: kubernetes_namespace
- action: replace
source_labels:
- __meta_kubernetes_service_name
target_label: kubernetes_name
在上面的配置中第一项“__meta_kubernetes_service_annotation_prometheus_io_scrap”的帅选条件为Service的annotation区域需要有prometheus.io/scrape=true 的声明。
(5)kube-state-metrics
kube-state-metrics主要是用来监控Kubernetes 集群上的Pod、DaemonSet、Deployment、Job、CronJob 等各种资源对象的状态。kube-state-metrics 的gitlab地址为:https://github.com/kubernetes/kube-state-metrics
对于kube-state-metrics的安装我们只需将gitlab上该项目拉取下来,再通过kubec aply创建即可。
git clone https://github.com/kubernetes/kube-state-metrics.git
]# cd kube-state-metrics-master/examples/standard/
# 在server的metadata下添加annotations
annotations:
prometheus.io/scraped: "true"
# 创建kube-state-metrics
]# kubectl apply -f ./service.yaml
kube-state-metrics创建完成后需要在prometheus的配置文件中追加配置,抓取带有prometheus.io/scraped: "true"
注解的endpoint。
]# cat prometheus-cm.yaml
. . . . . .
- job_name: "kube-state-metrics"
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scraped]
action: keep
regex: true
- 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: service_name
# 重新加载配置
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config unchanged
# 使配置生效
]# curl -XPOST http://192.168.16.132:31736/-/reload
上面操作完成后就可以在promeheus的”targets”中看到kube-state-metrics相关数据呢,kube-state-metrics对应的svc有两个端口,在prometheus中显示了两个target。
三、grafana的使用
grafana 是⼀个可视化⾯板,有着⾮常漂亮的图表和布局展示,功能⻬全的度量仪表盘和图形编辑器,⽀持 Graphite、zabbix、InfluxDB、Prometheus、OpenTSDB、Elasticsearch 等作为数据源,⽐Prometheus⾃带的图表展示功能更强大更炫;并且有丰富的插件。
1、grafana的安装
Grafana的各种安装方法见官方文档(https://grafana.com/docs/grafana/latest/)。grafana在docker中运行直接执行命令” docker run -d --name=grafana -p 3000:3000 grafana/grafana”即可。此处的安装我们同prometheus一样,将grafana通过deployment控制器运行k8s中,再通过svc访问。需要注意的是>=5.1的版本运行的userID是472。
# 创建一个基于nfs storage class的pvc
]# cat grafana-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: grafana
namespace: prometheus
annotations:
volume.beta.kubernetes.io/storage-class: "managed-nfs-storage"
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
]# kubectl apply -f grafana-pvc.yaml
# 创建基于deployment控制器的pod
]# cat grafana-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
namespace: prometheus
labels:
app: grafana
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana:7.3.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
name: Grafana
# 通过环境变量的方式传递用户名密码
env:
- name: GF_SECURITY_ADMIN_USER
value: admin
- name: GF_SECURITY_ADMIN_PASSWORD
value: dayi123
readinessProbe:
failureThreshold: 10
httpGet:
path: /api/health
port: 3000
scheme: HTTP
initialDelaySeconds: 60
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 30
livenessProbe:
failureThreshold: 3
httpGet:
path: /api/health
port: 3000
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 200m
memory: 256Mi
volumeMounts:
- mountPath: /var/lib/grafana
subPath: grafana
name: storage
# 定义grafana的用户
securityContext:
fsGroup: 472
runAsUser: 472
volumes:
- name: storage
persistentVolumeClaim:
claimName: grafana
# 创建
]# kubectl apply -f grafana-deployment.yaml
# 创建NodePort类型的svc将grafana暴露出去便于访问
]# cat grafana-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: prometheus
labels:
app: grafana
spec:
type: NodePort
ports:
- port: 3000
selector:
app: Grafana
# 查看创建的svc资源
]# kubectl get svc -n prometheus
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
grafana NodePort 10.108.43.11 <none> 3000:30380/TCP 5m6s
prometheus NodePort 10.111.61.27 <none> 9090:31736/TCP 55d
上面所有的资源创建完成后我们就可以通过网页去访问grafana。用户名密码为在grafana的deployment中定义用户名密码。
2、使用grafana
Grafana安装完成后就可以使用grafana,首先我们需要配置数据源,登录grafana后,点击“DATA SOURCE”进行数据源的设置。进入后选择“Prometheus”根据自己实际情况进行prometheus的一些相关设置。设置完成后保存即可。数据源设置如下:
数据源设置完成后就可以添加dashboard,dashboard也可以导入通过导入的方式增加,操作如下:
导入以id号为162的dashboard为例,可以将编号ID为162的dashboard下载到本地,然后这⾥重新上传即可,也可以在⽂本框中直接输⼊162编号回⻋导⼊这个 dashboard。
在导入时一定要选择数据源。
Dashboard导入后,dashboard中可能会没有数据,一方面可能是由于prometheus和grafana时间不一致导致的,需要修改时间,另一方面是由于该图表的查询语句无法查询到数据,需要修改查询语句。修改方法为:点击该图像标题,点击下拉框中的“Edit”进行编辑,对查询语句根据实际情况进行调整。
Dashboard id号为162的第一个图像的原查询语法为:
(sum(node_memory_MemTotal) - sum(node_memory_MemFree +node_memory_Buffers +node_memory_Cached) ) / sum(node_memory_MemTotal) * 100
由于prometheus中没有“node_memory_MemTotal”等相关的指标数据,所以根据自己的prometheus中指标将“node_memory_MemTotal”等修改为““node_memory_MemTotal”_bytes”即可查询到数据。
(sum(node_memory_MemTotal_bytes) - sum(node_memory_MemFree_bytes+node_memory_Buffers_bytes+node_memory_Cached_bytes) ) / sum(node_memory_MemTotal_bytes) * 100
第二个图标中的原查询语句为:
sum(sum by (io_kubernetes_container_name)( rate(container_cpu_usage_seconds_total{image!=""}[1m] ) )) / count(node_cpu{mode="system"}) * 100
由于prometheus中存储出的数据中实际标签为“container”,并不存在标签“io_kubernetes_container_name”,所以需要修改为“container”,另一方面node_cpu这样的指标,实际为“node_cpu_seconds_total”,所以修改后的查询语法为:
sum(sum by (container)( rate(container_cpu_usage_seconds_total{image!=""}[1m] ) )) / count(node_cpu_seconds_total{mode="system"}) * 100
第三个图标和第一个图标差不多一样,也是不存在“node_filesystem_size”等这样的数据指标,需要进行修改。
# 原语句为
(sum(node_filesystem_size{device="rootfs"}) - sum(node_filesystem_free{device="rootfs"}) ) / sum(node_filesystem_size{device="rootfs"}) * 100
# 修改后语句为
(sum(node_filesystem_size_bytes{device="rootfs"}) - sum(node_filesystem_free_bytes{device="rootfs"}) ) / sum(node_filesystem_size_bytes{device="rootfs"}) * 100
第四个图表为pod的cpu使用率的图表,然而在prometheus中不存在名称为”io_kubernetes_container_name”该标签,需要将该标签替换为“pod”即可。其他的图表则依据prometheus中数据的实际情况进行调整。图表的查询语句修改完成后部分dashboard的如下:
除了上面的id号为162的dashboard模板为,还有常用的模板还有741(Deployment metrics)、747(Kubernetes Pod Metric)。
3、grafana中安装k8s插件
除了上面通过一些dashboard模板监控k8s集群为,prometheus还提供呢一个插件grafana-kubernetes-app对kubernetes集群进行监控,该插件的官方文档地址为:(https://grafana.com/grafana/plugins/grafana-kubernetes-app/installation)。
(1)安装插件
该插件的安装需要进入到grafana对应的pod中安装,安装完成后需要重启grafana所对应的pod。
# 查看pod
]# kubectl get pods -n prometheus
NAME READY STATUS RESTARTS AGE
grafana-5d6f5f45bc-wsps7 1/1 Running 1 7h47m
# 进入pod
]# kubectl exec -it grafana-5d6f5f45bc-wsps7 /bin/sh -n prometheus
# 安装插件
/usr/share/grafana $ grafana-cli plugins install grafana-kubernetes-app
installing grafana-kubernetes-app @ 1.0.1
from: https://grafana.com/api/plugins/grafana-kubernetes-app/versions/1.0.1/download
into: /var/lib/grafana/plugins
✔ Installed grafana-kubernetes-app successfully
Restart grafana after installing plugins . <service grafana-server restart>
# 退出删除pod(删除后会重新创建,达到了重启的效果)
/usr/share/grafana $ exit
[root@master prometheus]# kubectl delete pods grafana-5d6f5f45bc-wsps7 -n prometheus
pod "grafana-5d6f5f45bc-wsps7" deleted
[root@master prometheus]# kubectl get pods -n prometheus
NAME READY STATUS RESTARTS AGE
grafana-5d6f5f45bc-876jx 0/1 Running 0 66s
重启完grafana后,进入到插件页面发现会多了一个kubernetes插件,如下图所示:
(2)配置插件
安装完该插件,我们点击该插件进入插件,在“configuer”中点击“Connect to your Kubernetes Cluster and deploy metric exporters”进行该插件的配置。
配置kubernetes集群需要填写集群的名称。Kubernetes集群的地址(即apiservice地址)及认证方式 ,认证方式可选择tls证书认证(选择“TLS Client Auth”和“With CA Cert”)。证书文件可将” ~/.kube/config”文件中的内容通过base64解码后使用。
相关的认证信息填写完成后,如果之前没有创建“Node Exporter”和“kube State Metrics”则点击“deploy”进行创建,如果已经创建则点击“save”即可。点击“save”后会在左边的菜单栏出现“kubernetes”的图表。在dashboard中就可以看到相关的dashboard,在新版本的grafana中需要根据prometheus的实际数据对dashboard图标查询语句进行一些调整。
4、grafana监控告警
(1)、配置告警方式
设置grafana的邮件告警,需要在grafana的配置文件“/etc/grafana/grafan.ini”中设置smtp邮件服务器的地址。此处我们将grafana的配置文件通过configmap资源对象挂载到grafana的pod中。
# 创建grafana邮箱告警的configmap
]# cat grafana-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: grafana-config
namespace: prometheus
data:
grafana.ini: |
[server]
root_url = http://192.168.16.132:30380/
[smtp]
enable = true
host = smtp.163.com:25
user = dayi_123@163.com
password = dayi123
skip_verify = true
from_address = dayi_123@163.com
[alerting]
enabled = true
execute_alerts = true
# 创建
]# kubectl apply -f grafana-cm.yaml
# 将configmap挂载到grafana的pod中
# 修改grafana-deployment.yaml的配置文件,将configmap挂载到pod中
]# cat grafana-deployment.yaml
. . . . . .
volumeMounts:
- mountPath: /var/lib/grafana
subPath: grafana
name: storage
- mountPath: "/etc/grafana"
name: config
volumes:
- name: storage
persistentVolumeClaim:
claimName: grafana
- name: config
configMap:
name: grafana-config
# 更新pod
]# kubectl apply -f grafana-deployment.yaml
邮箱smtp设置后就可以设置告警发送到的邮箱等相关的信息。除了可以设置以邮件的方式告警外,还可以设置、钉钉、slack、 webhook等方式告警。设置钉钉告警需要在钉钉群里面添加机器人,类型为自定义机器人,添加完后将webhook 地址添设置钉钉告警的“Webhook URL”下即可。
(2)、设置告警
告警方式设置完成后,需要进行告警相关的设置,告警的设置我们需要先选择Graph相关图表,点击编辑,进⼊Graph编辑⻚⾯可以看到有⼀个Alert模块,点击该模块后点击“create Alert”即可进行告警的相关设置,具体设置根据自己的实际情况进行设置。
四、prometheus的告警功能
由于Grafana只⽀持Graph的图表的报警的报警功能,Grafana的报警功能⽐较弱,所以一般都是用prometheus的报警模块AlertManager进行报警。Alertmanager主要⽤于接收Prometheus发送的告警信息,它⽀持丰富的告警通知渠道,⽽且很容易做到告警信息进⾏去重,降噪,分组等。
1、AlertManager的安装
AlertManager的官⽅⽂档地址为https://prometheus.io/docs/alerting/configuration/;默认的安装方式为下载二进制文件,通过命令“./alertmanager --config.file=simple.yml”即可运行AlertManager。
由于prometheus运行在deployment控制器的pod中,所以将AlertManager的镜像也添加到prometheus所在的pod中。同时将AlerManager的配置文件以configmap的方式挂载到pod中。
# AlertManager的configmap文件
]# cat alertamager-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: alertmanager-cm
namespace: prometheus
data:
config.yml: |
global:
# 在没有报警的情况下声明为已解决的时间
resolve_timeout: 5m
# 报警发送的邮箱地址
smtp_smarthost: 'smtp.126.com'
smtp_from: 'dayi_123@126.com'
smtp_auth_username: 'dayi_123@126.com'
smtp_auth_password: 'xxxxxx'
smtp_hello: '126.com'
smtp_require_tls: false
# 所有报警信息进⼊后的根路由,⽤来设置报警的分发策略
route:
# 是接收到报警信息后的重新分组标签,
group_by: ['alertname', 'cluster']
# 报警分组被创建后,初始化通知时间
group_wait: 30s
# 当第⼀个报警发送后,发送新的报警信息的间隔时间。
group_interval: 5s
# 如果⼀个报警信息已经发送成功了,重新发送时间
repeat_interval: 5m
# 默认的receiver:如果⼀个报警没有被⼀个route匹配,则发送给默认的接收器
receiver: default
- receiver: emil
group_wait: 10s
match_re:
team: node
# 接收邮件的邮箱,可以设置多个
receivers:
- name: 'default'
email_configs:
- to: 'liuyi@ecmoho.com'
send_resolved: 'true'
- name: email
email_configs:
- to: 'liuyi@ecmoho.com'
send_resolved: 'true'
# 创建
]# kubectl apply -f alertamager-cm.yaml
configmap/alertmanager-cm created
AlertManager的configmap文件创建后,需要修改之前创建的prometheus的deployment的资源配置文件,在pod中新增AlertManager的镜像。即在prometheus的deployment中增加以下配置文件:
#在prometheus-deployment资源清单中配置文件中增加alertmanager镜像
]# cat prometheus-deployment.yaml
. . . . . .
- name: alertmanager
image: prom/alertmanager:v0.21.0
imagePullPolicy: IfNotPresent
args:
- "--config.file=/etc/alertmanager/config.yml"
ports:
- containerPort: 9093
name: http
volumeMounts:
- mountPath: "/etc/alertmanager"
name: alertcfg
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 100m
memory: 256Mi
- name: alertcfg
configMap:
name: alertmanager-cm
# 删除重新创建
]# kubectl delete -f prometheus-deployment.yaml
]# kubectl apply-f prometheus-deployment.yaml
# 同时也可在prometheus的svc中添加alertmanager配置
]# cat prometheus-svc.yaml
. . . . .
- name: alert
port: 9093
targetPort: 9093
# 重新加载
]# kubectl apply -f prometheus-svc.yaml
2、配置告警
AlertManager的容器启动起来后,我们还需要在Prometheus中配置AlertManager的地址,让Prometheus 能够访问到AlertManager。同时还需通过prometheus配置文件添加告警规则配置。
# 在prometheus中配置文件中配置alertmanager地址
]# cat prometheus-cm.yaml
. . . . . .
alerting:
alertmanagers:
- static_configs:
- targets: ["localhost:9093"]
rule_files:
- /etc/prometheus/rules.yml
# 配置完成后重新创建并加载
]# kubectl delete -f prometheus-cm.yaml
configmap "prometheus-config" deleted
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config created
]# curl -XPOST "http://192.168.16.132:3173
Prometheus配置中告警规则是通过引入rule_files实现的,这⾥我们同样将rules.yml ⽂件⽤ConfigMap的形式挂载到/etc/prometheus⽬录下⾯即可。
# 配置告警规则
]# cat prometheus-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: prometheus
data:
prometheus.yml: |
. . . . . .
rules.yml: |
groups:
- name: test-rule
rules:
- alert: NodeMemoryUsage
expr: (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) / node_memory_MemTotal_bytes * 100 > 80
for: 2m
labels:
team: node
annotations:
summary: "{{$labels.instance}}: High Memory usage detected"
description: "{{$labels.instance}}: Memory usage is above 20% (current value is:{{ $value }}"
# 重新创建配置并加载
]# kubectl delete -f prometheus-cm.yaml
configmap "prometheus-config" deleted
]# kubectl apply -f prometheus-cm.yaml
configmap/prometheus-config created
]# curl -XPOST "http://192.168.16.132:31736/-/reload"
告警规则中各参数作用如下:
for:使 Prometheus 服务等待指定的时间, 然后执⾏查询表达式。
labels:允许指定额外的标签列表,把它们附加在告警上。
Annotations:指定了另⼀组标签,它们不被当做告警实例的身份标识,它们经常⽤于存储些额外的信息,⽤于报警信息的展示之类的。
除了上面的告警规则外,其余告警规则我们可根据自己需求自定义。如果相关的告警规则被触发我们可以在prometheus的alerts模块中(安装alertmanager后会出现)或alertmanager页面中查看。
3、配置钉钉告警
要使用钉钉告警,首先需要我们定义webhook来接收报警信息,然后在webhook⾥⾯去进⾏告警信息的处理。在github上有人已经做了该项目(https://github.com/timonwong/prometheus-webhook-dingtalk),同时该项目也被人做成docker镜像(https://hub.docker.com/r/timonwong/prometheus-webhook-dingtalk);我们只需根据自己需求配置使用即可。
在k8s集群中我们也将该webhook运行在deployment控制的pod中。资源清单定义如下:
]# cat ddtalk-hook.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ddtalk-hook
namespace: prometheus
spec:
selector:
matchLabels:
app: ddtalk-hook
template:
metadata:
labels:
app: ddtalk-hook
spec:
containers:
- name: ddtalk-hook
image: timonwong/prometheus-webhook-dingtalk:v1.4.0
args:
- --ding.profile=webhook1=https://oapi.dingtalk.com/robot/send?access_token=53630694d60843f17b99e40949afba58fb247995554120bf054037f6111ea59f
ports:
- containerPort: 8060
name: http
resources:
requests:
cpu: 50m
memory: 100Mi
limits:
cpu: 50m
memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:
name: ddtalk-hook
namespace: prometheus
spec:
selector:
app: ddtalk-hook
ports:
- name: hook
port: 8060
targetPort: http
]# kubectl apply -f ddtalk-hook.yaml
上面资源定义完成后我们需要在alermanager的配置文件中添加一个routes,用于将告警信息发送到接收钉钉告警的服务中。
]# cat alertamager-cm.yaml
. . . . . .
routes:
. . . . . .
- receiver: webhook
group_wait: 10s
receivers:
- name: 'email'
email_configs:
- to: 'liuyi@ecmoho.com'
send_resolved: true
. . . . . .
五 、Prometheus Operator 的安装与使用
Operator是由CoreOS公司开发的,⽤来扩展 Kubernetes API,是特定的应⽤程序控制器,它⽤来创建、配置和管理复杂的有状态应⽤,如数据库、缓存和监控系统。Operator基于Kubernetes的资源和控制器概念之上构建,但同时⼜包含了应⽤程序特定的⼀些专业知识,⽐如创建⼀个数据库的Operator,则必须对创建的数据库的各种运维⽅式⾮常了解,创建Operator 的关键是CRD(⾃定义资源)的设计。CRD 是对 Kubernetes API 的扩展,Kubernetes中的每个资源都是⼀个API对象的集合。
Operator 是将运维⼈员对软件操作的知识给代码化,同时利⽤ Kubernetes 强⼤的抽象来管理⼤规模的软件应⽤。
1、Prometheus-Operator
官方文档地址:https://coreos.com/operators/prometheus/docs/latest/user-guides/getting-started.html
Github地址:https://github.com/prometheus-operator/prometheus-operator
Prometheus-operator程序地址:https://github.com/prometheus-operator/kube-prometheus
Prometheus-Operator中Operator是最核⼼的部分,作为⼀个控制器,他会去创建Prometheus、ServiceMonitor、AlertManager以及PrometheusRule 4个 CRD 资源对象,然后会⼀直监控并维持这4个资源对象的状态。prometheus这种资源对象就是作为 Prometheus Server存在,⽽ServiceMonitor就是exporter的各种抽象;exporter是⽤来专⻔提供metrics数据接⼝的⼯具,Prometheus就是通过ServiceMonitor提供的metrics数据接⼝去pull数据的,alertmanager这种资源对象就是对应的AlertManager的抽象,⽽ PrometheusRule是⽤来被Prometheus实例使⽤的报警规则⽂件。这样我们要在集群中监控什么数据,就变成了直接去操作Kubernetes集群的资源对象了。
2、Prometheus-Operator的安装
Prometheus-Operator的安装可以使用源码进⾏安装,也可以⽤Helm来进⾏⼀键安装。使用helm安装只需通过“helm install --name my-release stable/prometheus-operator”命令即可完成安装。使用源码安装的方法如下:
# 下载源码
]# git clone https://github.com/prometheus-operator/kube-prometheus
# 创建相关的名称空间及operator等相关资源
]# cd kube-prometheus/manifests/
]# kubectl apply -f setup/
# 创建prometheus等相关资源
]# kubectl apply -f ./
alertmanager.monitoring.coreos.com/main created
secret/alertmanager-main created
service/alertmanager-main created
serviceaccount/alertmanager-main created
. . . . . .
由于使用prometheus-operator定义的资源数据都是存储在临时挂载目录中,服务重启后数据会丢失,为了保持数据持久化,我们需要创建一个StorageClass (使用之前创建的基于nfs的storageclass)。然后在prometheus的CRD资源对象中添加如下配置:
storage:
volumeClaimTemplate:
spec:
storageClassName: managed-nfs-storage
resources:
requests:
storage: 5Gi
修改后的promehteus的crd资源定义如下:
# 查看之前创建的storageclass
]# kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
managed-nfs-storage fuseim.pri/ifs Delete Immediate false 10
# 修改后的promehteus crd资源
]# cat prometheus-prometheus.yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
labels:
prometheus: k8s
name: k8s
namespace: monitoring
spec:
alerting:
alertmanagers:
- name: alertmanager-main
namespace: monitoring
port: web
storage:
volumeClaimTemplate:
spec:
storageClassName: managed-nfs-storage
resources:
requests:
storage: 5Gi
image: quay.io/prometheus/prometheus:v2.22.1
nodeSelector:
kubernetes.io/os: linux
podMonitorNamespaceSelector: {}
podMonitorSelector: {}
probeNamespaceSelector: {}
probeSelector: {}
replicas: 1
resources:
requests:
memory: 400Mi
ruleSelector:
matchLabels:
prometheus: k8s
role: alert-rules
securityContext:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 1000
serviceAccountName: prometheus-k8s
serviceMonitorNamespaceSelector: {}
serviceMonitorSelector: {}
version: v2.22.1
# 更新配置
]# kubectl apply -f prometheus-prometheus.yaml
上面的资源创建完成后,会生产相关的svc资源,为了能够正常访问promehteus及grafana我们需要将promehteus及grafana(新版默认为NodePort)的svc修改为NodePort类型。
# 生成的svc
]# kubectl get svc -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
alertmanager-main ClusterIP 10.97.233.207 <none> 9093/TCP 39m
alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 30m
grafana NodePort 10.100.21.231 <none> 3000:30611/TCP 39m
kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 39m
node-exporter ClusterIP None <none> 9100/TCP 39m
prometheus-adapter ClusterIP 10.103.4.15 <none> 443/TCP 39m
prometheus-k8s ClusterIP 10.105.172.229 <none> 9090/TCP 39m
prometheus-operated ClusterIP None <none> 9090/TCP 30m
prometheus-operator ClusterIP None <none> 8443/TCP 93m
# 修改prometheus的端口类型为NodePort
]# kubectl edit svc prometheus-k8s -n monitoring
上面操作完成后,可登录prometheus查看,k8s集群中大部分资源都已经被监控,而grafana中也已经生成了相关的dashboard。
3、Prometheus-Operator的配置
上面的资源创建后,prometheus已经将k8s集群的大部分资源监控。没有被监控到的资源包括kube-controller-manager和kube-scheduler这两个系统组件。kube-scheduler 组件对应的 ServiceMonitor 资源的定义如下:
]# cat prometheus-serviceMonitorKubeScheduler.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
k8s-app: kube-scheduler
name: kube-scheduler
namespace: monitoring
spec:
endpoints:
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
interval: 30s
port: https-metrics
scheme: https
tlsConfig:
insecureSkipVerify: true
jobLabel: k8s-app
# 匹配某⼀命名空间中的service,如果想从所有的namespace中匹配⽤any: true
namespaceSelector:
matchNames:
- kube-system
# 匹配的Service的labels, 如果使⽤mathLabels,则下⾯的所有标签都匹配时才会匹配该service,如果使⽤matchExpressions,则⾄少匹配⼀个标签的service
selector:
matchLabels:
k8s-app: kube-scheduler
通过监控kube-scheduler的ServiceMonitor资源发现,监控kube-scheduler是通过kube-system名称空间下的标签为k8s-app=kube-scheduler的svc采集监控数据的。而系统中没有该svc,所以监控不到kube-scheduler。需要我们去手动创建一个svc。
]# cat kube-schedule-svc.yaml
apiVersion: v1
kind: Service
metadata:
namespace: kube-system
name: kube-scheduler
labels:
k8s-app: kube-scheduler
annotations:
prometheus.io/scrape: 'true'
spec:
selector:
component: kube-scheduler
ports:
- name: http-metrics
port: 10251
targetPort: 10251
protocol: TCP
# 创建
]# kubectl apply -f kube-schedule-svc.yaml
当kube-scheduler的svc创建后,在k8s的监控中已经发现了kube-scheduler的target,但是抓取数据时出错了,这是因为kubeadm搭建的集群中kube-scheduler 默认是绑定在127.0.0.1上⾯的。kube-scheduler绑定的地址更改成 0.0.0.0即可满⾜要求。
# 修改监听地址
]# sed -i "s@host: 127.0.0.1@host: 0.0.0.0@g" /etc/kubernetes/manifests/kube-scheduler.yaml
修改完成后我们将该⽂件从当前⽂件夹中移除,隔⼀会⼉再移回该⽬录,就可以⾃动更新,然后再去看prometheus中kube-scheduler这个targe已经正常。
kube-controller-manager的监控也可按照此方法配置,kube-controller-manager监听的地址是10252,晒选该资源的label是”k8s-app: kube-controller-manager”。
4、自定义Prometheus-Operator监控项
在prometheus的集群中,处理监控集群的组件外,大多数时候我们需要根据业务需求自定义监控想,在promehteus-operator中自定义监控想需要通过以下步骤来完成:
(1)建立ServiceMonitor对象,用户Prometheus添加监控项
(2)为ServiceMonitor对象关联metrics数据接口的Service对象
(3)确保Service对象可以正确获取到metrics数据
Prometheus-operator中并没有etcd的监控,为etcd自动以监控项的操作如下:
# 首先为用到的etcd证书创建一个secret资源
]# kubectl -n monitoring create secret generic etcd-certs --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key --from-file=/etc/kubernetes/pki/etcd/ca.crt
secret/etcd-certs created
# 查看
]# kubectl get secret etcd-certs -n monitoring
NAME TYPE DATA AGE
etcd-certs Opaque 3 10m
# 然后将用到的证书配置到prometheus中
]# kubectl edit prometheus k8s -n monitoring
. . . . . .
ruleSelector:
matchLabels:
prometheus: k8s
role: alert-rules
secrets:
- etcd-certs
. . . . . .
# 查看prometheus中的证书
]# kubectl exec -it prometheus-k8s-0 ls /etc/prometheus/secrets/etcd-certs/ -n monitoring
ca.crt healthcheck-client.crt healthcheck-client.key
因为很多时候etcd是独立于集群之外的,所以我们在创建svc的同时需要创建一个Endpoints将etcd代理到k8s集群,然后将svc绑定到Endpoints。需要注意的是svc和Endpoints的metadata区域内容要保持一致。
]# cat etcd-svcendpoints.yaml
apiVersion: v1
kind: Service
metadata:
name: etcd-k8s
namespace: kube-system
labels:
k8s-app: etcd
spec:
type: ClusterIP
clusterIP: None
ports:
- name: port
port: 2379
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: etcd-k8s
namespace: kube-system
labels:
k8s-app: etcd
subsets:
- addresses:
- ip: 192.168.16.131
ports:
- port: 2379
# 创建
]# kubectl apply -f etcd-svcendpoints.yaml
Svc资源创建完成后,就需要创建etcd的monitoring资源。由于证书中的serverName 和etcd中签发的可能不匹配,所以加上了在定义etcd的monitor资源时加上了insecureSkipVerify=true。
]# cat etcd-servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: etcd-k8s
namespace: monitoring
labels:
k8s-app: etcd-k8s
spec:
jobLabel: k8s-app
endpoints:
- port: port
interval: 30s
scheme: https
tlsConfig:
caFile: /etc/prometheus/secrets/etcd-certs/ca.crt
certFile: /etc/prometheus/secrets/etcd-certs/healthcheck-client.crt
keyFile: /etc/prometheus/secrets/etcd-certs/healthcheck-client.key
insecureSkipVerify: true
selector:
matchLabels:
k8s-app: etcd
namespaceSelector:
matchNames:
- kube-system
# 创建
]# kubectl apply -f etcd-servicemonitor.yaml
Etcd的监控完成后可以在grafana中导入编号为3070的dashboard,便可获取etcd的监控图表。
5、配置 PrometheusRule
安装完prometheus-operator后自带的监控项已经有了告警规则,我们自定义的监控项就需要我们自定义一些告警规则。手动搭建的prometheus中⾃定义告警需要在 Prometheus的配置⽂件中指定报警的rules⽂件或定义告警规则。Prometheus-operator中自定义告警规则需要创建⼀个具有prometheus=k8s和role=alert-rules标签的
PrometheusRule对象即可。例如添加的etcd的监控项创建告警规则:
]# cat etcd-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
abels:
prometheus: k8s
role: alert-rules
name: etcd-rules
namespace: monitoring
spec:
groups:
- name: etcd
rule:
- alert: EtcdClusterUnavailable
annotations:
summary: etcd cluster small
description: etcd cluster unavailable
expr: |
count(up{job="etcd"} == 0) > (count(up{job="etcd"}) / 2 - 1)
for: 3m
labels:
severity: critical
# 创建
]# kubectl apply -f etcd-rules.yaml
prometheusrule.monitoring.coreos.com/etcd-rules created
pod中的promehteus的告警规则的位置为“/etc/prometheus/rules/prometheus-k8s-rulefiles-0/”。所以该资源创建后实际上会生成一个“<namespace>-<name>.yaml 的⽂件”。
]# kubectl exec -it prometheus-k8s-0 -n monitoring ls /etc/prometheus/rules/prometheus-k8s-rulefiles-0/
monitoring-etcd-rules.yaml monitoring-prometheus-k8s-rules.yaml
6、配置告警
Prometheus-operator中alertmanager的告警配置是通过“kube-prometheus/manifests/alertmanager-secret.yaml”这个配置文件配置的,这个创建后主要配置信息如下:
]# kubectl get secret alertmanager-main -n monitoring -o yaml
apiVersion: v1
data:
alertmanager.yaml: Imdsb2JhbCI6CiAgInJlc29sdmVfdGltZW91dCI6ICI1bSIKImluaGliaXRfcnVsZXMiOgotICJlcXVhbCI6CiAgLSAibmFtZXNwYWNlIgogIC0gImFsZXJ0bmFtZSIKICAic291cmNlX21hdGNoIjoKICAgICJzZXZlcml0eSI6ICJjcml0aWNhbCIKICAidGFyZ2V0X21hdGNoX3JlIjoKICAgICJzZXZlcml0eSI6ICJ3YXJuaW5nfGluZm8iCi0gImVxdWFsIjoKICAtICJuYW1lc3BhY2UiCiAgLSAiYWxlcnRuYW1lIgogICJzb3VyY2VfbWF0Y2giOgogICAgInNldmVyaXR5IjogIndhcm5pbmciCiAgInRhcmdldF9tYXRjaF9yZSI6CiAgICAic2V2ZXJpdHkiOiAiaW5mbyIKInJlY2VpdmVycyI6Ci0gIm5hbWUiOiAiRGVmYXVsdCIKLSAibmFtZSI6ICJXYXRjaGRvZyIKLSAibmFtZSI6ICJDcml0aWNhbCIKInJvdXRlIjoKICAiZ3JvdXBfYnkiOgogIC0gIm5hbWVzcGFjZSIKICAiZ3JvdXBfaW50ZXJ2YWwiOiAiNW0iCiAgImdyb3VwX3dhaXQiOiAiMzBzIgogICJyZWNlaXZlciI6ICJEZWZhdWx0IgogICJyZXBlYXRfaW50ZXJ2YWwiOiAiMTJoIgogICJyb3V0ZXMiOgogIC0gIm1hdGNoIjoKICAgICAgImFsZXJ0bmFtZSI6ICJXYXRjaGRvZyIKICAgICJyZWNlaXZlciI6ICJXYXRjaGRvZyIKICAtICJtYXRjaCI6CiAgICAgICJzZXZlcml0eSI6ICJjcml0aWNhbCIKICAgICJyZWNlaXZlciI6ICJDcml0aWNhbCI=
kind: Secret
metadata:
name: alertmanager-main
namespace: monitoring
该配置文件中的告警信息都是通过base64加密的,解密后即是告警相关的一些配置信息
]# echo "Imdsb2JhbCI6CiAgInJlc29sdmVfdGltZW91dCI6ICI1bSIKImluaGliaXRfcnVsZXMiOgotICJlcXVhbCI6CiAgLSAibmFtZXNwYWNlIgogIC0gImFsZXJ0bmFtZSIKICAic291cmNlX21hdGNoIjoKICAgICJzZXZlcml0eSI6ICJjcml0aWNhbCIKICAidGFyZ2V0X21hdGNoX3JlIjoKICAgICJzZXZlcml0eSI6ICJ3YXJuaW5nfGluZm8iCi0gImVxdWFsIjoKICAtICJuYW1lc3BhY2UiCiAgLSAiYWxlcnRuYW1lIgogICJzb3VyY2VfbWF0Y2giOgogICAgInNldmVyaXR5IjogIndhcm5pbmciCiAgInRhcmdldF9tYXRjaF9yZSI6CiAgICAic2V2ZXJpdHkiOiAiaW5mbyIKInJlY2VpdmVycyI6Ci0gIm5hbWUiOiAiRGVmYXVsdCIKLSAibmFtZSI6ICJXYXRjaGRvZyIKLSAibmFtZSI6ICJDcml0aWNhbCIKInJvdXRlIjoKICAiZ3JvdXBfYnkiOgogIC0gIm5hbWVzcGFjZSIKICAiZ3JvdXBfaW50ZXJ2YWwiOiAiNW0iCiAgImdyb3VwX3dhaXQiOiAiMzBzIgogICJyZWNlaXZlciI6ICJEZWZhdWx0IgogICJyZXBlYXRfaW50ZXJ2YWwiOiAiMTJoIgogICJyb3V0ZXMiOgogIC0gIm1hdGNoIjoKICAgICAgImFsZXJ0bmFtZSI6ICJXYXRjaGRvZyIKICAgICJyZWNlaXZlciI6ICJXYXRjaGRvZyIKICAtICJtYXRjaCI6CiAgICAgICJzZXZlcml0eSI6ICJjcml0aWNhbCIKICAgICJyZWNlaXZlciI6ICJDcml0aWNhbCI=" | base64 -d
"global":
"resolve_timeout": "5m"
"inhibit_rules":
- "equal":
- "namespace"
- "alertname"
"source_match":
"severity": "critical"
"target_match_re":
"severity": "warning|info"
- "equal":
- "namespace"
- "alertname"
"source_match":
"severity": "warning"
"target_match_re":
"severity": "info"
"receivers":
- "name": "Default"
- "name": "Watchdog"
- "name": "Critical"
"route":
"group_by":
- "namespace"
"group_interval": "5m"
"group_wait": "30s"
"receiver": "Default"
"repeat_interval": "12h"
"routes":
- "match":
"alertname": "Watchdog"
"receiver": "Watchdog"
- "match":
"severity": "critical"
"receiver": "Critical"
因此,我们需要配置告警地址等信息,只许将配置文件创建为secret对象即可。
# 邮件告警及钉钉告警配置信息如下
]# cat alert-conf/alertmanager.yaml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.126.com:25'
smtp_from: 'dayi_123@126.com'
smtp_auth_username: 'dayi_123@126.com'
smtp_auth_password: 'xxxxxx'
smtp_hello: '126.com'
smtp_require_tls: false
route:
group_by: ['alertname', 'cluster']
group_wait: 30s
group_interval: 5s
repeat_interval: 5m
receiver: default
routes:
- receiver: email
group_wait: 10s
match_re:
team: node
- receiver: webhook
group_wait: 10s
receivers:
- name:
webhook: 'webhook'
webhook_configs:
- url: 'http://ddtalk-hook:8060'
send_resolved: true
- name: 'default'
email_configs:
- to: 'liuyi@ecmoho.com'
send_resolved: true
- name: 'email'
email_configs:
- to: 'liuyi@ecmoho.com'
send_resolved: true
# 删除之前的secret,创建新的secret
]# kubectl delete secret alertmanager-main -n monitoring
secret "alertmanager-main" deleted
]# kubectl create secret generic alertmanager-main --from-file=alert-conf/alertmanager.yaml -n monitoring
secret/alertmanager-main created
定义了钉钉告警后,自然要定义告警接收程序,将前面prometheus的钉钉告警接收程序修改下名称空间放在当前名称空间即可。
# 接收处理钉钉告警资源配置如下
]# cat ddtalk-hook.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ddtalk-hook
namespace: monitoring
spec:
selector:
matchLabels:
app: ddtalk-hook
template:
metadata:
labels:
app: ddtalk-hook
spec:
containers:
- name: ddtalk-hook
image: timonwong/prometheus-webhook-dingtalk:v1.4.0
args:
- --ding.profile=webhook1=https://oapi.dingtalk.com/robot/send?access_token=53630694d60843f17b99e40949afba58fb247995554120bf054037f6111ea59f
ports:
- containerPort: 8060
name: http
resources:
requests:
cpu: 50m
memory: 100Mi
limits:
cpu: 50m
memory: 100Mi
---
apiVersion: v1
kind: Service
metadata:
name: ddtalk-hook
namespace: prometheus
spec:
selector:
app: ddtalk-hook
ports:
- name: hook
port: 8060
targetPort: http
# 创建
]# kubectl apply -f ddtalk-hook.yaml