K8s 集群监控之Kube Prometheus(Prometheus Operator)

Kube Prometheus项目地址

https://github.com/coreos/kube-prometheus

项目的Helm安装包地址

https://github.com/helm/charts/blob/master/stable/prometheus-operator

Prometheus官网地址

https://prometheus.io/

Prometheus Operator项目地址

https://github.com/coreos/prometheus-operator/

一个部署样例

https://github.com/coreos/kube-prometheus/blob/master/examples/example-app/

Prometheus Operator是什么

Prometheus Operator是运行在Kubernetes之上的监控和告警工具。部署时不用创建和修改prometheus的配置文件,所有的操作通过创建prometheus自己的资源对象来实现。对于监控配置的修改可以做到实时生效。

Prometheus Operator的自定义资源(CustomResourceDefinitions CRD)

  • Prometheus: 定义Prometheus监控系统的部署。
  • ServiceMonitor:监控一组service。该service需要暴露监控数据,供prometheus收集。
  • PodMonitor:监控一组pod。
  • PrometheusRule:Prometheus的规则文件。包含告警规则。
  • AlertManager:定义告警管理器的部署。

QuickStart

下载kube-prometheus项目。

git clone https://github.com/coreos/kube-prometheus.git

执行:

# Create the namespace and CRDs, and then wait for them to be availble before creating the remaining resources
kubectl create -f manifests/setup
# 下面命令为等待setup过程运行完毕
until kubectl get servicemonitors --all-namespaces ; do date; sleep 1; echo ""; done
kubectl create -f manifests/

移除Kube Prometheus

执行:

kubectl delete --ignore-not-found=true -f manifests/ -f manifests/setup

访问仪表盘

可以使用port forward方式访问仪表盘。

访问Prometheus

$ kubectl --namespace monitoring port-forward svc/prometheus-k8s 9090

访问Grafana

$ kubectl --namespace monitoring port-forward svc/grafana 3000

访问Alert Manager

$ kubectl --namespace monitoring port-forward svc/alertmanager-main 9093

这些服务的端口可以通过localhost访问到。

注意:如果需要通过其他地址访问,需要增加address参数。举例如下:

$ kubectl --namespace monitoring port-forward --address 0.0.0.0 svc/prometheus-k8s 9090

手动部署prometheus operator

上面步骤使用的是Kube Prometheus。该项目内置了一系列prometheus operator的资源对象配置,可以做到一键安装。

Prometheus operator也可以手工方式部署。

安装Prometheus Operator

  1. Git下载Prometheus Operator项目
git clone https://github.com/coreos/prometheus-operator.git
  1. 执行命令,创建prometheus-operator对象和相关CRD
kubectl apply -f bundle.yaml
  1. 启用prometheus资源对象的RBAC规则

创建ServiceAccount:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus

创建ClusterRole:

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]

创建ClusterRoleBinding

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: default
  1. 创建prometheus资源对象
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
spec:
  serviceAccountName: prometheus
  serviceMonitorSelector:
    matchLabels:
      team: frontend
  podMonitorSelector:
    matchLabels:
      team: frontend
  resources:
    requests:
      memory: 400Mi
  enableAdminAPI: false

通过serviceMonitorSelectorpodMonitorSelector决定哪些ServiceMonitor和PodMonitor生效。如果选择器为空({})意味着会选择所有的对象。

  1. 部署自己的应用。
    下面举一个例子:

创建一个Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example-app
  template:
    metadata:
      labels:
        app: example-app
    spec:
      containers:
      - name: example-app
        image: fabxc/instrumented_app
        ports:
        - name: web
          containerPort: 8080

这里假定我们的监控数据在8080端口暴露。

再创建一个service,即访问监控数据的service。

kind: Service
apiVersion: v1
metadata:
  name: example-app
  labels:
    app: example-app
spec:
  selector:
    app: example-app
  ports:
  - name: web
    port: 8080
  1. 创建ServiceMonitor

这一步我们需要Prometheus读取上一步创建的service暴露的监控数据。需要借助于ServiceMonitor完成。

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: example-app
  labels:
    team: frontend
spec:
  selector:
    matchLabels:
      app: example-app
  endpoints:
  - port: web

注意:

  • 这里的selector需要匹配上一步创建出来的service。
  • endpoints的port只能配置为service中的命名端口,不能使用数字。
  • 需要确保prometheus对象的serviceMonitorSelectorserviceMonitorNamespaceSelector匹配这一步创建出的ServiceMonitor对象。
  1. 暴露prometheus端口

如果需要暴露prometheus端口可以在集群外访问,需要执行此步骤。

apiVersion: v1
kind: Service
metadata:
  name: prometheus
spec:
  type: NodePort
  ports:
  - name: web
    nodePort: 30900
    port: 9090
    protocol: TCP
    targetPort: web
  selector:
    prometheus: prometheus

这里使用创建了一个使用NodePort的Service。

Prometheus资源对象

Prometheus资源对象的作用相当于整个Prometheus的配置中心。

Prometheus资源对象描述文件如下:

apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  creationTimestamp: "2020-02-12T04:38:38Z"
  generation: 1
  labels:
    prometheus: k8s
  name: k8s
  namespace: monitoring
  resourceVersion: "3745"
  selfLink: /apis/monitoring.coreos.com/v1/namespaces/monitoring/prometheuses/k8s
  uid: 3d66375e-b8fb-453b-bcd2-a9ef1fd75387
