使用 Prometheus+Grafana 监控 Kubernetes 集群:从二进制文件启动,通过 YAML 文件构建

首先

最近我调查了一下如何监控Kubernetes,然后想知道实际的使用方法,于是就试着运行了起来。作为监控Kubernetes的工具,代表性的有Datadog和Prometheus,但这次我选择了调查并实践了Prometheus的使用方法。此外,我还结合了常用于与Prometheus一起使用的可视化工具Grafana进行利用。

Prometheus是什么?

最初,这个工具是由SoundCloud开发的,具备监控和警报功能。自2016年开始加入CNCF,到2018年8月获得毕业状态。

アーキテクチャ

关于其内容的说明,以下文章是一个有参考价值的资源。
下一个主要的监控工具!我们亲身实践了 Prometheus
10分钟了解 Prometheus

公式介绍页面在这里。

Prometheus的启动

使用Prometheus的方法可以大致分为两种:
1. 安装并启动二进制文件。
2. 使用容器镜像来启动。

第二个选项是可以从Kubernetes或docker开始,但本次我们将介绍通过创建yaml文件并从kubectl命令集启动的步骤。

环境

我们将使用在这篇文章中构建的环境。

操作系统:Centos7
Kubernetes版本:1.13.1
用户:以下操作均在root用户下执行。

启动二进制文件

如何从二进制文件开始的方法已在官方网页的”入门指南”中介绍。

Binary文件的安装

通过此页面选择版本并进行安装。

wget https://github.com/prometheus/prometheus/releases/download/v2.6.0/prometheus-2.6.0.linux-amd64.tar.gz
tar xvfz prometheus-2.6.0.linux-amd64.tar.gz
cd prometheus-2.6.0.linux-amd64

检查prometheus.yml文件。

在Prometheus的配置文件prometheus.yml中,默认情况下如下所示。如果有配置更改,需要修改该文件来启动Prometheus。稍后将对配置文件进行部分更改。

# my global config
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.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9090']

从二进制文件启动

以下这样通过指定配置文件来启动。

./prometheus --config.file=prometheus.yml

运行该命令后,将显示以下日志:当出现 “Server is ready to receive web requests.” 的显示时,表示可以访问。

level=info ts=2019-01-04T03:31:45.335407864Z caller=main.go:243 msg="Starting Prometheus" version="(version=2.6.0, branch=HEAD, revision=dbd1d58c894775c0788470944b818cc724f550fb)"
level=info ts=2019-01-04T03:31:45.335501267Z caller=main.go:244 build_context="(go=go1.11.3, user=root@bf5760470f13, date=20181217-15:14:46)"
level=info ts=2019-01-04T03:31:45.33552679Z caller=main.go:245 host_details="(Linux 3.10.0-957.1.3.el7.x86_64 #1 SMP Thu Nov 29 14:49:43 UTC 2018 x86_64 k8s-master (none))"
level=info ts=2019-01-04T03:31:45.335552521Z caller=main.go:246 fd_limits="(soft=1024, hard=4096)"
level=info ts=2019-01-04T03:31:45.335572558Z caller=main.go:247 vm_limits="(soft=unlimited, hard=unlimited)"
level=info ts=2019-01-04T03:31:45.336808997Z caller=main.go:561 msg="Starting TSDB ..."
level=info ts=2019-01-04T03:31:45.336861457Z caller=web.go:429 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2019-01-04T03:31:45.362425157Z caller=main.go:571 msg="TSDB started"
level=info ts=2019-01-04T03:31:45.3624917Z caller=main.go:631 msg="Loading configuration file" filename=prometheus.yml
level=info ts=2019-01-04T03:31:45.36354544Z caller=main.go:657 msg="Completed loading of configuration file" filename=prometheus.yml
level=info ts=2019-01-04T03:31:45.363564736Z caller=main.go:530 msg="Server is ready to receive web requests."

从图形用户界面进行连接

在默认设置下,您可以从localhost:9090访问Prometheus面板。在此处,我们将从http://<k8s-master的全局IP地址:9090>进行访问。
访问后,将显示以下屏幕(<k8s-master的全局IP地址:9090/graph>)。

