介绍
Prometheus Operator 为 Kubernetes 提供了对 Prometheus 机器相关监控组件的本地部署和管理方案,该项目的目的是为了简化和自动化基于 Prometheus 的监控栈配置,主要包括以下几个功能:
Kubernetes 自定义资源:使用 Kubernetes CRD 来部署和管理 Prometheus、Alertmanager 和相关组件。
简化的部署配置:直接通过 Kubernetes 资源清单配置 Prometheus,比如版本、持久化、副本、保留策略等等配置。
Prometheus 监控目标配置:基于熟知的 Kubernetes 标签查询自动生成监控目标配置,无需学习 Prometheus 特地的配置。
Prometheus Operator 的架构图:
kube-prometheus是通过k8s operator的方式实现的监控方案,首先会在k8s集群内注册多个crd资源,其中最主要四种的crd资源,并利用 Operator 编写了一系列常用的监控资源清单。
Prometheus: 由 Operator 依据一个自定义资源kind: Prometheus类型中,所描述的内容而部署的 Prometheus Server 集群,可以将这个自定义资源看作是一种特别用来管理Prometheus Server的StatefulSets资源。
ServiceMonitor: 这个CRD定义了,我们需要监控的动态服务,通过获取到svc到label标签进行绑定到,指定的svc然后获取到对应的ep资源的metics路由(可以定义目标的metrics的url),得而可以提取了pod的监控数据。Operator也会实时的watch servicemonitor资源的变化,当有新的servicemonitor创建的时候他会自动去更新prometheus.yml文件,然后对prometheus-server进行reload的操作。
Alertmanager:该 CRD 定义了在 Kubernetes 集群中运行的 Alertmanager 的配置,同样提供了多种配置,包括持久化存储。
对于每个 Alertmanager 资源,Operator 都会在相同的命名空间中部署一个对应配置的 StatefulSet,Alertmanager Pods 被配置为包含一个名为 的 Secret,该 Secret 以 alertmanager.yaml 为 key 的方式保存使用的配置文件。
PrometheusRule: 该CRD定义了我们需要监控告警的规则,有非常重要的一个属性 ruleSelector,用来匹配 rule 规则的过滤器,要求匹配具有 prometheus=k8s 和 role=alert-rules 标签的 PrometheusRule 资源对象。创建好的promethrule规则也会被Operator自动加载到prometheus-server的/etc/prometheus/rules/prometheus-k8s-rulefiles-0/这个路径下面
然后会在集群里以deployment的方式运行prometheus-operator的controller自定义控制器。这个控制器会定时的list/watch上述的四种主要的crd资源,通过loop循环的方式来调谐管理对应的资源,从而有效的管理监控资源。
日常管理使用
创建监控的流程:
- 在程序开发的时候暴露metrics接口并提供监控数据
- 创建SVC,确保通过svc的可以正常获取到ep的监控数据
- 创建servicemonitor通过svc的label进行绑定,并设置jobLabel(定义通过ep的哪个label的值设置为job的名称),如果metrics接口不是/metrics的时候也可以通过配置path修改默认值
监控ETCD案例:
修改ETCD的metrics的监听地址
这边环境使用kubeadm部署,通过kubectl获取到etcd的配置文件查看:
`[root@dm01 ~]# kubectl get po etcd-dm01 -n kube-system -o yaml| grep -C 10 metrics`
- command:
- etcd
- --advertise-client-urls=https://115.238.100.73:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://115.238.100.73:2380
- --initial-cluster=dm01=https://115.238.100.73:2380,dm02=https://192.168.1.12:2380,dm03=https://192.168.1.13:2380
- --key-file=/etc/kubernetes/pki/etcd/server.key
- --listen-client-urls=https://127.0.0.1:2379,https://115.238.100.73:2379
- --listen-metrics-urls=http://127.0.0.1:2381 #可以看到默认的是监听在127.0.0.1这个地址上面的
- --listen-peer-urls=https://115.238.100.73:2380
- --name=dm01
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
image: registry.aliyuncs.com/k8sxio/etcd:3.4.13-0
imagePullPolicy: IfNotPresent
复制代码
可以看到启动参数里面有一个 –listen-metrics-urls=http://127.0.0.1:2381 的配置,该参数就是来指定 metrics 接口运行在 2381 端口下面的,而且是 http 的协议,所以也不需要什么证书配置,这就比以前的版本要简单许多了,以前的版本需要用 https 协议访问,所以要配置对应的证书。
修改/etc/kubernetes/manifest/ 目录下面(静态 Pod 默认的目录)的 etcd.yaml 文件中将上面的listen-metrics-urls 更改http://0.0.0.0:2381 对外暴露即可,不然等会通过servicemonitor获取的数据的时候会出现被拒绝的情况。
创建ServiceMonitor资源
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
labels:
k8s-app: etcd-k8s
spec:
endpoints:
- interval: 15s
port: port
jobLabel: k8s-app
namespaceSelector:
matchNames:
- kube-system
selector:
matchLabels:
k8s-app: etcd-demo
复制代码
创建SVC和endpoints
apiVersion: v1
kind: Service
metadata:
labels:
k8s-app: etcd-demo
name: etcd-k8s
namespace: kube-system
spec:
clusterIP: None
ports:
- name: port
port: 2381
protocol: TCP
targetPort: 2381
type: ClusterIP
---
apiVersion: v1
kind: Endpoints
metadata:
labels:
k8s-app: etcd-demo
name: etcd-k8s
namespace: kube-system
subsets:
- addresses:
- ip: 192.168.1.11
nodeName: dm01
- ip: 192.168.1.12
nodeName: dm02
- ip: 192.168.1.13
nodeName: dm03
ports:
- name: port
port: 2381
protocol: TCP
复制代码
去prometheus页面上面查看是否获取到ETCD的监控数据
数据采集到后,可以在 grafana 中导入编号为 3070 的 dashboard,就可以获取到 etcd 的监控图表
创建PrometheusRule
我们设定一个规则,如果ETCD集群存活的节点数小于3的话就触发报警
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
labels:
prometheus: k8s
role: alert-rules
name: etcd-rules
namespace: monitoring
spec:
groups:
- name: etcd
rules:
- alert: EtcdClusterUnavailable
annotations:
description: Node survival is not equal to three
summary: etcd cluster small
expr: "sum(up{job="etcd-demo"}) < 3"
for: 1m
labels:
severity: critical
复制代码
关键配置说明
1. 创建rule的时候下面的两个label必须满足,这样才能被识别,这个可以通过查看prometheus这个CRD资源到yaml文件中查看到ruleSeletor的定义
`[root@dm01 /opt/softs]# kubectl get Prometheus k8s -o yaml -n monitoring `
···
ruleSelector:
matchLabels:
prometheus: k8s
role: alert-rules
···
复制代码
2. expr表示PromQ语法判断有没有满足设定的阀值,for表示满足这个条件多久才会发生告警,一般的话满足条件会处于pending状态,这个表示过了一分钟以后会出firing
expr: "sum(up{job="etcd-demo"}) < 3"
for: 1m
复制代码
创建完成之后可以在prometheus的rules页面上看到这个规则
Altermanager实现企业微信告警
这边测试实现告警时通过Altermanager+prometheusAlter调用企业微信的机器人实现告警。
部署prometheusAlter服务并修改app.conf文件
kubectl apply -n monitoring -f https://raw.githubusercontent.com/feiyu563/PrometheusAlert/master/example/kubernetes/PrometheusAlert-Deployment.yaml
复制代码
prometheusAlter的配置文件时通过ConfigMap的形式挂载进去的,这个服务提供非常多的告警渠道,我们这边只是使用了微信告警的模式
修改关键配置
`[root@dm01 /etc/kubernetes]# kubectl edit configmap prometheus-alert-center-conf -n monitoring -o yaml`
···
#是否开启微信告警通道,可同时开始多个通道0为关闭,1为开启
open-weixin=1
#默认企业微信机器人地址
wxurl=xxxxx
···
复制代码
通过创建ingress配置域名访问他的UI界面
可以通过告警测试,查看有没有问题
配置Altermanager服务的配置
注:Altermanager的报警文件是存储在alertmanager-secret这个secret里面的,编辑配置
[root@dm01 /etc/kubernetes]# cat /root/kube-prometheus/manifests/alertmanager.yaml
global:
resolve_timeout: 5m
route:
group_by: ['instance']
group_wait: 30s # 当一个新的报警分组被创建后,需要等待至少 group_wait 时间来初始化通知,这种方式可以确保您能有足够的时间为同一分组来获取多个警报,然后一起触发这个报警信息。
group_interval: 10s # 相同的group之间发送告警通知的时间间隔
repeat_interval: 10m # 如果一个报警信息已经发送成功了,等待 repeat_interval 时间来重新发送他们,不同类型告警发送频率需要具体配置
receiver: 'web.hook.prometheusalert' # 默认的receiver:如果一个报警没有被一个route匹配,则发送给默认的接收器
# 上面所有的属性都由所有子路由继承,并且可以在每个子路由上进行覆盖。
routes:
- receiver: 'web.hook.prometheusalert'
group_wait: 10s
match:
level: '1'
receivers:
- name: 'web.hook.prometheusalert'
webhook_configs: #定义我们上面部署的PrometheusAlter服务的svc地址
- url: 'http://prometheus-alert-center.monitoring.svc.cluster.local:8080/prometheus/alert'
复制代码
重新创建alertmanager-main这个secret实现更新
[root@dm01 /etc/kubernetes]# kubectl delete secret alertmanager-main -n monitoring
secret "alertmanager-main" deleted
[root@dm01 /etc/kubernetes]# kubectl create secret generic alertmanager-main --from-file=/root/kube-prometheus/manifests/alertmanager.yaml -n monitoring
复制代码
触发报警测试
使一个节点的ETCD挂掉
在kubeadm部署的环境里面直接mv走这个etcd的yaml文件就可以
[root@dm01 /etc/kubernetes/manifests]# mv etcd.yaml /opt/softs/
[root@dm01 /etc/kubernetes/manifests]# docker ps | grep -i etcd
复制代码
过一分钟查看Alter的状态
企业微信收到告警
golang的基础监控实现
用一段最基础的代码
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":2112", nil)
}
复制代码
通过Dockerfile打包
### Build the manager binary
FROM golang:1.15 as builder
WORKDIR /workspace
ENV GOPROXY="https://goproxy.cn,direct"
# Copy the go source
COPY . .
# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -o gotest main.go
# Runtime
FROM alpine
WORKDIR /usr/local/bin
COPY --from=builder /workspace/gotest /usr/local/bin/gotest
CMD ["gotest"]
复制代码
打包后部署到k8s环境并创建servicemonitor资源
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: go-demo
namespace: monitoring
labels:
k8s-app: go-demo
spec:
jobLabel: k8s-app
endpoints:
- port: port
interval: 15s
selector:
matchLabels:
k8s-app: go-demo
namespaceSelector:
matchNames:
- test008
---
apiVersion: v1
kind: Service
metadata:
name: go-demo
namespace: test008
labels:
k8s-app: go-demo
spec:
type: ClusterIP
ports:
- name: port
port: 2121
selector:
k8s-app: go-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-demo
namespace: test008
labels:
k8s-app: go-demo
spec:
replicas: 1
selector:
matchLabels:
k8s-app: go-demo
template:
metadata:
labels:
k8s-app: go-demo
spec:
containers:
- name: go-demo
image: xxx
ports:
- containerPort: 2121
复制代码
问题
这个时候我们创建起来查看控制台会发现,其实并没有获取到我们部署到这个服务,查看prometheus的日志发现,由于prometheus对这个test008没有权限获取资源
原因
由于我们默认部署的kube-prometheus,他的role和rolebinding只对三个命名空间创建绑定了权限“default”,“monitoring”,“kube-system”,获取别的命名空间里的数据时需要创建对应的role和rolebinding规则
###对指定命名空间创建Role
apiVersion: rbac.authorization.k8s.io/v1
items:
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: prometheus-k8s
namespace: default
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: prometheus-k8s
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: prometheus-k8s
namespace: monitoring
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: prometheus-k8s
namespace: test008
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- pods
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch
kind: RoleList
复制代码
创建Rolebinding
apiVersion: rbac.authorization.k8s.io/v1
items:
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prometheus-k8s
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: monitoring
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prometheus-k8s
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: monitoring
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prometheus-k8s
namespace: monitoring
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: monitoring
- apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prometheus-k8s
namespace: test008
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: prometheus-k8s
subjects:
- kind: ServiceAccount
name: prometheus-k8s
namespace: monitoring
kind: RoleBindingList
复制代码