使用 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>)。
当您从上述画面中访问http://<k8s-master的全局IP地址:9090/metrics>时,将显示以下指标列表。您还可以在屏幕顶部的选项卡中选择访问。
在《入门指南》中也提供了一些获取指标的示例。在这里,我们将获取一个名为prometheus_target_interval_length_seconds的度量指标。
启动 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.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'] #ポート番号を変更する
现在能够使用先前无法使用的指标。这里展示了一个名为node_cpu_second_total的图表。
您可以通过 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'] #ターゲットを追加する
启动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 Dashboard
只需更改图表的标题和细节设置等,即可完成图表。
【补充】据这篇文章所述,似乎是因为无法获取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>,你可以像下面这样访问它。
你也可以指定指标并将其显示在图表上。
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显示。
总结和意见
-
- binary: 公式ページが推奨?している手順だけあって、非常に簡単に起動ができます。設定ファイルも比較的わかりやすく、ターゲットの追加も簡単です。
- yaml: yamlファイルの準備ができさえすればとても簡単にできますが、yamlファイルの準備がとても大変です。
我本来想在YAML文件中启动Node Exporter并进行度量的捕获,但是无论是写法有误还是其他原因,都无法成功(虽然部署成功了,但最终无法获取度量)。我将继续调查YAML文件的写法。从个人角度来看,从二进制文件执行似乎更容易,但考虑到灵活性和配置管理等因素,使用YAML进行部署更为方便。
请参考以下链接
尝试用Grafana来显示Prometheus的数据图表
试一试使用Prometheus的file_sd_configs
关于Kubernetes的RBAC
在Prometheus中监视所有Kubernetes节点的方法
以容器方式启动Prometheus的方法