Featured image of post 从零安装prometheus

从零安装prometheus

家里的各种服务,监控需求总是少不了的。目前最常用的监控莫过去prometheusgrafana组合了。但是网网上的多种都过期了,因为官方把helm charts分拆了,这里手把手教你如何从零开始安装它。

本文提供两种方案,一个是基于kube-prometheus-stack安装直接监控全家桶,新手是推荐的,免除不少折腾,开箱即用。另一种是基于prometheus-operator再一步步修改配置,并且安装插件以提供监控能力。

说明:本文假定你有一定基础,如果你要问啥是prometheus,那请关闭本文章去自行Google学习。

前置准备

为了让数据可以更加持久化,我们让Prometheus使用外部PV来保存数据,这样集群挂掉都不会丢失我们监控数据(其实这数据也没那么重要啦:D)。所以我基于longhorn部署了一套自用的分布式存储系统,这里不谈其具体部署(你或许也有其它选择),仅看一下PV的定义:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: PersistentVolume
metadata:
  name: prometheus-vol-pv
  labels:
    app: prometheus-vol-pv
spec:
  capacity:
    storage: 10Gi # 这个大小家用或许够了吧
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: longhorn
  csi:
    driver: driver.longhorn.io
    fsType: ext4
    volumeAttributes:
      numberOfReplicas: '3'
      staleReplicaTimeout: '2880'
    # 这个需要先在Longhorn UI中先CreateVolume
    volumeHandle: prometheus-pv

基于kube-prometheus-stack安装

这是全家桶,除了prometheus,operator等,还带了grafana。我们直基于Helm chart安装,可以简要看一下说明:

1
2
3
4
5
6
  {
    "name": "prometheus-community/kube-prometheus-stack",
    "version": "40.1.2",
    "app_version": "0.59.1",
    "description": "kube-prometheus-stack collects Kubernetes manifests, Grafana dashboards, and Prometheus rules combined with documentation and scripts to provide easy to operate end-to-end Kubernetes cluster monitoring with Prometheus using the Prometheus Operator."
  }

基于自己的需求,定制了一些values选项:

  • 关闭了一些用不到的选项
  • 指定了我自己分配的PV(为了长期持久化保存监控数据,你可能需要静态PV)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# ----- 以下是 values-kube-stack.yaml 的内容 -------------
alertmanager:
  enabled: false

pushgateway:
  enabled: false

prometheus:
  enabled: true
  prometheusSpec:
   ## Prometheus StorageSpec for persistent data
    ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/storage.md
    storageSpec: 
    ## Using PersistentVolumeClaim
      volumeClaimTemplate:
       spec:
         storageClassName: longhorn # 这里我指定了另一个sc,可换成你正在用的或""
         accessModes: ["ReadWriteOnce"]
         resources:
           requests:
             storage: 10Gi

使用helm安装

我们可以直接用helm安装(这是最简便的):

1
helm install prometheus prometheus-community/kube-prometheus-stack -f values-kube-stack.yaml -n prometheus

稍等一会,你可看到各个服务在上面指定的命名空间prometheus中启动了,有这些:

  • prometheus-kube-prometheus-operator: [核心]控制器
  • prometheus-kube-state-metrics: 插件:k8s指标收集
  • prometheus-grafana: grafana,用于可视化
  • prometheus-node-exporter: 插件:node指标收集
  • prometheus-prometheus-kube-prometheus-prometheus-0: [核心]prometheus存储及服务

基本上你不用再配置啥了,直接去使用吧~

使用helmfile安装

另外如果你使用helmfile安装的话,注意其不会安装crds,需要我们手工安装,我们可以写个如下的kustomization文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
resources:
  - pv.yaml # 前文所说的静态PV
  # 首次执行需要安装crd,请反注释下面这一段
  - crds/crd-alertmanagerconfigs.yaml
  - crds/crd-alertmanagers.yaml
  - crds/crd-podmonitors.yaml
  - crds/crd-probes.yaml
  - crds/crd-prometheuses.yaml
  - crds/crd-prometheusrules.yaml
  - crds/crd-servicemonitors.yaml
  - crds/crd-thanosrulers.yaml
namespace: prometheus

然后kubectl apply -k .即可将这些CRDs安装,再使用helmfile安装以上的helm chart。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# ------- 如果你是 helmfile 安装,类似这样配置 -----------
repositories:
 - name: prometheus-community
   url: https://prometheus-community.github.io/helm-charts
releases:
- name: prometheus
  namespace: prometheus
  chart: prometheus-community/kube-prometheus-stack
  values:
    - values-kube-stack.yaml

执行helmfile apply即可。结果和使用helm安装一样,同样你已经可以使用了。

另外如果想配置grafana,可以参考这里

小结

优点明显,部署简单,开箱即用。 缺点,勉强说的话,你没机会搞清楚为啥它能工作的。接下来我们从零开始趟坑来学习一下:)

基于prometheus-operator安装

直接安装prometheus-operator后,还需要手工安装众多东西和配置(如Prometheus资源等)要做,比较烦琐,但配置它让你对prometheus的流程能够更清晰。我们还是一步步走起。

安装operator

1
kubectl create -f  https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/bundle.yaml

做完这步之后只会有一个operator服务和crd就绪。

配置Prometheus

通过prometheus-operator可以创建我们需要的prometheus-server等。你可参考官方这里文档,我感觉这文档写得顺序有些小问题。