spec:
  alerting:
    alertmanagers:
    - name: alertmanager-main
      namespace: monitoring
      port: web
  baseImage: quay.io/prometheus/prometheus
  nodeSelector:
    kubernetes.io/os: linux
  podMonitorNamespaceSelector: {}
  podMonitorSelector: {}
  replicas: 2
  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.15.2

其中,限制监控范围的配置有如下四个:

  • podMonitorNamespaceSelector:扫描哪个namespace下的PodMonitor,如果为空,则扫描所有的namespace。
  • serviceMonitorNamespaceSelector:扫描哪个namespace下的ServiceMonitor,如果为空,则扫描所有的namespace。
  • podMonitorSelector:通过selector配置扫描哪些PodMonitor。如果为空,则扫描所有PodMonitor。
  • serviceMonitorSelector:通过selector配置扫描哪些ServiceMonitor。如果为空,则扫描所有ServiceMonitor。

除此之外还有一个ruleSelector,只有匹配该selector的PrometheusRules才会被读取。因此我们如是用默认的prometheus配置,自己创建的PrometheusRules需要有如下两个标签:

prometheus: k8s
role: alert-rules

指定Prometheus的远程存储

生产环境Prometheus的监控数据需要落地到数据库中。

建议使用Influx数据库。它和Prometheus的兼容性最好。

安装InfluxDB

InfluxDB官网链接:https://www.influxdata.com/

下载安装并启动服务即可。

# 启动InfluxDB
systemctl start influxdb

# 进入InfluxDB
influx

创建一个名为prometheus的数据库:

curl -XPOST http://localhost:8086/query --data-urlencode "q=CREATE DATABASE prometheus"

编译并运行Remote storage adapter

Prometheus使用Influx作为远程存储需要一个remote_storage_adapterremote_storage_adapter可以支持Graphite, Influxdb和Opentsdb。其中Influxdb支持READ和WRITE模式。

源代码链接如下:https://github.com/prometheus/prometheus/tree/master/documentation/examples/remote_storage/remote_storage_adapter

使用Git clone源代码之后,执行go build命令编译。

接下来运行Remote storage adapter

./remote_storage_adapter --influxdb-url=http://localhost:8086/ --influxdb.database=prometheus --influxdb.retention-policy=autogen

注意:这里Influxdb默认端口是8086,使用的数据库名为prometheus。

配置prometheus资源对象

涉及的配置项解释如下:

  • remoteRead 获取数据的URL
  • remoteWrite 写入数据的URL

修改prometheus资源对象的配置文件,增加:

spec:
  remoteRead:
    - url: "http://localhost:9201/read"
  remoteWrite:
    - url: "http://localhost:9201/write"

注意:9201端口是remote_storage_adapter默认监听的端口。

PS:prometheus原生配置文件的配置方法如下:

# Remote write configuration (for Graphite, OpenTSDB, or InfluxDB).
remote_write:
  - url: "http://localhost:9201/write"

# Remote read configuration (for InfluxDB only at the moment).
remote_read:
  - url: "http://localhost:9201/read"

ServiceMonitor资源资源对象

配置Prometheus从一个Service读取监控信息。

首先配置一个service,用来指定监控信息暴露端口。

kind: Service
apiVersion: v1
metadata:
  name: example-app
  labels:
    app: example-app
spec:
  selector:
    app: example-app
  ports:
  - name: web
    port: 8080

监控信息从这个pod的8080端口暴露。

再创建一个ServiceMonitor:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: example-app
  labels:
    team: frontend
spec:
  selector:
    matchLabels:
      app: example-app
  endpoints:
  - port: web

port这个地方必须使用命名端口。

PodMonitor

配置Prometheus从一个Pod读取监控信息。

注意:目前配置项作用尚未明确,这里给出部分配置项。

apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: example-pod-monitor
  namespace: default
  labels:
    app: example
spec:
  podMetricsEndpoints:
  selector:
  podTargetLabels:
  sampleLimit:
  jobLabel:

PrometheusRule

用于配置告警规则。

示例如下:

kind: PrometheusRule
metadata:
labels: 
  prometheus: k8s
  role: alert-rules
name: prometheus-k8s-rules
spec:
  groups:
  - name: k8s.rules
  rules: 
  - alert: KubeletDown
    annotations:
      message: Kubelet has disappeared from Prometheus target discovery.
    expr: |
      absent(up{job="kubelet"} == 1)
    for: 15m
    labels:
      severity: critical

和Ingress配合使用

除了使用NodePort暴露prometheus服务到集群外,我们还可以使用Ingress的方式暴露服务。

Ingress的配置如下所示:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: monitoring
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: "/$1"
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: prometheus
          servicePort: 9090
        path: /prometheus/(.*)

该Ingress将/prometheus/映射为prometheus这个service。此时可以通过http://hostname/prometheus/访问到Prometheus server。但有个问题,页面的静态资源没法加载。

为了解决这个问题,接下来需要为Prometheus server添加一个context path的配置。

Prometheus对象有一个externalUrl的配置项,它包含了context path的功能,需要配置为完整的对外暴露的URL。如下所示:

apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: main
spec:
  replicas: 2
  version: v2.15.2
  externalUrl: http://hostname/prometheus/
  resources:
    requests:
      memory: 400Mi

更详细的使用方式可参考:
https://coreos.com/operators/prometheus/docs/latest/user-guides/exposing-prometheus-and-alertmanager.html

使用示例

https://github.com/coreos/kube-prometheus/blob/master/examples/example-app/

参考文档

https://github.com/coreos/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md

https://coreos.com/operators/prometheus/docs/latest/user-guides/exposing-prometheus-and-alertmanager.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容