《Prometheus监控实战》第13章 监控Tornado

2019-12-20 16:57:02 浏览数 (1)

第13章 监控Tornado

  • 我们将在Kubernetes集群上部署一个名为Tornado的应用程序并对其进行监控。Tornado是一个简单的REST-ful HTTP API,用Clojure语言编写的,可在JVM上运行,具有 Redis数据存储和Mysql
  • 监控如下内容
  1. Mysql
  2. Redis
  3. Tornado API应用程序

13.1 边车模式

  • 边车为应用程序提供支持功能——例如,基础设施边车可能会收集日志或进行监控。边车还与父应用程序共享相同的生命周期,与父应用程序一起创建和删除

提示:边车有时也被称为sidekicks


13.2 Mysql

  • 使用Prometheus监控Mysql是通过exporter完成的:Mysqld exporter。exporter使用提供的凭证连接到Mysql服务器并查询服务器状态。使用边车模式在部署到Kubernetes的Docker容器中运行exporter
  • 代码清单:exporter容器
  • 使用带有latest标签的prom/mysqld-exporter镜像,并将容器命名为tornado-db-exp。我们使用DATA_SOURCE_NAME环境变量指定了数据库连接的详细信息,此连接使用DSN格式配置Mysql服务器的连接和凭据的详细信息
  • 代码清单:连接到Mysql容器
代码语言:javascript复制
kubectl exec -ti <pod> -- /usr/bin/mysql -p
  • 代码清单:创建Mysql用户
  • 代码清单:额外的Mysql exporter收集器
  • 从Mysql的performance_schema数据库中收集数据,跟踪特定查询和操作的性能
  • 代码清单:tornado-db服务
  • 使用了两个注解:prometheus.io/scrape告诉Prometheus抓取这个服务:prometheus.io/port告诉要抓取的端口。我们指定这一点是希望Prometheus在端口9104上访问Mysql Exporter,而不是直接访问Mysql服务器
  • 代码清单:Kubernetes端点作业的重新标记
代码语言:javascript复制
relabel_configs:
  - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
    action: keep
    regex: true
  - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
    action: replace
    target_label: __address__
    regex: ([^:] )(?::d )?;(d )
    replacement: $1:$2
……

prometheus.io/port注解将被注入__address__标签中,以便被作业抓取。接下来的服务发现将开始收集这些Mysql指标

Mysql监控配置
  • 我们将创建一个可能的规则样本,大致与Google的四个黄金指标一致,让你了解如何使用Mysql指标。将专注于
  1. 延迟
  2. 流量
  3. 错误
  4. 饱和度

警告:测量Mysql性能很难,尤其是在跟踪延迟等信号时,情况会因应用程序和服务器配置的不同而有很大差异。这些规则为你提供了起点,而不是明确的答案

  • 代码清单:Mysql慢查询警报
代码语言:javascript复制
- alert: MySQLHighSlowQuerysHigh
  expr: rate(mysql_global_status_slow_queries[2m]) > 5
  labels:
    severity: warning
  annotations:
    summary: MySQL Slow query rate is exceeded on {{ $labels.instance }} for {{ $labels.kubernetes_name }}
  • 如果两分钟内慢查询超过5个,则会生成一个警报
  • 代码清单:Mysql请求速率记录mysql_rules.yml
代码语言:javascript复制
groups:
  - name: mysql_rules
    rules:
      - record: mysql:write_requests:rate2m
        expr: sum(rate(mysql_global_status_commands_total{command=~"insert|update|delete"}[2m])) without (command)
      - record: mysql:select_requests:rate2m
        expr: sum(rate(mysql_global_status_commands_total{command="select"}[2m]))
      - record: mysql:total_requests:rate2m
        expr: rate(mysql_global_status_commands_total[2m])
  • 我们使用mysql_global_status_commands_total指标并获取特定命令的所有写请求:insert、update和delete。然后,为这些请求计算两分钟的速率。我们对使用select命令的读取请求和总请求执行相同的操作。然后使用topk聚合运算符来获取最近五分钟内根据模式和速率分组的最常用语句,这有助于我们理解服务器正在做什么
  • 代码清单:连接和中止的连接