prometheus-binary-1.jpg

当您从上述画面中访问http://<k8s-master的全局IP地址:9090/metrics>时,将显示以下指标列表。您还可以在屏幕顶部的选项卡中选择访问。

prometheus-binary-2.jpg

在《入门指南》中也提供了一些获取指标的示例。在这里,我们将获取一个名为prometheus_target_interval_length_seconds的度量指标。

prometheus-binary-5.jpg
prometheus-binary-6.jpg
prometheus-binary-7.jpg

启动 Node Exporter

Prometheus是一种Pull型的监控工具,需要从被监视的服务器接收指标。Kubernetes默认提供与Prometheus兼容的指标,但我们将启动一个名为Exporter的工具来输出指标。
在Prometheus的页面上介绍了Exporter的种类,它支持从硬件到数据库等各种指标。在这里,我们将使用一个称为Node Exporter的Exporter。关于使用Node Exporter进行Prometheus监控的方法也在官方页面上介绍,基本上我们采用那种方法。

Node Exporter也提供了二进制文件,可以在Prometheus的下载页面上找到。安装和解压二进制文件的步骤与Prometheus类似,然后启动即可。

[root@k8s-master ~]# wget https://github.com/prometheus/node_exporter/releases/download/v0.17.0/node_exporter-0.17.0.linux-amd64.tar.gz
[root@k8s-master ~]# tar xvfz node_exporter-0.17.0.linux-amd64.tar.gz
[root@k8s-master ~]# cd node_exporter-0.17.0.linux-amd64
[root@k8s-master node_exporter-0.17.0.linux-amd64]# ./node_exporter &

显示以下日志内容并启动。

INFO[0000] Starting node_exporter (version=0.17.0, branch=HEAD, revision=f6f6194a436b9a63d0439abc585c76b19a206b21)  source="node_exporter.go:82"
INFO[0000] Build context (go=go1.11.2, user=root@322511e06ced, date=20181130-15:51:33)  source="node_exporter.go:83"
INFO[0000] Enabled collectors:                           source="node_exporter.go:90"
INFO[0000]  - arp                                        source="node_exporter.go:97"
INFO[0000]  - bcache                                     source="node_exporter.go:97"
INFO[0000]  - bonding                                    source="node_exporter.go:97"
INFO[0000]  - conntrack                                  source="node_exporter.go:97"
INFO[0000]  - cpu                                        source="node_exporter.go:97"
INFO[0000]  - diskstats                                  source="node_exporter.go:97"
INFO[0000]  - edac                                       source="node_exporter.go:97"
INFO[0000]  - entropy                                    source="node_exporter.go:97"
INFO[0000]  - filefd                                     source="node_exporter.go:97"
INFO[0000]  - filesystem                                 source="node_exporter.go:97"
INFO[0000]  - hwmon                                      source="node_exporter.go:97"
INFO[0000]  - infiniband                                 source="node_exporter.go:97"
INFO[0000]  - ipvs                                       source="node_exporter.go:97"
INFO[0000]  - loadavg                                    source="node_exporter.go:97"
INFO[0000]  - mdadm                                      source="node_exporter.go:97"
INFO[0000]  - meminfo                                    source="node_exporter.go:97"
INFO[0000]  - netclass                                   source="node_exporter.go:97"
INFO[0000]  - netdev                                     source="node_exporter.go:97"
INFO[0000]  - netstat                                    source="node_exporter.go:97"
INFO[0000]  - nfs                                        source="node_exporter.go:97"
INFO[0000]  - nfsd                                       source="node_exporter.go:97"
INFO[0000]  - sockstat                                   source="node_exporter.go:97"
INFO[0000]  - stat                                       source="node_exporter.go:97"
INFO[0000]  - textfile                                   source="node_exporter.go:97"
INFO[0000]  - time                                       source="node_exporter.go:97"
INFO[0000]  - timex                                      source="node_exporter.go:97"
INFO[0000]  - uname                                      source="node_exporter.go:97"
INFO[0000]  - vmstat                                     source="node_exporter.go:97"
INFO[0000]  - xfs                                        source="node_exporter.go:97"
INFO[0000]  - zfs                                        source="node_exporter.go:97"
INFO[0000] Listening on :9100                            source="node_exporter.go:111"
prometheus-binary-12.jpg
prometheus-binary-13.jpg

