[关闭]
@levinzhang 2019-09-15T14:37:38.000000Z 字数 8702 阅读 591

为Jaeger安装环境搭建监控基础设施

摘要

本文阐述了如何在Kubernetes环境中,为Jaeger搭建监控基础设施,并为其实现自定义的Dashboard和告警规则。


本文最初发表于RedHat开发者博客,经原作者Juraci Paixão Kröhling和RedHat授权由InfoQ中文站翻译分享。

在生产环境中部署Jaeger时,持续观察Jaeger实例,保证它的行为符合预期是非常重要的。毕竟,Jaeger停机将会意味着跟踪数据的丢失,这样的话,我们很难理解生产环境的应用中究竟出现了什么问题。

本文将会介绍如何为Jaeger安装环境构建监控基础设施。首先,我们会为那些急切想监控Jaeger的读者提供现成资源的链接。

在第二部分中,我们会深入了解如何在Kubernetes集群中安装所有的工具,包括PrometheusGrafana和Jaeger本身,同时还会学习如何安装所需的工具,从而基于Jaeger官方的监控mixin自定义告警规则和dashboard。

提示:如果你已经具有Grafana、Prometheus和Jaeger组成的可运行环境的话,那么你可能只关心基础dashboard和告警定义在什么地方,它们的地址如下:

如果你已经熟悉mixin的话,Jaeger的官方监控mixin就可以在主资源仓库获取

预备条件

本指南假设你具备Kubernetes的admin访问权限。如果以测试为目的的话,有一种了解Kubernetes集群的简便方式,那就是在本地运行Minikube

本指南还需要用到jsonnetjb (jsonnet-bundler)。它们可以借助go get,在本地机器通过如下命令安装:

  1. $ go get github.com/google/go-jsonnet/cmd/jsonnet
  2. $ go get github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb

安装Prometheus、Alertmanager和Grafana

在Kubernetes之上安装Prometheus可以通过多种方式来实现。其中一种方式是使用kube-prometheus项目,但是也可以直接使用Prometheus Operator,还可以使用Prometheus Operator的社区Helm chart。在本指南中,我们会使用kube-prometheus来获取Prometheus、Alertmanager和Grafana实例。

首先,我们使用jb生成一个基础jsonnet文件,该文件描述了我们的安装需求,将kube-prometheus作为依赖添加进来:

  1. $ jb init
  2. $ jb install \
  3. github.com/jaegertracing/jaeger/monitoring/jaeger-mixin@master \
  4. github.com/grafana/jsonnet-libs/grafana-builder@master \
  5. github.com/coreos/kube-prometheus/jsonnet/kube-prometheus@master

完成之后,我们需要有一个名为jsonnetfile.json的manifest文件,它大致如下所示:

  1. {
  2. "dependencies": [
  3. {
  4. "name": "mixin",
  5. "source": {
  6. "git": {
  7. "remote": "https://github.com/jpkrohling/jaeger",
  8. "subdir": "monitoring/mixin"
  9. }
  10. },
  11. "version": "1668-Move-Jaeger-mixing-to-main-repo"
  12. },
  13. {
  14. "name": "grafana-builder",
  15. "source": {
  16. "git": {
  17. "remote": "https://github.com/grafana/jsonnet-libs",
  18. "subdir": "grafana-builder"
  19. }
  20. },
  21. "version": "master"
  22. },
  23. {
  24. "name": "kube-prometheus",
  25. "source": {
  26. "git": {
  27. "remote": "https://github.com/coreos/kube-prometheus",
  28. "subdir": "jsonnet/kube-prometheus"
  29. }
  30. },
  31. "version": "master"
  32. }
  33. ]
  34. }