代码语言:javascript复制
- alert: MySQLAbortedConnectionsHigh
  expr: rate(mysql_global_status_aborted_connects[2m]) > 5
  labels:
    severity: warning
  annotations:
    summary: MySQL Aborted connection rate is exceeded on {{ $labels.instance }} for {{ $labels.kubernetes_name }}
  • 我们将警告中止连接的速率是否超过阀值,并创建一个记录规则以跟踪整体连接速率
  • 最后,我们想知道Mysql服务何时不可用。这些警报使用服务状态和特定于exporter的up指标的组合:mysql_up。mysql_up指标在Mysql服务器上执行SELECT 1,如果查询成功,则将其设置为1。第一个警报检查mysql_up指标的值 是否为0,0表示查询失败。第二个警报在服务消失且指标过期时检查此指标的存在
  • 代码清单:Mysql警报
代码语言:javascript复制
- alert: TornadoDBServerDown
  expr: mysql_up{kubernetes_name="tornado-db"} == 0
  for: 10m
  labels:
    severity: critical
  annotations:
    summary: MySQL Server {{ $labels.instance }} is down!

13.3 Redis

  • 像Mysql一样,Promethseus也有对应Redis的exporter。Redis Exporter将从INFO命令导出大部分条目,其中包含服务器、客户端、内存和CPU使用情况的详细信息。在每个数据库中,还有用于键总数、过期键和键的平均TTL的指标,你可以导出这些键的值
  • 代码清单:Redis服务和边车
代码语言:javascript复制
apiVersion: apps/v1beta2
kind: Deployment
  - name: redis-exporter
    image: oliver006/redis_exporter:latest
    env:
      - name: REDIS_ADDR
        value: redis//tornado-redis:6379
      - name: REDIS_PASSWORD
        value: tornadoapi
    ports:
      - containerPort: 9121
  • 我们正在运行一个名为redis-exporter的容器,该容器通过Docker镜像构建。指定了两个环境变量和端口
  • 代码清单:通过Kubernetes暴露Redis服务端口
  • 可以看到我们暴露了端口9121,并指定了两个注解:一个用于告诉Prometheus服务端点作业要抓取这个服务,另一个用于指示要抓取的端口。下一次Prometheus进行服务发现时,它将检测更新后的服务并开始收集redis指标
Redis监控配置
  • 代码清单:Redis警报
代码语言:javascript复制
- alert: TornadoRedisCacheMissesHigh
  expr: redis_keyspace_hits_total / (redis_keyspace_hits_total   redis_keyspace_misses_total) > 0.8
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: Redis Server {{ $labels.instance }} Cache Misses are high.
  • 我们想知道Redis服务何时不可用。这些警报使用服务状态和特定于exporter的up指标的组合:redis_up。如果Redis服务器的抓取成功,则redis_up指标设置为1.第一个警报检查redis_up指标的值是否为0,0表示查询失败。第二个警报在服务消失且指标过期时检查此指标的存在
  • 代码清单:Redis可用性警报
代码语言:javascript复制
- alert: TornadoRedisServerDown
  expr: redis_up{kubernetes_name="tornado-redis"} == 0
  for: 10m
  labels:
    severity: critical
  annotations:
    summary: Redis Server {{ $labels.instance }} is down!

