cloudvtech 2019-07-01
本实践指南中我们将看到如何部署Prometheus Operator到Kubernetes集群中,以及如何增加一个外部服务到Prometheus的targets列表。
在我的上个项目中,我们决定使用Prometheus Operator作为我们的监控和报警工具。我们的应用运行于Kubernetes集群中,但是除此我们还有个外部应用 — 一个GPU机器。
Kubernetes根本感知不到这个服务,相关服务通过HTTP请求连接该服务。我想跟你们分享下我使用Prometheus Operator的经验以及如何定制它来监控外部服务。
Prometheus及其社区有一个非常活跃的开发者群体和用户社区。它现在是一个独立的开源项目,独立于任何公司进行维护。Prometheus已经成为Kubernetes和Docker领域监控和报警的事实标准。它提供了到目前为止最详细和可操作的监控指标和分析。在最新的主要版本2.0版本(访问下载页面查看当前最新版)Prometheus的性能有了显著提升,并且现在它在高负载和并发下表现良好。除此以外你可以获得世界领先的开源项目的所有好处。Prometheus可以免费使用,并可以轻松覆盖很多使用场景。
2016年年末,CoreOs引入了Operator 模式,并发布了Prometheus Operator 作为Operator模式的工作示例。Prometheus Operator自动创建和管理Prometheus监控实例。
Prometheus Operator的任务是使得在Kubernetes运行Prometheus仅可能容易,同时保留可配置性以及使Kubernetes配置原生。 https://coreos.com/operators/...Prometheus Operator使我们的生活更容易——部署和维护。
为了理解这个问题,我们首先需要了解Prometheus Operator得工作原理。

Prometheus Operator架构图. 来源:prometheus-operator
我们成功部署 Prometheus Operator后可以看到一个新的CRDs(Custom Resource Defination):
Prometheus deployment。Operator根据定义自动创建Prometheusscrape配置。Alertmanager deployment。当服务新版本更新时,将会常见一个新Pod。Prometheus监控k8s API,因此当它检测到这种变化时,它将为这个新服务(pod)创建一组新的配置。
Prometheus Operator使用一个CRD,叫做ServiceMonitor将配置抽象到目标。
下面是是个ServiceMonitor的示例:
apiVersion: monitoring.coreos.com/v1alpha1
kind: ServiceMonitor
metadata:
name: frontend
labels:
tier: frontend
spec:
selector:
matchLabels:
tier: frontend
endpoints:
- port: web # works for different port numbers as long as the name matches
interval: 10s # scrape the endpoint every 10 seconds这仅仅是定义一组服务应该如何被监控。现在我们需要定义一个包含了该ServiceMonitor的Prometheus实例到其配置:
apiVersion: monitoring.coreos.com/v1alpha1
kind: Prometheus
metadata:
name: prometheus-frontend
labels:
prometheus: frontend
spec:
version: v1.3.0
# Define that all ServiceMonitor TPRs with the label `tier = frontend` should be included
# into the server's configuration.
serviceMonitors:
- selector:
matchLabels:
tier: frontend现在Prometheus将会监控每个带有tier: frontend label的服务。
想我说讲的那样,我们想监控一个外部服务,在这个GPU机器上我启动一个node-exporter:
docker run -d -p 9100:9100 node-exporter
我们想要发送node-exportor数据到Prometheus。
我们应该如何为一个既没有Pod也没有Service的服务创建ServiceMonitor呢?
为了解决这个问题,我决定深入研究Kubernetes如何处理Pod和Service的关系。
在Kubernetes官方文档Service页面,我发现了一下内容:
Kubernetes原生应用,Kubernetes提供了一个简单Endpoints API,当服务中的一组pod发生更改时,该API就会更新。对于非本机应用程序,Kubernetes提供了一个基于虚拟ip的服务桥接器,服务将重定向到后端pod。这就是我想要的解决方案!我需要创建一个自定义EndPoint定义我外部服务匹配Service和最终的ServiceMonitor定义,这样Prometheus就会把它增加到targets列表。
Prometheus Operator先决条件:
Kubernetes命令和组件基本知识Kubernetes集群Helm准备好动手操作:
idob ~(☸|kube.prometheus:default): ▶ helm repo add coreos https://s3-eu-west-1.amazonaws.com/coreos-charts/stable/ idob ~(☸|kube.prometheus:default): ▶ helm install coreos/prometheus-operator --name prometheus-operator --namespace monitoring
到目前为止,我们已经在我们的集群中安装了Prometheus Operator的TPR。
现在我们来部署Prometheus,Alertmanager和Grafana。
Helm Charts时,我更倾向于创建一个独立的value.yaml文件将包含我所有自定义的变更。这么做使我和同事为后期的变化和修改更容易。idob ~(☸|kube.prometheus:default):
▶ helm install coreos/kube-prometheus --name kube-prometheus \
-f my_changes/prometheus.yaml \
-f my_changes/grafana.yaml \
-f my_changes/alertmanager.yaml就是这样,很简单,对吧?
要检查一切是否运行正常你应该这么做:
idob ~(☸|kube.prometheus:default): ▶ k -n monitoring get po NAME READY STATUS RESTARTS AGE alertmanager-kube-prometheus-0 2/2 Running 0 1h kube-prometheus-exporter-kube-state-68dbb4f7c9-tr6rp 2/2 Running 0 1h kube-prometheus-exporter-node-bqcj4 1/1 Running 0 1h kube-prometheus-exporter-node-jmcq2 1/1 Running 0 1h kube-prometheus-exporter-node-qnzsn 1/1 Running 0 1h kube-prometheus-exporter-node-v4wn8 1/1 Running 0 1h kube-prometheus-exporter-node-x5226 1/1 Running 0 1h kube-prometheus-exporter-node-z996c 1/1 Running 0 1h kube-prometheus-grafana-54c96ffc77-tjl6g 2/2 Running 0 1h prometheus-kube-prometheus-0 2/2 Running 0 1h prometheus-operator-1591343780-5vb5q 1/1 Running 0 1h
我们来访问下Prometheus UI看一下targets页面:
idob ~(☸|kube.prometheus:default): ▶ k -n monitoring port-forward prometheus-kube-prometheus-0 9090 Forwarding from 127.0.0.1:9090 -> 9090
浏览器展示如下:

