kubernetes-yaml/learn/learn-kubernetes-master/chapter14.md

477 lines
36 KiB
Markdown
Raw Normal View History

# 第十四章 使用 Prometheus 监控应用程序和 Kubernetes
监控是日志的伙伴:监视系统告诉您某些地方出了问题然后您可以深入日志以找出详细信息。与日志记录一样您希望有一个集中的系统来收集和可视化关于所有应用程序组件的指标。Kubernetes中已建立的监控方法使用另一个CNCF项目:Prometheus这是一个收集和存储指标的服务器应用程序。在本章中您将学习如何在Kubernetes中部署一个共享监控系统使用 dashboard 面板显示单个应用程序和整个集群的健康状况。
Prometheus 在许多平台上运行但它特别适合Kubernetes。您可以在一个Pod中运行Prometheus该Pod可以访问Kubernetes API服务器然后Prometheus查询API以找到它需要监视的所有目标。
当你部署新的应用程序时你不需要做任何设置更改——prometheus会自动发现它们并开始收集指标。Kubernetes的应用程序也特别适合Prometheus。在本章中你将看到如何很好地利用sidecar模式因此每个应用程序都可以为Prometheus提供一些指标即使应用程序本身还没有准备好。
## 14.1 Prometheus 如何监控 Kubernetes 的工作负载
Prometheus 中的度量完全是通用的:您想要监视的每个组件都有一个HTTP端点该端点返回对该组件重要的所有值。web服务器包含它所服务的请求数量的指标Kubernetes节点包含可用内存数量的指标。Prometheus并不关心度量标准中的内容;它只存储组件返回的所有内容。对普罗米修斯来说,重要的是它需要收集的目标列表。
图14.1显示了如何使用Prometheus的内置服务发现在Kubernetes中工作。
![图14.1](./images/Figure14.1.png)
<center>图14.1普罗米修斯使用拉模型收集指标,自动找到目标</center>
本章的重点是让 Prometheus 与 Kubernetes 很好地合作为您提供一个动态监控系统当您的集群扩展到更多的节点运行更多的应用程序时该系统仍能保持工作。我不会详细介绍如何在应用程序中添加监控或者应该记录哪些指标电子书的附录B是《Learn Docker in a Month of lunch》中的“添加可观察性与容器化监控”一章它将为您提供额外的细节。
我们将从启动普罗米修斯开始。Prometheus服务器是一个单独的组件负责服务发现、指标收集和存储它有一个基本的web UI您可以使用它来检查系统的状态并运行简单的查询。
现在试试吧将Prometheus部署在专用的监视命名空间中配置为在 test 命名空间中查找应用程序(test 命名空间还不存在)。
```
# 切换到章节目录:
cd ch14
# 创建 Prometheus Deployment and ConfigMap:
kubectl apply -f prometheus/
# 等待 Prometheus to start:
kubectl wait --for=condition=ContainersReady pod -l app=prometheus -n kiamol-ch14-monitoring
# 获取 web UI 地址:
kubectl get svc prometheus -o jsonpath='http://{.status.loadBalancer.ingress[0].*}:9090' -n kiamol-ch14-monitoring
# 访问 UI, 查看 /targets page
```
Prometheus 称 metrics 收集为 scraping。当您访问 Prometheus UI 时,您将看到没有抓取目标,尽管有一个名为 testpods 的类别它列出了零目标。图14.2显示了我的输出。test-pods 的名称来自您在ConfigMap中部署的Prometheus配置Pod从中读取该配置。
![图14.2](./images/Figure14.2.png)
<center>图14.2 目前还没有目标但Prometheus将继续检查Kubernetes API以寻找新的pod </center>
配置 Prometheus 以在 Kubernetes 中寻找目标是相当简单的尽管术语一开始令人困惑。Prometheus 使用作业来定义一组相关的目标,这些目标可以是应用程序的多个组件。抓取配置可以简单到一个静态域名列表(Prometheus轮询该列表以获取指标)也可以使用动态服务发现。清单14.1 向 Prometheus 展示了test-pods作业配置的开头它使用Kubernetes API进行服务发现。
> 清单 14.1 prometheus-config.yaml, 使用Kubernetes scrape 配置
```
scrape_configs: # 这是 configmap 中的 yaml.
- job_name: 'test-pods' # 用于 test apps
kubernetes_sd_configs: # 从 kubernetes API 查找目标
- role: pod # 搜寻 Pods
relabel_configs: # 应用这些过滤规则
- source_labels:
- __meta_kubernetes_namespace
action: keep # 只包含本章测试命名空间的 pods
regex: kiamol-ch14-test
```
需要解释的是 relabel_configs 部分。Prometheus使用标签存储度量标签是标识源系统和其他相关信息的键值对。您将在查询中使用标签来选择或聚合指标还可以在将指标存储到Prometheus之前使用它们来过滤或修改指标。这是重新标签从概念上讲它类似于Fluent bit中的数据管道——您有机会丢弃不想要的数据并重新塑造您想要的数据。正则表达式在 Prometheus 中也出现了不必要的复杂问题,但很少需要进行更改。你在重新标签阶段设置的管道应该足够通用,适用于所有应用程序。配置文件中的全管道应用如下规则:
- 只包含命名空间 kiamol-ch14-test 中的Pods。
- 使用 Pod 名称作为Prometheus实例标签的值。
- 使用 Pod 元数据中的app标签作为Prometheus作业标签的值。
- 在 Pod 元数据中使用可选注解配置抓取目标。
这种方法是由约定驱动的——只要您的应用程序被建模以适应规则它们就会自动被选为监视目标。Prometheus使用规则来查找匹配的Pods对于每个目标它通过向/metrics路径发出HTTP GET请求来收集指标。Prometheus需要知道使用哪个网络端口因此Pod规范需要显式地包括容器端口。这是一个很好的实践因为它有助于记录应用程序的设置。让我们将一个简单的应用程序部署到test命名空间看看Prometheus用它做了什么。
现在试试吧,将时间检查应用程序部署到测试命名空间。该规格匹配所有的普罗米修斯 scrape 规则所以新的Pod应该被找到并添加为 scrape目标。
```
# 创建 test namespace 以及 timecheck Deployment:
kubectl apply -f timecheck/
# 等待 app 启动:
kubectl wait --for=condition=ContainersReady pod -l app=timecheck -n kiamol-ch14-test
# 刷新Prometheus界面中的 target 列表,并确认
# timecheck Pod然后浏览到/graph页面选择
# timecheck_total然后单击“执行”
```
我的输出如图14.3所示其中我打开了两个浏览器窗口以便您可以看到部署应用程序时发生了什么。普罗米修斯看到时间检查Pod被创建它符合重新标记阶段的所有规则所以它被添加为目标。普罗米修斯配置设置为每30秒检查一次目标。时间检查应用程序有一个/metrics端点它返回它写了多少时间检查日志的计数。当我在Prometheus中查询该指标时应用程序已经写入了22个日志条目。
![图14.3](./images/Figure14.3.png)
<center>图14.3 将应用程序部署到测试命名空间- prometheus找到它并开始收集指标. </center>
这里您应该认识到两个重要的事情:应用程序本身需要提供度量因为Prometheus只是一个收集器而那些度量代表应用程序实例的活动。时间检查应用程序不是一个web应用程序——它只是一个后台进程——所以没有服务将流量导向它。普罗米修斯在查询Kubernetes API时获得Pod的IP地址并直接向Pod发出HTTP请求。您也可以配置Prometheus来查询Services但是这样您就会得到一个目标它是跨多个Pod的负载均衡器并且您希望Prometheus独立地抓取每个Pod。
你可以使用Prometheus中的指标来增强仪表板显示应用程序的整体健康状况你可以汇总所有pod来获得标题值。您还需要能够向下钻取以查看pod之间是否有差异。这将帮助您确定某些实例是否执行不良并将反馈到您的运行状况检查中。我们可以放大时间检查应用程序看看在单个Pod级别收集的重要性。
现在试试吧添加另一个副本到时间检查应用程序。这是一个新的Pod符合普罗米修斯规则所以它将被发现并添加为另一个 scrape 目标。
```
# 缩放部署以添加另一个Pod:
kubectl scale deploy/timecheck --replicas 2 -n kiamol-ch14-test
# 等待新的 pod 启动:
kubectl wait --for=condition=ContainersReady pod -l app=timecheck -n kiamol-ch14-test
# 回到普罗米修斯,检查 target 列表,在 graph 页面,
# 执行timecheck_total和dotnet_total_memory_bytes的查询
```
在这个练习中,你会看到普罗米修斯发现了新的 pod并开始采集它。两个Pod记录相同的指标Pod名称被设置为每个指标上的标签。对timecheck_total指标的查询现在返回两个结果——每个Pod一个结果——在图14.4中可以看到一个Pod比另一个Pod完成了更多的工作。
![图14.4](./images/Figure14.4.png)
<center>图14.4 每个实例都记录自己的指标因此您需要从每个Pod收集数据。 </center>
时间检查计数器是在应用程序代码中显式捕获的度量。大多数语言都有一个Prometheus客户端库您可以将其插入到您的构建中。这些库允许您像这样捕获特定于应用程序的细节它们还收集有关应用程序运行时的一般信息。这是一个.net应用程序Prometheus客户端库记录运行时细节比如正在使用的内存和CPU数量以及正在运行的线程数量。在下一节中我们将运行一个分布式应用程序其中每个组件都公开Prometheus指标我们将看到当应用程序仪表板包括运行时性能和应用程序详细信息时它是多么有用。
## 14.2 监视使用 Prometheus 客户端库构建的应用程序
电子书的附录B介绍了如何向一个应用程序添加指标该应用程序显示了来自NASA“每日天文照片”(APOD)服务的图片。该应用程序的组件在Java、Go和Node.js中它们都使用Prometheus客户端库来公开运行时和应用程序指标。本章包括部署到test 命名空间的应用程序的Kubernetes清单因此所有应用程序Pods将被Prometheus发现。
现在试试吧将APOD应用程序部署到测试命名空间并确认应用程序的三个组件被添加为Prometheus目标。
```
# 部署 app:
kubectl apply -f apod/
# 等待启动成功:
kubectl wait --for=condition=ContainersReady pod -l app=apod-api -n kiamol-ch14-test
# 获取 app URL:
kubectl get svc apod-web -o jsonpath='http://{.status.loadBalancer.ingress[0].*}:8014' -n kiamol-ch14-test
# 访问 app, 然后刷新 Prometheus targets 界面
```
你可以在图 14.5 中看到我的输出其中有一个非常令人愉快的图像叫做林德斯暗星云1251。应用程序如预期的那样运行普罗米修斯已经发现了所有新的pod。在部署应用程序的30秒内你应该会看到所有新目标的状态都是正常的这意味着普罗米修斯已经成功地抓取了它们。
![图14.5](./images/Figure14.5.png)
<center>图14.5 APOD组件都有服务但它们仍然在Pod级别被抓取</center>
在这个练习中我还有两件重要的事情要指出。首先Pod规范都包括一个容器端口它说明应用程序容器正在监听端口80这就是Prometheus找到要抓取的目标的方法。web UI的Service实际上监听端口8014但是Prometheus直接访问Pod端口。其次API目标没有使用标准/度量路径因为Java客户机库使用不同的路径。我在Pod规范中使用了注释来说明正确的路径。
基于约定的发现很棒因为它消除了大量重复的配置和潜在的错误但并不是每个应用都符合约定。我们在普罗米修斯中使用的重标签管道为我们提供了一个很好的平衡。默认值适用于任何符合约定的应用程序但任何不符合约定的应用程序都可以用注释覆盖默认值。清单14.2显示了如何配置覆盖以设置度量的路径。
> 清单 14.2 prometheus-config.yaml, 使用 annotations 覆盖默认值
```
- source_labels: # 这个是 test-pods job 中的 relabel 配置.
- __meta_kubernetes_pod_annotationpresent_prometheus_io_path
- __meta_kubernetes_pod_annotation_prometheus_io_path
regex: true;(.*) # 如果 pod 具有一个名为 prometheus.io/path 的 annotation
target_label: __metrics_path__ #从 annotation 中获取设置 target path
```
这远没有看起来那么复杂。规则是这样的:如果 pod 有一个叫 prometheus.io/path 注释然后就使用该注释的值作为度量路径。Prometheus使用标签来完成这一切因此每个Pod注释都成为一个名称为meta_kubernetes_pod_annotation_<annotation-name>的标签并且有一个附带的标签名为meta_kubernetes_pod_annotationpresent_<annotation-name>您可以使用它来检查注释是否存在。任何使用自定义指标路径的应用程序都需要添加注释。清单14.3显示了APOD API。
> Listing 14.3 api.yaml, path annotation
```
template: # 这是 deployment 的 pod spec 配置
metadata:
labels:
app: apod-api # 在 prometheus 中用作 job 标签
annotations:
prometheus.io/path: "/actuator/prometheus" # 设置 metrics path
```
复杂性集中在 Prometheus 配置中应用程序清单非常容易指定覆盖。当您多使用一些重新标记规则时它们就不那么复杂了并且通常遵循完全相同的模式。完整的Prometheus配置包括类似的规则应用程序可以覆盖指标端口并选择完全退出抓取。
当你在读这篇文章的时候普罗米修斯一直在忙着抓取时间支票和APOD应用程序。看看Prometheus UI的Graph页面上的指标可以看到大约有200个指标正在被收集。UI非常适合运行查询并快速查看结果但你不能用它来构建一个仪表板在一个屏幕上显示应用程序的所有关键指标。为此您可以使用Grafana它是容器生态系统中的另一个开源项目由Prometheus团队推荐。
现在试试吧使用ConfigMaps部署Grafana它建立了与Prometheus的连接并包括APOD应用程序的仪表板。
```
# 在监控命名空间中部署Grafana:
kubectl apply -f grafana/
# 等待启动:
kubectl wait --for=condition=ContainersReady pod -l app=grafana -n
kiamol-ch14-monitoring
# 获取 dashboard url:
kubectl get svc grafana -o jsonpath='http://{.status.loadBalancer.ingress[0].*}:3000/d/kb5nhJAZk' -n kiamol-ch14-monitoring
# 浏览到URL;使用用户名kiamol和密码kiamol登录
```
图14.6所示的仪表板很小但它让您了解了如何将原始指标转换为系统活动的信息视图。仪表板由Prometheus查询驱动Grafana在后台运行该查询。每个组件都有一行其中包括运行时指标(处理器和内存使用)和应用程序指标(http请求和缓存使用)的混合。
![图14.6](./images/Figure14.6.png)
<center>图14.6应用程序仪表板提供了对性能的快速洞察。这些图表都是由Prometheus metrics提供的</center>
像这样的仪表板将是贯穿整个组织的共同努力。支持团队将设置他们需要看到的需求应用程序开发和运营团队确保应用程序捕获数据并在仪表板上显示它。就像我们在第13章中看到的日志系统一样这是一个由轻量级开源组件构建的解决方案因此开发人员可以在他们的笔记本电脑上运行与在生产环境中运行的相同的监控系统。这有助于在开发和测试中进行性能测试和调试。
使用Prometheus转移到集中监视将需要开发工作但是它可以是一个增量过程您从基本的度量开始并随着团队开始提出更多的需求而添加它们。我在本章的待办事项列表应用程序中添加了对普罗米修斯的支持这大约花了十几行代码。在Grafana中有一个简单的应用程序仪表板所以当你部署应用程序时你将能够看到一个仪表板的起点它将在未来的版本中得到改进。
现在试试吧,运行启用指标的待办事项列表应用程序并使用该应用程序生成一些指标。在Grafana中已经有一个仪表盘来可视化指标。
```
# 部署 app:
kubectl apply -f todo-list/
# 等待启动:
kubectl wait --for=condition=ContainersReady pod -l app=todo-web -n
kiamol-ch14-test
# 访问应用,插入待办项
# 然后在 windows 中运行脚本:
.\loadgen.ps1
# 或者 macOS/Linux:
chmod +x ./loadgen.sh && ./loadgen.sh
# 获取新的 dashboard 地址:
kubectl get svc grafana -o jsonpath='http://{.status.loadBalancer.ingress[0].*}:3000/d/Eh0VF3iGz' -n kiamol-ch14-monitoring
# 浏览 dashboard
```
仪表板上没有太多东西但它比没有仪表板的信息要多得多。它告诉你应用程序在容器内使用了多少CPU和内存创建任务的速率以及HTTP请求的平均响应时间。您可以在图14.7中看到我的输出,其中我添加了一些任务,并使用负载生成脚本发送了一些流量。
![图14.7](./images/Figure14.7.png)
<center>图14.7 一个由 Prometheus 客户端库和几行代码驱动的简单仪表板 </center>
所有这些指标都来自待办事项应用程序Pod。在这个版本中应用程序还有另外两个组件:一个用于存储的Postgres数据库和一个Nginx代理。这两个组件都没有对Prometheus的本地支持因此它们被排除在目标列表之外。否则普罗米修斯将继续尝试着获取度量标准并失败。对应用程序进行建模的人员的工作是了解一个组件不公开指标并指定应该排除它。清单14.4显示了使用一个简单注释完成的操作。
> 清单 14.4 proxy.yaml, 一个 pod spec 排除 监控
```
template: # 这是 deployment pod spec 配置
metadata:
labels:
app: todo-proxy
annotations: # 排除 target
prometheus.io/scrape: "false"
```
组件不需要对Prometheus提供本地支持并提供自己的度量端点以包含在监视系统中。Prometheus有自己的生态系统——除了可以用来向自己的应用程序添加指标的客户端库之外一整套 exporter 可以为第三方应用程序提取和发布指标。我们可以使用 exporter 为代理和数据库组件添加缺少的指标。
## 14.3 通过 metrics exporters 来监控第三方应用
大多数应用程序都以某种方式记录指标但较老的应用程序不会以Prometheus格式收集和公开它们。Exporters 是独立的应用程序了解目标应用程序如何进行监视并可以将这些指标转换为Prometheus格式。Kubernetes提供了完美的方式来运行一个exporter 与应用程序的每个实例使用 sidecar 容器。这就是我们在第7章中介绍的适配器模式。
Nginx和Postgres都有可用的 exporters 我们可以作为sidecars来运行以改善待办应用程序的监控仪表板。Nginx exporter 从Nginx服务器上的状态页面读取数据并将数据转换为Prometheus格式。记住Pod中的所有容器都共享网络命名空间因此exporter 容器可以在本地主机地址访问Nginx容器。exporter 为自定义端口上的指标提供了自己的HTTP端点因此完整的Pod spec 包括sidecar容器和指定指标端口的注释。清单14.5显示了关键部分。
> 清单 14.5 proxy-with-exporter.yaml, 添加 metrics exporter 容器
```
template: # Deployment 中的 pod spec
metadata:
labels:
app: todo-proxy
annotations:
prometheus.io/port: "9113" # 指定 metrics port
spec:
containers:
- name: nginx
# ... nginx spec 没有变化
- name: exporter # exporter 作为 sidecar 运行.
image: nginx/nginx-prometheus-exporter:0.8.0
ports:
- name: metrics
containerPort: 9113 # 指定 metrics port
args: # 从 ngins load metrics
- -nginx.scrape-uri=http://localhost/stub_status
```
排除 scrape 已经被移除所以当你部署这个更新普罗米修斯将scrape 端口9113上的Nginx Pod在那里exporter 正在监听。所有的Nginx指标将由Prometheus存储Grafana仪表板可以更新为代理添加一行。在本章中我们不打算讨论Prometheus查询语言(PromQL)或构建Grafana仪表板——仪表板可以从JSON文件导入并且有一个更新的仪表板可以部署。
现在试试吧,更新 proxy deployment 以添加 sidecar并将更新后的仪表板加载到Grafana ConfigMap中。
```
# 添加 proxy sidecar:
kubectl apply -f todo-list/update/proxy-with-exporter.yaml
# 等待启动:
kubectl wait --for=condition=ContainersReady pod -l app=todo-proxy -n
kiamol-ch14-test
# 输出 exporter 日志:
kubectl logs -l app=todo-proxy -n kiamol-ch14-test -c exporter
# 更新 app dashboard:
kubectl apply -f grafana/update/grafana-dashboard-todo-list-v2.yaml
# 重启 Grafana load 新 dashboard:
kubectl rollout restart deploy grafana -n kiamol-ch14-monitoring
# 刷新 dashboard
```
Nginx exporter 没有提供大量的信息但基本的细节都在那里。你可以在图14.8中看到我们得到了HTTP请求的数量以及Nginx如何处理连接请求的底层分解。即使使用这个简单的仪表板你也可以看到Nginx正在处理的流量和web应用程序正在处理的流量之间的相关性这表明代理没有缓存响应而是对每个请求都调用web应用程序。
![图14.8](./images/Figure14.8.png)
<center>图14.8使用导出器收集代理指标为仪表板添加了另一层细节. </center>
如果能从Nginx得到更多的信息就好了——比如响应中HTTP状态码的分解——但是 exporter 只能从源系统中转可用的信息这对Nginx来说并不多。其他 exporter 提供更多细节但您需要集中您的仪表板以便显示关键指标。超过12个左右的可视化和仪表板变得势不可挡而且如果它不能一眼传达有用的信息那么它就没有做得很好。
还有一个组件要添加到待办事项列表仪表板中:Postgres数据库。Postgres将各种有用的信息存储在数据库中的表和函数中exporter 运行查询来支持其metrics端点。Postgres exporter 的设置遵循我们在Nginx中看到的相同模式。在这种情况下sidecar被配置为访问本地主机上的Postgres使用与Postgres容器用于admin密码相同的Kubernetes Secret。我们将对应用程序仪表板进行最后的更新以显示来自 exporter 的关键数据库指标。
现在试试,更新数据库部署规范添加Postgres exporter 作为 sidecar 容器。然后用更新待办事项列表仪表板以显示数据库性能。
```
# 添加 Postgres exporter sidecar:
kubectl apply -f todo-list/update/db-with-exporter.yaml
# 等待 pod 启动:
kubectl wait --for=condition=ContainersReady pod -l app=todo-db -n
kiamol-ch14-test
# 输出 exporter 日志:
kubectl logs -l app=todo-db -n kiamol-ch14-test -c exporter
# 更新 dashboard 重启 Grafana:
kubectl apply -f grafana/update/grafana-dashboard-todo-list-v3.yaml
kubectl rollout restart deploy grafana -n kiamol-ch14-monitoring
```
在图14.9中,我缩小并向下滚动,这样您就可以看到新的可视化效果,但是在全屏模式下,整个仪表板都是赏心悦目的。一个页面显示了代理的流量,应用程序的工作强度,用户实际在做什么,以及数据库内部发生了什么。您可以在自己的应用程序中使用客户端库和 exporter 获得相同级别的细节,而这只需要几天的努力。
![图14.9](./images/Figure14.9.png)
<center> 图 14.9 数据库 exporter 记录有关数据活动的度量,这将向仪表板添加详细信息. </center>
exporter 在那里为没有普罗米修斯支持的应用程序添加指标。如果您的目标是将一组现有的应用程序转移到Kubernetes上那么您可能没有一个奢侈的开发团队来添加自定义指标。对于这些应用程序您可以使用Prometheus blackbox exporter这是一种极端的方法即有监控总比没有好。
blackbox exporter 可以在sidecar中运行向应用程序容器发出TCP或HTTP请求并提供一个基本的度量端点来说明应用程序是否启动。这种方法类似于在Pod规范中添加容器探测除了 blackbox exporter 仅供参考。如果应用程序不适合Kubernetes 的自我修复机制你可以运行一个仪表板来显示应用程序的状态比如我们在本书中使用的随机数API。
现在试试吧,使用 blackbox exporter 和最简单的Grafana仪表板部署随机数API。您可以通过重复使用API来破坏它然后重置它使其重新工作仪表板跟踪状态。
```
# 部署 API 程序到测试命名空间:
kubectl apply -f numbers/
# 添加新的 dashboard 到 grafana:
kubectl apply -f grafana/update/numbers-api/
# 获得 API URL:
kubectl get svc numbers-api -o jsonpath='#app - http://{.status.loadBalancer.ingress[0].*}:8016/rng' -n kiamol-ch14-test
# 通过访问/rng URL来使用API
# 它将在三次调用后中断;
# 然后访问 /reset 来修复它
# 获取仪表盘的URL并在Grafana中加载它:
kubectl get svc grafana -o jsonpath='# dashboard - http://{.status
.loadBalancer.ingress[0].*}:3000/d/Tb6isdMMk' -n kiamol-ch14-
monitoring
```
随机数API不支持Prometheus但是运行 blackbox exporter 作为sidecar容器可以基本了解应用程序状态。图14.10显示了一个大部分为空的仪表板,但这两个可视化显示了应用程序是否健康,以及应用程序在不健康和被重置之间切换时状态的历史趋势。
![图14.10](./images/Figure14.10.png)
<center>图14.10 即使是一个简单的仪表盘也是有用的。这显示了API的当前和历史状态。 </center>
随机数API的Pod规范遵循与待办应用中的Nginx和Postgres类似的模式: blackbox exporter 被配置为一个额外的容器并指定暴露指标的端口。Pod 注释自定义度量URL的路径因此当Prometheus从sidecar中抓取度量时它调用 blackbox exporter 该导出器检查API是否响应HTTP请求。
现在我们有三个不同的应用程序的仪表板,它们有不同的细节级别,因为应用程序组件与它们收集的数据不一致。但是所有的组件都有一个共同点:它们都在 kubernetes 容器中运行.在下一节中您将学习如何通过配置Prometheus从集群本身收集平台指标。
## 14.4 监控容器以及 kubernetes 对象
Prometheus与Kubernetes集成用于服务发现但它不从API收集任何指标。你可以从另外两个组件获得关于Kubernetes对象和容器活动的指标:cAdvisor(谷歌开源项目)和kube-state-metrics (Kubernetes组织的一部分)。两者都作为集群中的容器运行但它们从不同的来源收集数据。cAdvisor从容器运行时收集度量因此它作为一个DaemonSet运行每个节点上都有一个Pod以报告该节点的容器。kube-state-metrics查询Kubernetes API因此它可以作为 Deployment 运行,在任何节点上都有一个副本。
现在试试吧,为 cAdvisor 和 kube-state-metrics 部署度量收集器并更新Prometheus配置以将它们包括为抓取目标。
```
# 部署 cAdvisor 和 kube-state-metrics:
kubectl apply -f kube/
# 等待 cAdvisor 启动:
kubectl wait --for=condition=ContainersReady pod -l app=cadvisor -n kube-system
# 更新 Prometheus config:
kubectl apply -f prometheus/update/prometheus-config-kube.yaml
# 等待 ConfigMap 更新生效:
sleep 30
# 使用 HTTP POST 请求重新加载 Prometheus 配置:
curl -X POST $(kubectl get svc prometheus -o
jsonpath='http://{.status.loadBalancer.ingress[0].*}:9090/-/reload'
-n kiamol-ch14-monitoring)
# 访问 Prometheus UI— 在 Graph 页面你将看到包含 容器以及 kubernetes 对象的 metrics 信息
```
在本练习中,您将看到 Prometheus 正在收集数以千计的新度量。原始数据包括每个容器使用的计算资源和每个Pod的状态。我的输出如图14.11所示。当您运行这个练习时您可以检查Prometheus UI中的Targets页面以确认新的目标正在被抓取。Prometheus不会自动重新加载配置因此在练习中会有一个延迟让Kubernetes有时间传播ConfigMap更新并且curl命令强制Prometheus重新加载配置。
![图14.11](./images/Figure14.11.png)
<center>图 14.11 新指标显示集群和容器级别的活动. </center>
刚刚部署的更新后的Prometheus配置包括两个新的作业定义如清单14.6所示。kube-state-metrics使用服务的完整DNS名称指定为静态目标。一个Pod收集所有的指标所以这里不存在负载平衡问题。cAdvisor使用Kubernetes服务发现来查找DaemonSet中的每个Pod这将为多节点集群中的每个节点提供一个目标。
> 清单 14.6 prometheus-config-kube.yaml, Prometheus 新的采集 target
```
- job_name: 'kube-state-metrics' # Kubernetes metrics 使用静态的 DNS 配置
static_configs:
- targets:
- kube-state-metrics.kube-system.svc.cluster.local:8080
- kube-state-metrics.kube-system.svc.cluster.local:8081
- job_name: 'cadvisor' # Container metrics 使用 kubernetes 服务发现
kubernetes_sd_configs: # 来找到所有的 DaemonSet Pods,加上命名空间以及标签参数
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_namespace
- __meta_kubernetes_pod_labelpresent_app
- __meta_kubernetes_pod_label_app
action: keep
regex: kube-system;true;cadvisor
```
现在我们遇到了与随机数仪表板相反的问题:新指标中有太多信息,所以平台仪表板需要高度选择性,如果它想要有用的话。我准备了一个示例仪表板,这是一个很好的开始。它包括集群的当前资源使用情况和所有可用资源数量,以及按命名空间划分的一些高级分解和节点运行状况的警告指示器。
现在试试吧为关键集群指标部署一个仪表板并对Grafana进行更新以便它加载新的仪表板。
```
# 创建仪表板ConfigMap并更新Grafana:
kubectl apply -f grafana/update/kube/
# 等待 grafana 加载:
kubectl wait --for=condition=ContainersReady pod -l app=grafana -n
kiamol-ch14-monitoring
# 获取新的 dashboard url:
kubectl get svc grafana -o
jsonpath='http://{.status.loadBalancer.ingress[0].*}:3000/d/oWe9aYxmk' -n kiamol-ch14-monitoring
# 浏览 dashboard
```
这是另一个用于大屏幕的仪表板,因此图 14.12 中的屏幕截图并不能准确地显示它。当您运行这个练习时您可以更仔细地检查它。上面一行显示内存使用情况中间一行显示CPU使用情况下面一行显示Pod容器的状态。
![图14.12](./images/Figure14.12.png)
<center>图14.12 另一个小截图—在您自己的集群中运行练习以查看完整的大小. </center>
像这样的平台 dashboard 级别相当低——它实际上只是显示您的集群是否接近饱和点。支持这个仪表板的查询将更有用可以作为警报在资源使用失控时发出警告。Kubernetes 的压力指示器在那里很有用。内存压力和进程压力值显示在仪表板中还有一个磁盘压力指示器。这些值很重要因为如果节点受到计算压力它可以终止Pod容器。这些都是值得注意的良好指标因为如果您达到了这个阶段您可能需要呼叫某人来看护集群恢复正常。
平台指标还有另一个用途:在应用程序本身无法提供足够详细指标的情况下为应用程序仪表板添加细节。平台仪表板显示整个集群中聚合的计算资源使用情况但cAdvisor在容器级别上收集它。kube-state-metrics也是如此您可以过滤特定工作负载的指标以便向应用程序仪表板添加平台信息。我们将在本章中进行最后一次仪表板更新将平台的详细信息添加到随机数应用程序中。
现在试试吧,为随机数API更新仪表板以添加来自平台的指标。这只是一个Grafana更新;应用程序本身和普罗米修斯都没有变化。
```
# 更新 dashboard:
kubectl apply -f grafana/update/grafana-dashboard-numbers-api-v2.yaml
# 重新启动Grafana让它重新加载仪表板:
kubectl rollout restart deploy grafana -n kiamol-ch14-monitoring
# 等待 pod 启动:
kubectl wait --for=condition=ContainersReady pod -l app=grafana -n
kiamol-ch14-monitoring
# 浏览随机数API仪表板
```
如图14.13所示仪表板仍然是基础信息但至少我们现在有了一些细节可以帮助关联任何问题。如果HTTP状态代码显示为503我们可以快速查看CPU是否也处于峰值状态。如果Pod标签包含一个应用程序版本(这是应该的),我们可以确定哪个版本的应用程序遇到了问题。
![图14.13](./images/Figure14.13.png)
<center>图14.13 使用容器和Pod指标增强基本运行状况统计可以增加相关性. </center>
关于监控还有很多我不会在这里介绍的内容但是现在您已经对Kubernetes和Prometheus如何协同工作有了一个坚实的基础。您缺少的主要部分是在服务器级收集指标和配置警报。服务器指标提供磁盘和网络使用情况等数据。您可以通过直接在节点上运行 exporter 来收集它们(对于Linux服务器使用Node export对于Windows服务器使用Windows export)并使用服务发现将节点添加为抓取目标。Prometheus 有一个复杂的警报系统,它使用 PromQL 查询定义警报规则。您可以配置警报以便当规则被触发时Prometheus 将发送电子邮件、创建Slack消息或通过PagerDuty发送通知。
我们将通过查看《Kubernetes》中普罗米修斯的完整架构来结束本章并深入研究哪些部分需要定制工作以及需要在哪里努力。
## 14.5 了解您在监控方面所做的投资
当你走出核心 Kubernetes进入生态系统时你需要了解你所依赖的项目是否在五年后或一年后或在你所写的章节付印时仍然存在。在这本书中我一直很小心地只包括那些开源的、被大量使用的、具有既定历史和治理模型的生态系统组件。图14.14中的监视体系结构使用了全部满足这些标准的组件。
![图14.14](./images/Figure14.14.png)
<center>图14.14 监控不是免费的——它需要开发并依赖于开源项目. </center>
我提出这一点是因为迁移到普罗米修斯将涉及开发工作。您需要为您的应用程序记录有趣的指标以使您的仪表板真正有用。您应该对投资有信心因为Prometheus是监视容器应用程序最流行的工具并且该项目是cncf继Kubernetes之后第二个毕业的项目。目前正在进行的工作是将Prometheus度量格式引入一个开放标准(称为OpenMetrics)这样其他工具将能够读取以Prometheus格式公开的应用程序度量。
你在这些指标中包含什么将取决于你的应用程序的性质,但是一个好的通用方法是遵循谷歌网站可靠性工程实践的指导方针。在应用指标中添加四个黄金信号通常非常简单:延迟、流量、错误和饱和度。(电子书的附录B介绍了这些在《普罗米修斯》中的样子。)但真正的价值来自于从用户体验的角度考虑应用程序性能。一个显示数据库中磁盘使用率很高的图表并不能告诉你太多东西,但是如果你能看到有很大比例的用户因为你网站的结帐页面加载时间太长而没有完成购买,这是值得了解的。
监控到此结束,我们可以清理集群为实验室做准备了。
现在试试吧,删除本章的命名空间以及system命名空间下创建的对象。
```
kubectl delete ns -l kiamol=ch14
kubectl delete all -n kube-system -l kiamol=ch14
```
## 14.6 实验室
本章的另一个调查实验室。在lab文件夹中有一组清单用于稍微简单一点的Prometheus部署和Elasticsearch的基本部署。我们的目标是运行Elasticsearch并将度量流入到Prometheus中。以下是细节:
- Elasticsearch不提供自己的指标所以你需要找到一个组件来为你做这件事。
- Prometheus 配置将告诉您需要为Elasticsearch使用哪个命名空间以及您需要为度量路径使用注释。
- 你应该在你的Elasticsearch Pod spec 中包含一个版本标签,这样 Prometheus 就会把它添加到度量标签中。
您需要搜索Prometheus的文档才能开始它应该会为您指明方向。我的解决方案在GitHub上你可以在通常的地方检查: https://github.com/yyong-brs/learn-kubernetes/tree/master/kiamol/ch14/lab/README.md。