我们从上面链接中抄过来一些配置,这里指定了Prometheus资源和相关RBAC。

 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
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: prometheus
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/metrics
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources:
  - configmaps
  verbs: ["get"]
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: prometheus
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: prometheus
subjects:
- kind: ServiceAccount
  name: prometheus
  namespace: prometheus

当你执行apply后,趟坑之旅开始。

问题1:PV权限问题

你可能会遇上一个问题:

1
2
 prometheus ts=2022-09-23T16:58:00.286Z caller=query_logger.go:91 level=error component=activeQueryTracker msg="Error opening query log file" file=/prometheus/queri │
│ prometheus panic: Unable to create mmap-ed active query log

容器文件权限问题,参考这个issue,我们要修改Prometheus资源:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  # 添加下面的securityContext解决上述问题
  securityContext:
    runAsGroup: 0
    runAsNonRoot: false
    runAsUser: 0
    fsGroup: 0

我们添加上面的securityContext,服务一切起来正常了。

问题2:ServiceMonitor/PodMonitor无效

上面服务就绪,我们先自己安装node-exporter插件:

1
2
3
4
5
6
7
8
# 这里使用helmfile安装了node-exporter插件,你可以直接用Helm等其它方式
repositories:
 - name: prometheus-community
   url: https://prometheus-community.github.io/helm-charts
releases:
- name: prometheus-node-exporter
  namespace: prometheus
  chart: prometheus-community/prometheus-node-exporter

然后再定义一个ServiceMonitor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# 使用ServiceMonitor让prometheus可以生成抓取node-exporter的配置
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: node-exporter
  labels:
    # 1. 这里要指向Prometheus设置的label,这样ServiceMonitor才会被选择
    prometheus: kevin-prometheus
spec:
  jobLabel: jobLabel
  selector:
    # 2. 这里要匹配要监控的目标标签
    matchLabels:
      app.kubernetes.io/instance: prometheus-node-exporter
      app.kubernetes.io/name: prometheus-node-exporter
  endpoints:
    - port: metrics
  namespaceSelector:
    matchNames:
    - prometheus

虽然惊奇的发现Apply后ServiceMonitor(或PodMonitor)没有作用。原因是ServiceMonitor是通过它的labels来和我们的Prometheus关联的。我们需要继续向Prometheus添加一些参数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  securityContext:
    runAsGroup: 0
    runAsNonRoot: false
    runAsUser: 0
    fsGroup: 0
  # podMonitorSelector
  podMonitorSelector:
    matchLabels:
      prometheus: kevin-prometheus
  # serviceMonitorSelector
  serviceMonitorSelector:
    matchLabels:
      prometheus: kevin-prometheus

没有上述的matchLabels等指定一些匹配的label,并不会默认为匹配所有,它是必须的。

问题3:跨namespace后ServiceMonitor等无效

如果你继续在其它名字空间定义ServiceMonitor资源,比如我就定义了一个资源监控我笔记本使用情况:

 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
apiVersion: v1
kind: Endpoints
metadata:
    name: macbookpro15
    labels:
        system: macbookpro15
subsets:
  - addresses:
    - ip: 192.168.50.xx # 你的笔记本IP(或许要静态)
    ports:
    - name: metrics
      port: 9100
      protocol: TCP
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
    name: macbookpro15
    labels:
        app: macbookpro15
        prometheus: kevin-prometheus
spec:
    selector:
        matchLabels:
            system: macbookpro15
    namespaceSelector:
        # any: true
        matchNames:
        - monitor
    endpoints:
    - port: metrics
      interval: 10s
      honorLabels: true
---
apiVersion: v1
kind: Service
metadata:
    name: macbookpro15
    labels:
        system: macbookpro15
spec:
    ports:
    - name: metrics
      port: 9100
      protocol: TCP
      targetPort: 9100
---

整个资源在另一个名字空间monitor中,此时发现死活不能在Prometheus UI中发现这个服务。如果你通过UI查看Configuration,可能它不是下面这样的,而是指定的namespace,那就是问题所在:

1
2
3
4
5
  kubernetes_sd_configs:
  - role: pod
    kubeconfig_file: ""
    follow_redirects: true
    enable_http2: true

我们要加一下可以访问任何namespace的ServiceMonitor等资源,再一次修改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
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
  name: prometheus
  labels:
    prometheus: prometheus
spec:
  replicas: 1
  serviceAccountName: prometheus
  securityContext:
    runAsGroup: 0
    runAsNonRoot: false
    runAsUser: 0
    fsGroup: 0
  podMonitorNamespaceSelector: {}  # 这一行让可以选择任意namespace的PodMonitor
  podMonitorSelector:
    matchLabels:
      prometheus: kevin-prometheus
  serviceMonitorNamespaceSelector: {} # 这一行让可以选择任意namespace的ServiceMonitor
  serviceMonitorSelector:
    matchLabels:
      prometheus: kevin-prometheus
  storage:
    volumeClaimTemplate:
      spec:
        storageClassName: longhorn
        resources:
          requests:
            storage: 10Gi
  enableAdminAPI: true

添加注释的两行后,现在各个Namespace下的相关资源都会被发现了。

小结

通过第二种纯手工方式,我们对其运作多了一分了解。也可以做到仅部署我们想部署的服务,不受全家桶影响:)

总结

有时候一种方法搞定了,但是另一种方法有问题时,这最让人纠结。而我却总是不想绕过,于是花费了不少时间趟这种坑。从事后来看,只有踏实的理解了原理,才能够清楚配置为什么是这样的,背后是如何运转的,也算是另一种收获吧~~

如果能帮到你,欢迎留言交流探讨。