13.4 Tornado

  • Tornado API是一个Clojure应用程序,它使用Ring并在JVM上运行。应用程序提供了一个API端点,可以购买和销售商品(https://github.com/ring-clojure/ring)

13.4.1 添加Clojure包装器

  • 为了检测应用程序,我们使用了iapetos Clojure包装器(https://github.com/clj-commons/iapetos)。要启用iapetos包装器,需要将它添加到project.clj文件项目的依赖项中
  • 代码清单:project.clj
代码语言:javascript复制
(defproject tornado-api "0.1.0-SNAPSHOT"
      :description "Example Clojure REST service for AoM"
      :url "http://artofmonitoring.com"
      :dependencies [[org.clojure/clojure "1.8.0"]
                     [compojure "1.1.1"]
                     [ring/ring-json "0.1.2"]
                     [ring/ring-jetty-adapter "1.3.1"]
                     [ring-logger-timbre "0.7.5"]
                     [com.taoensso/timbre "4.2.1"]
                     [c3p0/c3p0 "0.9.1.2"]
                     [org.clojure/java.jdbc "0.4.2"]
                     [mysql/mysql-connector-java "5.1.38"]
                     [com.taoensso/carmine "2.12.2"]
                     [cheshire "4.0.3"]
                     [clj-statsd "0.3.11"]]
      :plugins [[lein-ring "0.7.3"]]
      :main tornado-api.handler
      :ring {:handler tornado-api.handler/app}
      :profiles {
                 :dev {:dependencies [[ring-mock "0.1.3"]]}
                 :uberjar {:aot :all}})

13.4.2 添加注册表

  • 我们需要定义一个注册表来保存所有指标
  • 代码清单:定义注册表
  • 我们创建了一个名为registry的注册表,并且已经初始化了Ring和JVM指标,这些指标将被自动收集或导出。然后我们定义了五个特定的指标,包括四个计数型指标和一个测量型指标
  • 代码清单:添加标签
  • 我们为item-bought计数器添加了description标签

13.4.3 添加指标

  • 我们现在可以在应用程序上为每个API方法添加函数调用以递增计数器
  • 代码清单:添加指标调用
代码语言:javascript复制
    (defn buy-item [item]
      (let [id (uuid)]
        (sql/db-do-commands db-config
          (let [item (assoc item "id" id)]
            (sql/insert! db-config :items item)
            (statsd/gauge (str statsd-prefix "item.bought.total") (item "price"))))
            (wcar* (car/ping)
              (car/set id (item "title")))
        (get-item id)))
  • 我们调用inc函数,以便在购买商品时增加item-bought计数器
  • 我们还添加了一个名为tornado_up的测量型指标,它将作为应用程序的up指标。当应用程序启动时,它会自动将值 设置为1
  • 代码清单:测量型指标tornado_up
代码语言:javascript复制
(prometheus/set (registry :tornado/up) 1)

13.4.4 导出指标

  • 我们希望启用/metrics页面本身,在示例中是使用内置的Ring支持
  • 代码清单:开始导出
代码语言:javascript复制
(def app
      (-> (handler/api app-routes)
        (middleware/wrap-json-body)
        (middleware/wrap-json-response)
        (ring/wrap-metrics registry {:path "/metrics")))
  • 代码清单:Tornado指标

13.4.5 Tornado监控配置

  • 使用一个Ring HTTP指标创建的延迟记录规则
  • 代码清单:Ring延时规则
代码语言:javascript复制
- record: tornado:request_latency_seconds:avg
  expr: http_request_latency_seconds_sum{status="200"} / http_request_latency_seconds_count{status="200"}
  • 我们创建了一个新指标tornado:request_latency_seconds:avg,表示响应为200 HTTP代码的请求的平均请求延迟(秒)
  • 还可以利用一个与Ring相关的历史记录来触发高延迟警报
  • 代码清单:Ring高延时警报
代码语言:javascript复制
- alert: TornadoRequestLatencyHigh
  expr: histogram_quantile(0.9, rate(http_request_latency_seconds_bucket{kubernetes_name="tornado-api"}[5m])) > 0.05
  for: 10m
  labels:
    severity: warning
  annotations:
    summary: API Server {{ $labels.instance }} latency is over 0.05.
  • 这里,我们使用histogram_quantile函数(https://prometheus.io/docs/prometheus/latest/querying/functions/#histogram_quantile)在5分钟内生成请求延迟的第90百分位数。如果持续10分钟超过0.05,那么警报将被触发
  • 还可以利用创建的up风格指标tornado_up来监控API服务的可用性
  • 代码清单:监控Tornado API可用性
代码语言:javascript复制
- alert: TornadoAPIServerDown
  expr: tornado_up{kubernetes_name="tornado-api"} != 1
  for: 10m
  labels:
    severity: critical
  annotations:
    summary: API Server {{ $labels.instance }} is down!
- alert: TornadoAPIServerGone
  expr:  absent(tornado_up{kubernetes_name="tornado-api"})
  for: 10m
  labels:
    severity: critical
  annotations:
    summary: No Tornado API servers are reporting!
    description: Werner Heisenberg says - there is no uncertainty about the Tornado API server being gone.
  • 在这里,我们将检测tornado_up指标的值是否大于0,或者它是否从我们的指标中消失

0 人点赞