编辑 prometheus.yml

要接收来自启动的Node Exporter的指标,你需要编辑prometheus.yml文件来指定目标。在这里,你可以按照以下方式更改目标的端口号。

# my global config
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.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9100']   #ポート番号を変更する
prometheus-binary-8.jpg

现在能够使用先前无法使用的指标。这里展示了一个名为node_cpu_second_total的图表。

prometheus-binary-9.jpg

您可以通过 Node Exporter 的 GitHub 页面查看可以获取哪些指标。

从别的节点获取指标

在此之前,我们一直在获取master(k8s-master)的指标,但现在我们需要获取worker(k8s-node-1)的指标。在worker一侧完成与上述步骤相同的Node Exporter的安装和启动后,我们将再次编辑prometheus.yml文件。编辑部分与之前一样,仍旧是targets的部分。

# my global config
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.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'prometheus'

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9100','k8s-node-1:9100']  #ターゲットを追加する
prometheus-binary-10.jpg

启动Grafana

我们能够通过Prometheus在这里确认指标。但正如您在屏幕上所见,显示相当单调且难以辨认。所以我们将启动Grafana作为可视化工具。Grafana的使用方法也在Prometheus官方网页上有介绍。正如预期的那样,它们通常会一起使用。启动方式与之前相同,不过在另一篇文章中他们使用systemctl进行启动,所以我们采用了这种方式。

[root@k8s-master ~]# wget https://dl.grafana.com/oss/release/grafana-5.4.2-1.x86_64.rpm
[root@k8s-master ~]# yum localinstall -y grafana-5.4.2-1.x86_64.rpm
[root@k8s-master ~]# systemctl start grafana-server
[root@k8s-master ~]# systemctl status grafana-server

当确认状态后,可以明确地看到它已经正常启动。

● grafana-server.service - Grafana instance
   Loaded: loaded (/usr/lib/systemd/system/grafana-server.service; disabled; vendor preset: disabled)
   Active: active (running) since Fri 2019-01-04 04:29:21 UTC; 8s ago
     Docs: http://docs.grafana.org
 Main PID: 2830 (grafana-server)
    Tasks: 11
   Memory: 18.5M
   CGroup: /system.slice/grafana-server.service
           └─2830 /usr/sbin/grafana-server --config=/etc/grafana/grafana.ini --pidfile=/var/run/grafana/grafana-server.pid --packaging=rpm cfg:defaul...

Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing CleanUpService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing NotificationService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing ProvisioningService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing PluginManager" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Starting plugin search" logger=plugins
Jan 04 04:29:21 k8s-master systemd[1]: Started Grafana instance.
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Plugin dir created" logger=plugins dir=/var/lib/gra.../plugins
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing TracingService" logger=server
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="Initializing Stream Manager"
Jan 04 04:29:21 k8s-master grafana-server[2830]: t=2019-01-04T04:29:21+0000 lvl=info msg="HTTP Server Listen" logger=http.server address=0.0.... socket=
Hint: Some lines were ellipsized, use -l to show in full.
prometheus-binary-11.jpg
prometheus-binary-14.jpg
prometheus-binary-15.jpg
prometheus-binary-16.jpg

准备Prometheus Dashboard

prometheus-binary-17.jpg
prometheus-binary-18.jpg
prometheus-binary-19.jpg
prometheus-binary-20.jpg
prometheus-binary-21.jpg
prometheus-binary-24.jpg
prometheus-binary-25.jpg
prometheus-binary-26.jpg
prometheus-binary-27.jpg
prometheus-binary-28.jpg
prometheus-binary-29.jpg
prometheus-binary-30.jpg