install命令应该还会创建一个名为vendor的目录,其中包含了所有的jsonnet依赖。现在,我们所需要就是一个deployment描述符:创建一个名为monitoring-setup.jsonnet的文件,内容如下:

  1. local kp =
  2. (import 'kube-prometheus/kube-prometheus.libsonnet') +
  3. {
  4. _config+:: {
  5. namespace: 'monitoring',
  6. },
  7. };
  8. { ['00namespace-' + name + '.json']: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } +
  9. { ['0prometheus-operator-' + name + '.json']: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } +
  10. { ['node-exporter-' + name + '.json']: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
  11. { ['kube-state-metrics-' + name + '.json']: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
  12. { ['alertmanager-' + name + '.json']: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } +
  13. { ['prometheus-' + name + '.json']: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
  14. { ['prometheus-adapter-' + name + '.json']: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) } +
  15. { ['grafana-' + name + '.json']: kp.grafana[name] for name in std.objectFields(kp.grafana) }

这样,我们就能生成所需的deployment manifest,并应用它们:

  1. $ jsonnet -J vendor -cm manifests/ monitoring-setup.jsonnet
  2. $ kubectl apply -f manifests/

第一次使用的时候,自定义资源定义(Custom Resource Definition,CRD)可能尚未就绪,这会导致如下的信息:

  1. no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1"

如果出现这种情况的话,只需要再次应用一下这些manifest即可,因为它们是幂等的。

几分钟之后,我们应该就会有几个可用的DeploymentStatefulset资源了:

  1. $ kubectl get deployments -n monitoring
  2. NAME READY UP-TO-DATE AVAILABLE AGE
  3. grafana 1/1 1 1 56s
  4. kube-state-metrics 1/1 1 1 56s
  5. prometheus-adapter 1/1 1 1 56s
  6. prometheus-operator 1/1 1 1 57s
  7. $ kubectl get statefulsets -n monitoring
  8. NAME READY AGE
  9. alertmanager-main 3/3 60s
  10. prometheus-k8s 2/2 50s

我们可以直接连接服务的端口,检查一下Prometheus是否已经启动:

  1. $ kubectl port-forward -n monitoring service/prometheus-k8s 9090:9090
  2. $ firefox http://localhost:9090

对Grafana执行相同的检查,默认凭证的用户名和密码都是admin

  1. $ kubectl port-forward -n monitoring service/grafana 3000:3000
  2. $ firefox http://localhost:3000

安装Jaeger

Jaeger Operator默认会安装到“observability”命名空间中。在本指南中,我们会将它放到“monitoring”命名空间中,与Prometheus和Grafana放到一起。为了实现这一点,我们需要通过curl获取manifest,并将“observability”替换为“monitoring”,然后将输出提供给kubectl

  1. $ kubectl create -f https://raw.githubusercontent.com/jaegertracing/jaeger-operator/v1.13.1/deploy/crds/jaegertracing_v1_jaeger_crd.yaml
  2. $ curl -s https://raw.githubusercontent.com/jaegertracing/jaeger-operator/v1.13.1/deploy/service_account.yaml | sed 's/observability/monitoring/gi' | kubectl apply -f -
  3. $ curl -s https://raw.githubusercontent.com/jaegertracing/jaeger-operator/v1.13.1/deploy/role.yaml | sed 's/observability/monitoring/gi' | kubectl apply -f -
  4. $ curl -s https://raw.githubusercontent.com/jaegertracing/jaeger-operator/v1.13.1/deploy/role_binding.yaml | sed 's/observability/monitoring/gi' | kubectl apply -f -
  5. $ curl -s https://raw.githubusercontent.com/jaegertracing/jaeger-operator/v1.13.1/deploy/operator.yaml | sed 's/observability/monitoring/gi' | kubectl apply -f -

在撰写本文的时候,最新版本为v1.13.1,所以你可以修改上述URL以匹配所需的版本。几分钟之后,Jaeger Operator就能启动并运行了:

  1. $ kubectl get deployment/jaeger-operator -n monitoring
  2. NAME READY UP-TO-DATE AVAILABLE AGE
  3. jaeger-operator 1/1 1 1 23s

Jaeger Operator准备就绪之后,我们就可以创建名为tracing的Jaeger实例了:

  1. kubectl apply -f - <<EOF
  2. apiVersion: jaegertracing.io/v1
  3. kind: Jaeger
  4. metadata:
  5. name: tracing
  6. namespace: monitoring
  7. EOF

稍等片刻,Jaeger实例就会准备就绪:

  1. $ kubectl get deployment/tracing -n monitoring
  2. NAME READY UP-TO-DATE AVAILABLE AGE
  3. tracing 1/1 1 1 17s
  4. $ kubectl get ingress -n monitoring
  5. NAME HOSTS ADDRESS PORTS AGE
  6. tracing-query * 192.168.122.181 80 26s

我们可以在Web浏览器中通过给定的IP地址访问Jaeger UI。在本例中,也就是http://192.168.122.181/,但是你的IP可能会有所不同。

现在,所有的内容都运行起来了,接下来我们安装业务应用,并通过instrument操作让它为接收到的每个请求都创建span:

  1. $ kubectl apply -n default -f https://raw.githubusercontent.com/jaegertracing/jaeger-operator/v1.13.1/deploy/examples/business-application-injected-sidecar.yaml

部署完成之后,我们可以直接打开一个到Pod的连接并向其发送请求:

  1. $ kubectl get -n default deployment/myapp
  2. NAME READY UP-TO-DATE AVAILABLE AGE
  3. myapp 1/1 1 1 26s
  4. $ kubectl port-forward deployment/myapp 8080:8080
  5. $ watch -n 0.5 curl localhost:8080

这样每秒钟会生成两个HTTP请求,在Jaeger UI中,我们应该会看到每个HTTP请求都会有一个trace。

创建PodMonitor

现在,我们已经有了一组功能齐全的监控服务:Prometheus、Grafana、Alertmanager和Jaeger。但是,Jaeger deployment所生成的指标并没有被Prometheus所捕获:我们需要创建一个ServiceMonitorPodMonitor,以便于告诉Prometheus到哪里获取数据。

根据组件的不同,指标会由不同的端口来提供:

组件 端口
Agent 14271
Collector 14269
Query 16687
All in one 14269

我们所创建的Jaeger实例并没有指定strategy,所以将会使用默认的strategy,即allInOne。我们的PodMonitor要告诉Prometheus从14269端口获取指标:

  1. $ kubectl apply -f - <<EOF
  2. apiVersion: monitoring.coreos.com/v1
  3. kind: PodMonitor
  4. metadata:
  5. name: tracing
  6. namespace: monitoring
  7. spec:
  8. podMetricsEndpoints:
  9. - interval: 5s
  10. targetPort: 14269
  11. selector:
  12. matchLabels:
  13. app: jaeger
  14. EOF

Prometheus可能需要花费几分钟的时间才能找到这个新的target。进入Targets页面,查找monitoring/tracing/0这个target。Prometheus捕获到Jaeger的指标端点之后,我们就可以在Prometheus Graph视图中看到Jaeger的指标了。例如,进入jaeger_collector_traces_saved_by_svc_total并点击Execute。图中显示的trace数量应该随着时间的推移而增加,它反映了前面步骤中针对业务应用程序运行的HTTP请求的数量。

适配mixin

现在,我们已经在Prometheus中获得了来自Jaeger实例的指标数据,但是应该在dashboard上显示哪些指标,在什么情况下应该生成哪些告警呢?

很难找到一个通用的、适合所有情况的答案来回答这些问题,但是我们在Grafana实验室的朋友们为Jaeger设计了一个mixin,它可以作为你自己的dashboard和告警的一个起点。此后,该mixin贡献了给Jaeger项目,并且可以在主存储库下访问。

让我们回到最初的monitoring-setup.jsonnet,并添加Jaeger特定的dashboard和告警规则:

  1. local jaegerAlerts = (import 'jaeger-mixin/alerts.libsonnet').prometheusAlerts;
  2. local jaegerDashboard = (import 'jaeger-mixin/mixin.libsonnet').grafanaDashboards;
  3. local kp =
  4. (import 'kube-prometheus/kube-prometheus.libsonnet') +
  5. {
  6. _config+:: {
  7. namespace: 'monitoring',
  8. },
  9. grafanaDashboards+:: {
  10. 'jaeger.json': jaegerDashboard['jaeger.json'],
  11. },
  12. prometheusAlerts+:: jaegerAlerts,
  13. };
  14. { ['00namespace-' + name + '.json']: kp.kubePrometheus[name] for name in std.objectFields(kp.kubePrometheus) } +
  15. { ['0prometheus-operator-' + name + '.json']: kp.prometheusOperator[name] for name in std.objectFields(kp.prometheusOperator) } +
  16. { ['node-exporter-' + name + '.json']: kp.nodeExporter[name] for name in std.objectFields(kp.nodeExporter) } +
  17. { ['kube-state-metrics-' + name + '.json']: kp.kubeStateMetrics[name] for name in std.objectFields(kp.kubeStateMetrics) } +
  18. { ['alertmanager-' + name + '.json']: kp.alertmanager[name] for name in std.objectFields(kp.alertmanager) } +
  19. { ['prometheus-' + name + '.json']: kp.prometheus[name] for name in std.objectFields(kp.prometheus) } +
  20. { ['prometheus-adapter-' + name + '.json']: kp.prometheusAdapter[name] for name in std.objectFields(kp.prometheusAdapter) } +
  21. { ['grafana-' + name + '.json']: kp.grafana[name] for name in std.objectFields(kp.grafana) }

接下来,生成新的manifest:

$ jsonnet -J vendor -cm manifests/ monitoring-setup.jsonnet

这里只会改变几个manifest,但是我们可以安全地再次应用所有的manifest:

  1. $ kubectl apply -f manifests/

稍等片刻之后,将会有一个新的Grafana pod替代之前的:

  1. $ kubectl get pods -n monitoring -l app=grafana
  2. NAME READY STATUS RESTARTS AGE
  3. grafana-558647b59-fkmr4 1/1 Running 0 11m
  4. grafana-7bcb7f5b9b-6rv2w 0/1 Pending 0 8s

注意:当使用Minikube时,新pod可能会由于Insufficient cpu而处于Pending状态。我们可以通过运行kubectl describe -n monitoring pod POD_NAME来检查原因,并使用kubectl delete -n monitoring pod POD_NAME手动删除旧的pod,或者使用标记--cpus以更高的值来启动minikube。

新的Grafana pod启动并运行之后,我们应该会看到Grafana有一个新的Jaeger仪表板,显示Prometheus提供的数据。类似地,Prometheus中也会有一个新的告警规则:查找名称中带有“Jaeger”的规则,比如JaegerCollectorQueueNotDraining

总结

在云原生微服务领域中,部署可观察性工具为业务应用程序提供洞察能力是必备的,另外,监视这些工具本身的行为也是必要的。本文展示了在Kubernetes中搭建完整技术栈并运行起来的一种方法,最终目标是使用Jaeger自己的内部指标来监视Jaeger。相同的方式可以扩展至让Prometheus获取业务应用的指标,并以Grafana作为dashboard工具来对数据进行可视化。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注