Contents

Prometheus in k8s(一) —— 使用kube-prometheus快速部署监控体系

前言

又好久没写博客了🤣真的不能把这个习惯丢掉啊,这次来记录一下在k8s集群上搭建监控体系的过程。

入职应用运维快半年了,逐渐发现开发只是IT团队的冰山一角,它固然至关重要,但背后支撑它能够露出水面的,是infra、运维、产品等多团队的同心协力。而就运维团队而言 ,对运行中应用进行即时监控与事件告警,可以说是关键能力之一。这个系列的主要目的,就是记录如何在k8s集群中搭建云原生的prometheus监控体系,在接下来的几篇博文内,将记录如何在自建k8s集群上部署prometheus operator,部署prom、grafana等实例,暴露web服务,实现监控数据持久化乃至最后实现对集群内外的应用服务进行监控告警。

Prometheus组件

下面是一个最简单的Prometheus部署架构:

其中:

  • 左侧是被监控的应用或者Exporter,负责暴露接口供Prometheus抓取监控指标,Exporter是一种程序的代称,负责抓取真正要被监控的应用的数据,有时候原有应用没有符合Prometheus规范的数据接口,就需要通过外挂一个Exporter来接入Prometheus的监控
  • 中间就是Prometheus Server了,负责根据配置抓取要监控的应用的指标,保存到内置的TSDB中,并提供查询接口。同时根据告警规则,当基于指标的表达式满足规则的时候,把告警推送给Alert Manager
  • 右侧则是Alert Manage,负责对Prometheus发送过来的告警事件进行分类聚合、抑制与第三方推送

另外,最常见而未提及的组件便是Grafana了,它负责调用Prometheus API,对数据进行可视化展示。

Prometheus Operator

那么假如我们需要监控的对象是部署在k8s上的集群,该如何使用Prometheus对其进行监控呢?相比于在集群外的vm上另外搭建Prometheus,更加云原生的做法是直接在集群内搭建Prometheus,如此一来,Prometheus本身使用到了k8s的高可用能力,同时又可以直接与集群内的监控对象通过虚拟网络直接通信,无需另外打通监控出口。

在云原生社区,有一套简单有效的Prometheus部署方案,也就是Prometheus Operator。Operator可以说是kubernetes的一种设计模式,它的核心思想是,通过一组在集群内运行的Operator应用,不断监控自定义资源,像k8s本身不断监控deployment等资源一样,自动在集群内部署包含领域知识的应用。Prometheus Operator便是如此,它通过监控Prometheus, AlertManager, ServiceMonitor等CRD来自动部署、配置集群内的Prometheus,运维人员只需要通过这些CRD描述自己希望的监控系统,无需手动操作,当需要在另一套集群内重新部署的时候,只需要再安装Operator,然后应用同一份CRD就可以了。

接下来,我们将通过Prometheus Operator来部署一套简单的监控方案,它既可以监控集群本身的状态,也可以监控集群内应用的状态。

kube-prometheus

官方提供了kube-prometheus这个框架来进行快速部署,用户只需要apply项目中的manifest文件,k8s就会新建一个namespace,然后把prometheus、alertmanager、grafana以及需要使用的CRD一并部署上去。同时它还附带了一套标准的监控配置,用于监控集群的节点、pod等基本的信息。

在k8s集群节点上:

1
2
3
4
5
6
7
8
9
# Create the namespace and CRDs, and then wait for them to be available before creating the remaining resources
# Note that due to some CRD size we are using kubectl server-side apply feature which is generally available since kubernetes 1.22.
# If you are using previous kubernetes versions this feature may not be available and you would need to use kubectl create instead.
kubectl apply --server-side -f manifests/setup
kubectl wait \
	--for condition=Established \
	--all CustomResourceDefinition \
	--namespace=monitoring
kubectl apply -f manifests/

等待镜像拉取并启动后,便能看到以下deployment与pod被成功部署:

此时,prometheus便开始根据默认配置抓取集群的监控数据了,接下来我们配置一个简单的nodePort Service,将prometheus的statefulset暴露到节点上,便能访问它的WebUI,可以看到已经抓取了很多指标:

我们可以做一个简单的查询,获取节点硬盘占用情况:

你可能会好奇它是如何获取节点宿主机的数据的,这是node-exporter的daemonset的片段:

 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
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app.kubernetes.io/component: exporter
      app.kubernetes.io/name: node-exporter
      app.kubernetes.io/part-of: kube-prometheus
  template:
    spec:
      automountServiceAccountToken: true
      containers:
        image: quay.io/prometheus/node-exporter:v1.7.0
        name: node-exporter
          readOnlyRootFilesystem: true
        volumeMounts:
        - mountPath: /host/sys
          mountPropagation: HostToContainer
          name: sys
          readOnly: true
        - mountPath: /host/root
          mountPropagation: HostToContainer
          name: root
          readOnly: true
        env:
        - name: IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        image: quay.io/brancz/kube-rbac-proxy:v0.16.0
        name: kube-rbac-proxy
        ports:
        - containerPort: 9100
          hostPort: 9100
          name: https
          readOnlyRootFilesystem: true
          runAsGroup: 65532
          runAsNonRoot: true
          runAsUser: 65532
          seccompProfile:
            type: RuntimeDefault
      hostNetwork: true
      hostPID: true
      nodeSelector:
        kubernetes.io/os: linux
      securityContext:
        runAsNonRoot: true
        runAsUser: 65534
      serviceAccountName: node-exporter
      volumes:
      - hostPath:
          path: /sys
        name: sys
      - hostPath:
          path: /
        name: root

daemonset配置了两个容器,kube-rbac-proxynode-exporter,其中node-exporter挂载了宿主机的根目录,还有宿主网络、pid等,于是能拿到各种硬件与底层文件的数据,然后kube-rbac-proxy则作为安全代理,转发prometheus server的监控抓取请求

Prometheus k8s常用指标

接下来我们探索一下这个监控集群的Prometheus,从一些常用指标开始

节点级别

节点CPU平均使用率

1
avg by (instance) (1-rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100

节点内存使用率

1
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100

节点硬盘使用率

1
(node_filesystem_size_bytes - node_filesystem_free_bytes) / node_filesystem_size_bytes{mountpoint="/"} * 100

kube-state-metrics

查看节点基本信息

1
kube_node_info

查看节点状态(有没有OutOfDisk、MemoryPressure、DiskPressure)

1
kube_node_status_condition

deployment副本状态

1
2
3

kube_deployment_spec_replicas #期望的副本数
kube_deployment_status_replicas #实际运行的副本数

30分钟内pod重启的次数

1
changes(kube_pod_container_status_restarts_total[5m])

Pod CPU使用量前10

1
topk(10, rate(container_cpu_usage_seconds_total{pod!=""}[5m]))

Pod 内存使用MB前10

1
topk(5,sum(container_memory_usage_bytes{container="",pod!=""}/(1024*1024)) by (pod))

容器在fs上消耗的字节数

1
container_fs_usage_bytes

To Be Continued

在这篇笔记中,我们学习了prometheus的基本架构,prometheus operator在k8s集群中的工作原理,以及如何使用kube-prometheus进行快速部署,最后记录了一些prometheus对k8s集群的常用监控指标。下一篇将记录如何把这些指标配置到grafana上实现可视化,alertmanager,然后重点记录alertmanager的相关概念及用法,最后实现一个把告警推送到第三方服务的demo。