只需更改图表的标题和细节设置等,即可完成图表。

prometheus-binary-31.jpg
prometheus-binary-32.jpg

【补充】据这篇文章所述,似乎是因为无法获取cAdvisor,导致图表无法正确显示。

这是从二进制文件启动Prometheus + Grafana的方法。

创建一个yaml文件并部署。

接下来,将介绍如何创建yaml文件并部署Prometheus + Grafana。

普罗米修斯的部署

创建用于部署Prometheus的各种yaml文件。创建步骤请参考此处。

在这里我们将创建四种yaml文件。

集群角色、集群角色绑定

由于参考了上述文章,我创建了ClusterRole和ClusterRoleBinding,但是文章中是针对GKE环境的假设,并且在这种情况下我认为它们是不必要的。

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: prometheus
rules:
- apiGroups: [""]
  resources:
  - nodes
  - nodes/proxy
  - services
  - endpoints
  - pods
  verbs: ["get", "list", "watch"]
- apiGroups:
  - extensions
  resources:
  - ingresses
  verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
  verbs: ["get"]
---
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: default
  namespace: monitoring

配置映射

在从Binary启动时,我编辑了prometheus.yml文件来修改设置。在使用yaml文件启动时,似乎有几种指定的方法可供选择。

    • ConfigMapで利用するデータを書き込む

 

    Deploymentでargsでconfigファイルを指定する

本次我们将指定要写入ConfigMap的数据。我们将在data:部分写入文件的内容。

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-server-conf
  labels:
    name: prometheus-server-conf
  namespace: monitoring
data:
  prometheus.yml: |-
    # my global config
    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.
      # scrape_timeout is set to the global default (10s).

    # Alertmanager configuration
    alerting:
      alertmanagers:
      - static_configs:
        - targets:
          # - alertmanager:9093

    # Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
    rule_files:
      # - "first_rules.yml"
      # - "second_rules.yml"

    # A scrape configuration containing exactly one endpoint to scrape:
    # Here it's Prometheus itself.
    scrape_configs:
      # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
      - job_name: 'prometheus'

        # metrics_path defaults to '/metrics'
        # scheme defaults to 'http'.

        static_configs:
        - targets: ['localhost:9100','k8s-node-1:9100']

部署

用这个文件来启动 Prometheus。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: prometheus-deployment
  namespace: monitoring
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: prometheus-server
    spec:
      containers:
        - name: prometheus
          image: prom/prometheus:latest
          # configfileで指定した場所には該当のファイルが存在しません。。。
          args:
            - "--config.file=/etc/prometheus/prometheus.yml"
            - "--storage.tsdb.path=/prometheus/"
          ports:
            - containerPort: 9090

服务

仅需要一个选项来以中文母语重新表述以下内容:仅仅部署上述Deployment文件,无法进行访问。我们需要进行外部连接的设置。参考文章中介绍了两种方法。

    • kubectl port forwardingを利用する

 

    NodePort, LoadBalancer等を用いる

在这里使用后一种方法。使用NodePort可以实现来自外部的连接。指定连接端口为30000。

apiVersion: v1
kind: Service
metadata:
  name: prometheus-service
spec:
  selector: 
    app: prometheus-server
  type: NodePort
  ports:
    - port: 8080
      targetPort: 9090 
      nodePort: 30000

部署各类YAML文件

那么开始部署吧。首先创建监控用的命名空间。

[root@k8s-master ~]# kubectl create namespace monitoring
namespace/monitoring created
[root@k8s-master ~]# kubectl get ns
NAME          STATUS   AGE
default       Active   11d
kube-public   Active   11d
kube-system   Active   11d
monitoring    Active   6s
[root@k8s-master ~]#

接下来,部署ClusterRole文件。

[root@k8s-master ~]# kubectl create -f clusterRole.yml 
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
[root@k8s-master ~]# 
[root@k8s-master ~]# kubectl get clusterrole prometheus -n monitoring
NAME         AGE
prometheus   13m
[root@k8s-master ~]# 

