在Kubernetes监视系列的第一部分中,我们讨论了如何将Kubernetes监视体系结构划分为系统组件的核心度量标准管道和基于自定义度量标准API的监视管道。基于自定义指标API的完整监视管道可以处理各种类型的指标(核心指标和非核心指标),这使其非常适合监视集群组件和集群中运行的用户应用程序。
存在许多用于监视Kubernetes集群的解决方案。最受欢迎的是Heapster,Prometheus和许多专有的应用程序性能管理(APM)供应商,例如Sysdig,Datadog或Dynatrace。
在本文中,我们将讨论Prometheus,因为它是对Kubernetes具有本机支持的开源软件。用Prometheus监视Kubernetes集群是自然的选择,因为默认情况下许多Kubernetes组件都附带Prometheus格式指标,因此Prometheus可以轻松发现它们。我们将概述Prometheus架构,并引导您配置和部署该架构,以监视示例应用程序,该示例应用程序采用Prometheus格式的指标。让我们开始吧!
什么是普罗米修斯?
Prometheus是最初由SoundCloud在2012年开发的开源监视和警报工具包。此后,该平台吸引了一个充满活力的开发人员和用户社区。 Prometheus现在已紧密集成到云原生生态系统中,并且对容器和Kubernetes具有本地支持。
在生产环境中部署Prometheus时,您会获得许多有用的功能和好处:
多维数据模型
Prometheus将所有数据存储为通过度量标准名称和键/值对标识的时间序列。数据格式如下:
1 |
<metric name>{<label name>=<label value>, …} |
例如,使用这种格式,我们可以像这样向/ messages端点表示HTTP POST请求的总数:
1 |
api_http_requests_total{method=”POST”, handler=”/messages”} |
这种方法类似于Kubernetes用标签组织数据的方式。 Prometheus数据模型有助于灵活且准确的时间序列,如果您的数据是高维数据,则特别有用。
灵活的查询语言
Prometheus随附了PromQL,PromQL是一种利用数据的高维度的功能查询语言。它允许用户选择,查询和汇总Prometheus收集的指标,为随后的分析和可视化做准备。 PromQL对时间序列有强大的处理能力,因为它对复杂数据类型(例如,即时矢量和范围矢量)以及简单的标量和字符串数据类型具有本地支持。
指标收集的有效拉模型
Prometheus通过基于HTTP的拉模型收集指标。这种方法使将应用程序度量标准传送到Prometheus非常简单。特别是,您无需明确地将指标推入Prometheus。您需要做的就是在应用程序中公开一个Web端口,并设计一个REST API终结点,以公开Prometheus格式指标。如果您的应用程序没有Prometheus格式度量标准,则可以使用多个度量标准导出程序来帮助您将其转换为原生Prometheus格式。创建/ metrics端点后,Prometheus将使用其功能强大的自动发现插件来收集,过滤和聚合指标。 Prometheus为包括Kubernetes,Open Stack,GCE,AWS EC2,Zookeeper Serverset等在内的许多指标提供程序提供了良好的支持。
发达的生态系统
Prometheus具有完善的组件和工具生态系统,包括用于检测应用程序代码的各种客户端库,将数据转换为Prometheus格式的专用导出器,AlertManagers,Web UI等。
高效的自动发现功能以及对容器和Kubernetes的出色支持,使Prometheus成为监视Kubernetes应用程序和集群组件的理想选择。在本教程中,我们将监视一个简单的Web应用程序,该应用程序将导出Prometheus格式的指标。我们使用了来自Go客户端库的示例应用程序,该应用程序导出了某些服务的虚假RPC延迟。为了在Kubernetes集群中部署该应用程序,我们使用Docker将其容器化并推送到Docker Hub存储库。
要完成下面使用的示例,您需要满足以下先决条件:
正在运行的Kubernetes集群 有关使用Supergiant部署Kubernetes集群的更多信息,请参见Supergiant文档。 或者,您可以使用Minikube在本地系统上安装单节点Kubernetes集群。
安装并配置为与集群通信的kubectl命令行工具。 在这里查看如何安装kubectl。
步骤1:为Prometheus启用RBAC
我们需要向Prometheus授予一些权限,以访问群集中运行的Pod,端点和服务。 我们可以通过定义RBAC策略的ClusterRole资源来执行此操作。 在ClusterRole清单中,我们列出了Prometheus操纵(读/写)各种集群资源的各种权限。 让我们看一下以下清单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - nodes - services - endpoints - pods verbs: ["get", "list", "watch"] - apiGroups: [""] resources: - configmaps verbs: ["get"] - nonResourceURLs: ["/metrics"] verbs: ["get"] |
上面的清单向Prometheus授予了以下群集范围的权限:
读取和观看对Pod,节点,服务和端点的访问。
读取对ConfigMap的访问权限
对非资源网址(例如,提供Prometheus格式指标的/ metrics URL)的读取访问权限。
除了ClusterRole之外,我们还需要为Prometheus创建一个ServiceAccount以在群集中表示其身份
1 2 3 4 |
apiVersion: v1 kind: ServiceAccount metadata: name: prometheus |
最后,我们需要使用ClusterRoleBinding资源绑定ServiceAccount和ClusterRole。 ClusterRoleBinding允许将用户,组或服务帐户列表与特定角色相关联。
1 2 3 4 5 6 7 8 9 10 11 12 |
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: prometheus namespace: default |
请注意,roleRef.name应该与第一步中创建的ClusterRole的名称匹配,而subject.name应该与第二步中创建的ServiceAccount的名称匹配。
我们将批量创建这些资源,因此将以上清单放入一个文件(例如rbac.yml),并用—分隔每个清单。 然后运行:
1 2 3 4 |
kubectl create -f rbac.yml clusterrolebinding.rbac.authorization.k8s.io “prometheus” created clusterrole.rbac.authorization.k8s.io “prometheus” created serviceaccount “prometheus” created |
步骤2:部署Prometheus
下一步是配置Prometheus。 该配置将包含刮擦目标和Kubernetes自动发现设置的列表,这些设置将允许Prometheus自动检测附带指标的应用程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
global: scrape_interval: 15s # By default, scrape targets every 15seconds. # Attach these labels to any time series or alerts when #communicating with external systems (federation, remote storage, #Alertmanager). external_labels: monitor: 'codelab-monitor' # Scraping Prometheus itself scrape_configs: - job_name: 'prometheus' scrape_interval: 5s static_configs: - targets: ['localhost:9090'] - job_name: 'kubernetes-service-endpoints' kubernetes_sd_configs: - role: endpoints relabel_configs: - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] action: replace target_label: kubernetes_name |
如您所见,配置包含两个主要部分:全局配置和抓取配置。全局部分包括在所有配置上下文中有效的参数。在本节中,我们定义15秒的刮擦间隔和外部标签。
反过来,scrape config部分定义了Prometheus要观看的作业/目标。在这里,您可以覆盖全局值,例如刮擦间隔。在每个作业部分,您还可以提供Prometheus可以收听的目标端点。如您所知,Kubernetes服务和部署是动态的。因此,在运行它们之前我们无法知道它们的URL。幸运的是,Prometheus自动发现功能可以解决此问题。
Prometheus附带了我们在第二个作业定义中使用的名为kubernetes_sd_configs的Kubernetes自动发现插件。我们将kubernetes_sd_configs设置为监视提供Prometheus格式指标的服务端点。我们还包括一些重新标记规则,用于用自定义值替换冗长的Kubernetes名称和标签,以简化监控。在本教程中,我们仅针对服务端点,但是您可以配置kubernetes_sd_configs来监视Kubernetes集群中的节点,吊舱和任何其他资源。
到目前为止,我们仅提到了Prometheus支持的一些配置参数。您可能还对其他一些内容感兴趣,例如:
scrape_timeout —刮取请求超时之前需要花费的时间。
basic_auth用于为每个抓取请求设置“授权”标头。
Consul,Amazon EC2,GCE等的服务特定的自动发现配置。
有关可用配置选项的完整列表,请参见Prometheus官方文档。
让我们将以上配置保存在prometheus.yml文件中,并使用以下命令创建ConfigMap:
1 2 |
kubectl create configmap prometheus-config —-from-file prometheus.yml configmap “prometheus-config” created |
接下来,我们将使用Docker Hub存储库中的容器映像来部署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 |
apiVersion: apps/v1 kind: Deployment metadata: name: prometheus-deployment spec: replicas: 2 selector: matchLabels: app: prometheus template: metadata: labels: app: prometheus spec: containers: - name: prometheus-cont image: prom/prometheus volumeMounts: - name: config-volume mountPath: /etc/prometheus/prometheus.yml subPath: prometheus.yml ports: - containerPort: 9090 volumes: - name: config-volume configMap: name: prometheus-config serviceAccountName: prometheus |
总结此清单的作用:
启动两个在端口9090上侦听的Prometheus副本。
将先前创建的ConfigMap挂载到/etc/prometheus/prometheus.yml的默认Prometheus配置路径中
将Prometheus服务帐户与部署相关联以授予所需的权限。
让我们将清单保存在prometheus-deployment.yml中并创建部署:
1 2 |
kubectl create -f prometheus-deployment.yaml deployment.extensions “prometheus-deployment” created |
要访问Prometheus Web界面,我们还需要将部署作为服务公开。 我们使用了NodePort服务类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
kind: Service apiVersion: v1 metadata: name: prometheus-service spec: selector: app: prometheus ports: - name: promui nodePort: 30900 protocol: TCP port: 9090 targetPort: 9090 type: NodePort |
让我们创建服务,将清单保存在prometheus-service.yaml中,然后运行以下命令:
1 2 |
kubectl create -f prometheus-service.yaml service “prometheus-service” created |
或者,您可以从终端公开部署。 这样,您无需定义服务清单:
1 2 |
kubectl expose deployment prometheus-deployment --type=NodePort --name=prometheus-service service "prometheus-service" exposed |
部署公开后,您可以访问Prometheus Web界面。 如果您使用的是Minikube,则可以通过运行带有–url标志的minikube服务来找到Prometheus UI URL:
1 2 |
minikube service prometheus-service --url http://192.168.99.100:30900 |
部署我们的测试指标应用程序后,记下URL以访问Prometheus UI。
步骤3:部署示例应用程序传送RPC延迟指标
现在已部署了Prometheus,因此我们准备为其提供一些指标。 让我们在/ metrics REST端点上部署示例应用服务指标。 以下是我们使用的部署清单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
apiVersion: apps/v1 kind: Deployment metadata: name: rpc-app-deployment labels: app: rpc-app spec: replicas: 2 selector: matchLabels: app: rpc-app template: metadata: labels: app: rpc-app spec: containers: - name: rpc-app-cont image: supergiantkir/prometheus-test-app ports: - name: web containerPort: 8081 |
此部署清单很容易解释。 部署后,该应用将向/ metrics端点发送随机RPC延迟数据。 如果您喜欢使用自己的名称,请确保所有标签和标签选择器彼此匹配。
继续并创建部署:
1 2 |
kubectl create -f rpc-app-deployment.yaml deployment.apps “rpc-app-deployment” created |
您还记得,我们将Prometheus配置为监视服务端点。 因此,我们需要将应用程序的部署公开为服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
apiVersion: v1 kind: Service metadata: name: rpc-app-service labels: app: rpc-app spec: ports: - name: web port: 8081 targetPort: 8081 protocol: TCP selector: app: rpc-app type: NodePort |
为了清楚起见,我们将spec.ports []。targetPort的值设置为与spec.ports []。port相同,尽管如果没有为targetPort提供值,Kubernetes会自动将其设置为。
与Prometheus服务一样,您可以从清单创建服务,也可以在终端中内联公开它。 如果选择清单,请运行:
1 2 |
kubectl create -f rpc-app-service.yaml service “rpc-app-service” created |
如果喜欢命令行方式,可以用:
1 2 |
kubectl expose deployment rpc-app-deployment --type=NodePort --name=rpc-app-service service "rpc-app-service" exposed |
验证是否成功:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
kubectl describe svc rpc-app-service Name: rpc-app-service Namespace: default Labels: app=rpc-app Annotations: <none> Selector: app=rpc-app Type: NodePort IP: 10.110.41.174 Port: web 8081/TCP TargetPort: 8081/TCP NodePort: web 32618/TCP Endpoints: 172.17.0.10:8081,172.17.0.9:8081 Session Affinity: None External Traffic Policy: Cluster Events: <none> |
如您所见,已分配NodePort,并且已将部署的端点成功添加到服务中。 现在,我们可以在指定的IP和端口上访问应用的指标终结点。 如果您使用的是Minikube,则首先需要使用以下命令获取服务的IP:
1 2 |
minikube service rpc-app-service --url http://192.168.99.100:30658 |
curl 获取metrics:
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 |
curl http://192.168.99.100:30658/metrics # TYPE promhttp_metric_handler_requests_total counter promhttp_metric_handler_requests_total{code="200"} 0 promhttp_metric_handler_requests_total{code="500"} 0 promhttp_metric_handler_requests_total{code="503"} 0 # HELP rpc_durations_histogram_seconds RPC latency distributions. # TYPE rpc_durations_histogram_seconds histogram rpc_durations_histogram_seconds_bucket{le="-0.00099"} 0 rpc_durations_histogram_seconds_bucket{le="-0.00089"} 0 rpc_durations_histogram_seconds_bucket{le="-0.0007899999999999999"} 0 rpc_durations_histogram_seconds_bucket{le="-0.0006899999999999999"} 2 rpc_durations_histogram_seconds_bucket{le="-0.0005899999999999998"} 18 rpc_durations_histogram_seconds_bucket{le="-0.0004899999999999998"} 59 rpc_durations_histogram_seconds_bucket{le="-0.0003899999999999998"} 236 rpc_durations_histogram_seconds_bucket{le="-0.0002899999999999998"} 669 rpc_durations_histogram_seconds_bucket{le="-0.0001899999999999998"} 1514 rpc_durations_histogram_seconds_bucket{le="-8.999999999999979e-05"} 2959 rpc_durations_histogram_seconds_bucket{le="1.0000000000000216e-05"} 4727 rpc_durations_histogram_seconds_bucket{le="0.00011000000000000022"} 6562 rpc_durations_histogram_seconds_bucket{le="0.00021000000000000023"} 8059 rpc_durations_histogram_seconds_bucket{le="0.0003100000000000002"} 8908 rpc_durations_histogram_seconds_bucket{le="0.0004100000000000002"} 9350 rpc_durations_histogram_seconds_bucket{le="0.0005100000000000003"} 9514 rpc_durations_histogram_seconds_bucket{le="0.0006100000000000003"} 9570 rpc_durations_histogram_seconds_bucket{le="0.0007100000000000003"} 9585 rpc_durations_histogram_seconds_bucket{le="0.0008100000000000004"} 9588 rpc_durations_histogram_seconds_bucket{le="0.0009100000000000004"} 9588 rpc_durations_histogram_seconds_bucket{le="+Inf"} 9588 rpc_durations_histogram_seconds_sum 0.11031870987310399 rpc_durations_histogram_seconds_count 9588 # HELP rpc_durations_seconds RPC latency distributions. # TYPE rpc_durations_seconds summary rpc_durations_seconds{service="exponential",quantile="0.5"} 6.43688069700151e-07 rpc_durations_seconds{service="exponential",quantile="0.9"} 2.3703557539528334e-06 rpc_durations_seconds{service="exponential",quantile="0.99"} 4.491775587389532e-06 rpc_durations_seconds_sum{service="exponential"} 0.014317520025277117 rpc_durations_seconds_count{service="exponential"} 14369 rpc_durations_seconds{service="normal",quantile="0.5"} 5.97571029483546e-06 rpc_durations_seconds{service="normal",quantile="0.9"} 0.0002795950678545625 rpc_durations_seconds{service="normal",quantile="0.99"} 0.0004838671111576318 rpc_durations_seconds_sum{service="normal"} 0.11031870987310399 rpc_durations_seconds_count{service="normal"} 9588 rpc_durations_seconds{service="uniform",quantile="0.5"} 8.961255876119688e-05 rpc_durations_seconds{service="uniform",quantile="0.9"} 0.0001764412468147929 rpc_durations_seconds{service="uniform",quantile="0.99"} 0.00019807911315607854 rpc_durations_seconds_sum{service="uniform"} 0.715789691590982 rpc_durations_seconds_count{service="uniform"} 7195 |
如您所见,该请求返回了许多Prometheus格式的RPC延迟指标。 每个度量标准的格式为<度量标准名称> {<标签名称> = <标签值>,…},并且具有唯一值。
由于Prometheus Kubernetes自动发现功能,我们可以期望Prometheus自动发现了该应用程序并开始提取这些指标。 让我们访问Prometheus网络界面进行验证。 使用您的Prometheus服务IP和在步骤2中获得的NodePort来访问Prometheus UI。
如果您转到/ targets端点,则会看到当前Prometheus目标的列表。 由于我们已将Prometheus配置为监视所有服务端点,因此可能会有很多目标。 在其中,您会找到标有app =” rpc-app”的目标。 那是我们的应用程序。 您还可以找到其他标签并查看上一次获取的时间。
此外,您还可以在“状态”->“配置”选项卡下查看当前的Prometheus配置:
最后,我们可以可视化示例应用程序生成的RPC时间序列。 为此,请转到图表标签,您可以在其中选择要显示的指标。
在上图中,我们可视化了rpc_durations_histogram_seconds_bucket指标。您还可以使用其他RPC指标和本机Prometheus指标。 Web界面还支持Prometheus查询语言PromQL,以选择和汇总所需的指标。 PromQL具有丰富的功能语义,允许使用时间序列,实例和范围向量,标量和字符串。要了解有关PromQL的更多信息,请查阅官方文档。
结论
而已!我们已经学习了如何配置Prometheus来监视服务于Prometheus格式指标的应用程序。 Prometheus具有复杂的配置语言和设置,因此我们只是从头开始。尽管Prometheus是一个功能强大的工具,但是如果没有对特定领域的语言和配置的充分了解,配置和运行它可能会面临挑战。为了填补这一空白,在下一个教程中,我们将研究使用Prometheus Operator配置和管理Prometheus实例,Prometheus Operator是一个有用的软件管理工具,旨在简化使用Prometheus监视应用程序的过程。请继续关注我们的博客,以了解更多信息!