我们可以看到一堆已经默认定义的targets,我们的目标是添加新的GPU Targets。
我们需要找到当前Prometheus正在寻找的label并使用它。(我们应该创建一个新的Prometheus实例并配置它只搜索我们的label,但我认为再多搜索一个targe就太过分了)
idob ~(☸|kube.prometheus:default):
▶ k -n monitoring get prometheus kube-prometheus -o yaml
apiVersion: monitoring.coreos.com/v1
kind: Prometheus
metadata:
labels:
app: prometheus
chart: prometheus-0.0.14
heritage: Tiller
prometheus: kube-prometheus
release: kube-prometheus
name: kube-prometheus
namespace: monitoring
spec:
...
baseImage: quay.io/prometheus/prometheus
serviceMonitorSelector:
matchLabels:
prometheus: kube-prometheus # <--- BOOM
....一切就绪,我们已经为我们的target创建必备资源做好了准备。
apiVersion: v1
kind: Endpoints
metadata:
name: gpu-metrics
labels:
k8s-app: gpu-metrics
subsets:
- addresses:
- ip: <gpu-machine-ip>
ports:
- name: metrics
port: 9100
protocol: TCP正如我们所决定的,我们正在创建自己的静态EndPoint,我们提供了IP,Port 以及只描述我们GPU服务的label: k8s-app: gpu-exporter。
apiVersion: v1
kind: Service
metadata:
name: gpu-metrics-svc
namespace: monitoring
labels:
k8s-app: gpu-metrics
spec:
type: ExternalName
externalName: <gpu-machine-ip>
clusterIP: ""
ports:
- name: metrics
port: 9100
protocol: TCP
targetPort: 9100apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: gpu-metrics-sm
labels:
k8s-app: gpu-metrics
prometheus: kube-prometheus
spec:
selector:
matchLabels:
k8s-app: gpu-metrics
namespaceSelector:
matchNames:
- monitoring
endpoints:
- port: metrics
interval: 10s
honorLabels: true最重要的部分是label — 我们必须分配label: prometheus: kube-prometheus 因此Prometheus服务器将在matchlabel部分查找此目标和第二个标签,以便ServiceMonitor只指向我们的gpu-export。
我们来apply所有:
idob ~(☸|kube.prometheus:default):
▶ k apply -f gpu-exporter-ep.yaml \
-f gpu-exporter-svc.yaml \
-f gpu-exporter-sm.yaml现在已经切换到Prometheus UI,如果我们看目标页面,我们应该看到我们的GPU在列表中:

就是这样。如你所见部署Prometheus Operator相当容易并且现在我希望你可以简单的监控你所有服即使他们已存在于你Kubetnetes集群以外。从我的经验来看Prometheus Operator工作相当完美,我强烈建议使用它。
我希望你喜欢它,请不要犹豫给反馈和分享你自己的经验。