部署 ConfigMap。

[root@k8s-master ~]# kubectl create -f prometheus-configmap.yml -n monitoring
configmap/prometheus-server-conf created
[root@k8s-master ~]# kubectl get configmap -n monitoring
NAME                     DATA   AGE
prometheus-server-conf   1      57s
[root@k8s-master ~]#

部署 Deployment 文件。

kubectl create -f prometheus-deployment.yml -n monitoring
deployment.extensions/prometheus-deployment created
[root@k8s-master ~]# kubectl get deployments -n monitoring
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
prometheus-deployment   1/1     1            1           16s
[root@k8s-master ~]#

最后部署Service文件。

[root@k8s-master ~]# kubectl create -f prometheus-service.yml -n monitoring
service/prometheus-service created
[root@k8s-master ~]# kubectl get svc -n monitoring
NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
prometheus-service   NodePort   10.108.59.161   <none>        8080:30000/TCP   9s
[root@k8s-master ~]# 

你可以通过GUI访问它。访问http://<k8s-master的全局IP地址:30000>,你可以像下面这样访问它。

prometheus-yaml-1.jpg

你也可以指定指标并将其显示在图表上。

prometheus-yaml-2.jpg

Grafana的部署

接下来部署Grafana。根据之前创建的用于Prometheus的Deployment和Service文件,创建了用于Grafana的文件。修改的部分是名称和容器镜像,以及端口号大约。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: grafana-deployment
  namespace: monitoring
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: grafana-server
    spec:
      containers:
        - name: grafana
          image: grafana/grafana:latest
          #args:
          #  - "--config.file=/root/prometheus.yml"
          #  - "--storage.tsdb.path=/prometheus/"
          ports:
            - containerPort: 3000
apiVersion: v1
kind: Service
metadata:
  name: grafana-service
spec:
  selector: 
    app: grafana-server
  type: NodePort
  ports:
    - port: 8100
      targetPort: 3000
      nodePort: 30020

那么就部署吧。

[root@k8s-master ~]# kubectl create -f grafana-deployment.yml -n monitoring
deployment.extensions/grafana-deployment created
[root@k8s-master ~]# kubectl get pods -n monitoring
NAME                                     READY   STATUS    RESTARTS   AGE
grafana-deployment-75d8d6dcc5-hkwt7      1/1     Running   0          11s
prometheus-deployment-5cc78d984f-b5pxw   1/1     Running   0          10m
[root@k8s-master ~]# kubectl create -f grafana-service.yml -n monitoring
service/grafana-service created
[root@k8s-master ~]# kubectl get svc -n monitoring
NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
grafana-service      NodePort   10.102.56.76    <none>        8100:30020/TCP   11s
prometheus-service   NodePort   10.102.96.204   <none>        8080:30000/TCP   11m
[root@k8s-master ~]#

由于这一点,您现在可以使用Grafana。请通过GUI访问http://<k8s-master的全局IP地址:30020>。通过登录页面进行相同的设置后,您将看到以下的Dashboard显示。

prometheus-yaml-3.jpg

总结和意见

    • binary: 公式ページが推奨?している手順だけあって、非常に簡単に起動ができます。設定ファイルも比較的わかりやすく、ターゲットの追加も簡単です。

 

    yaml: yamlファイルの準備ができさえすればとても簡単にできますが、yamlファイルの準備がとても大変です。

我本来想在YAML文件中启动Node Exporter并进行度量的捕获,但是无论是写法有误还是其他原因,都无法成功(虽然部署成功了,但最终无法获取度量)。我将继续调查YAML文件的写法。从个人角度来看,从二进制文件执行似乎更容易,但考虑到灵活性和配置管理等因素,使用YAML进行部署更为方便。

请参考以下链接

尝试用Grafana来显示Prometheus的数据图表
试一试使用Prometheus的file_sd_configs
关于Kubernetes的RBAC
在Prometheus中监视所有Kubernetes节点的方法
以容器方式启动Prometheus的方法

广告
将在 10 秒后关闭
bannerAds