通过Prometheus来做SLI/SLO监控展示

时间:2022-05-01 03:11:02

通过Prometheus来做SLI/SLO监控展示

什么是SLI/SLO

SLI,全名Service Level Indicator,是服务等级指标的简称,它是衡定系统稳定性的指标。

SLO,全名Sevice Level Objective,是服务等级目标的简称,也就是我们设定的稳定性目标,比如"4个9","5个9"等。

SRE通常通过这两个指标来衡量系统的稳定性,其主要思路就是通过SLI来判断SLO,也就是通过一系列的指标来衡量我们的目标是否达到了"几个9"。

如何选择SLI

在系统中,常见的指标有很多种,比如:

  • 系统层面:CPU使用率、内存使用率、磁盘使用率等
  • 应用服务器层面:端口存活状态、JVM的状态等
  • 应用运行层面:状态码、时延、QPS等
  • 中间件层面:QPS、TPS、时延等
  • 业务层面:成功率、增长速度等

这么多指标,应该如何选择呢?只要遵从两个原则就可以:

  • 选择能够标识一个主体是否稳定的指标,如果不是这个主体本身的指标,或者不能标识主体稳定性的,就要排除在外。
  • 优先选择与用户体验强相关或用户可以明显感知的指标。

通常情况下,可以直接使用谷歌的VALET指标方法。

  • V:Volume,容量,服务承诺的最大容量
  • A:Availability,可用性,服务是否正常
  • L:Latency,延迟,服务的响应时间
  • E:Error,错误率,请求错误率是多少
  • T:Ticket,人工介入,是否需要人工介入

这就是谷歌使用VALET方法给的样例。

通过Prometheus来做SLI/SLO监控展示

上面仅仅是简单的介绍了一下SLI/SLO,更多的知识可以学习《SRE:Google运维解密》和赵成老师的极客时间课程《SRE实践手册》。下面来简单介绍如何使用Prometheus来进行SLI/SLO监控

service-level-operator

 

Service level operator是为了Kubernetes中的应用SLI/SLO指标来衡量应用的服务指标,并可以通过Grafana来进行展示。

Operator主要是通过SLO来查看和创建新的指标。例如:

  1. apiVersion: monitoring.spotahome.com/v1alpha1 
  2. kind: ServiceLevel 
  3. metadata: 
  4.   name: awesome-service 
  5. spec: 
  6.   serviceLevelObjectives: 
  7.     - name"9999_http_request_lt_500" 
  8.       description: 99.99% of requests must be served with <500 status code. 
  9.       disable: false 
  10.       availabilityObjectivePercent: 99.99 
  11.       serviceLevelIndicator: 
  12.         prometheus: 
  13.           address: http://myprometheus:9090 
  14.           totalQuery: sum(increase(http_request_total{host="awesome_service_io"}[2m])) 
  15.           errorQuery: sum(increase(http_request_total{host="awesome_service_io", code=~"5.."}[2m])) 
  16.       output
  17.         prometheus: 
  18.           labels: 
  19.             team: a-team 
  20.             iteration: "3" 
  • availabilityObjectivePercent:SLO
  • totalQuery:总请求数
  • errorQuery:错误请求数

Operator通过totalQuert和errorQuery就可以计算出SLO的指标了。

部署service-level-operator

 

  • 前提:在Kubernetes集群中部署好Prometheus,我这里是采用Prometheus-Operator方式进行部署的。

(1)首先创建RBAC

  1. apiVersion: v1 
  2. kind: ServiceAccount 
  3. metadata: 
  4.   name: service-level-operator 
  5.   namespace: monitoring 
  6.   labels: 
  7.     app: service-level-operator 
  8.     component: app 
  9.  
  10. --- 
  11. apiVersion: rbac.authorization.k8s.io/v1 
  12. kind: ClusterRole 
  13. metadata: 
  14.   name: service-level-operator 
  15.   labels: 
  16.     app: service-level-operator 
  17.     component: app 
  18. rules: 
  19.   # Register and check CRDs. 
  20.   - apiGroups: 
  21.       - apiextensions.k8s.io 
  22.     resources: 
  23.       - customresourcedefinitions 
  24.     verbs: 
  25.       - "*" 
  26.  
  27.   # Operator logic. 
  28.   - apiGroups: 
  29.       - monitoring.spotahome.com 
  30.     resources: 
  31.       - servicelevels 
  32.       - servicelevels/status 
  33.     verbs: 
  34.       - "*" 
  35.  
  36. --- 
  37. kind: ClusterRoleBinding 
  38. apiVersion: rbac.authorization.k8s.io/v1 
  39. metadata: 
  40.   name: service-level-operator 
  41. subjects: 
  42.   - kind: ServiceAccount 
  43.     name: service-level-operator 
  44.     namespace: monitoring  
  45. roleRef: 
  46.   apiGroup: rbac.authorization.k8s.io 
  47.   kind: ClusterRole 
  48.   name: service-level-operator 

(2)然后创建Deployment

  1. apiVersion: apps/v1  
  2. kind: Deployment 
  3. metadata: 
  4.   name: service-level-operator 
  5.   namespace: monitoring 
  6.   labels: 
  7.     app: service-level-operator 
  8.     component: app 
  9. spec: 
  10.   replicas: 1 
  11.   selector: 
  12.     matchLabels: 
  13.       app: service-level-operator 
  14.       component: app 
  15.   strategy: 
  16.     rollingUpdate: 
  17.       maxUnavailable: 0 
  18.   template: 
  19.     metadata: 
  20.       labels: 
  21.         app: service-level-operator 
  22.         component: app 
  23.     spec: 
  24.       serviceAccountName: service-level-operator 
  25.       containers: 
  26.         - name: app 
  27.           imagePullPolicy: Always 
  28.           image: quay.io/spotahome/service-level-operator:latest 
  29.           ports: 
  30.             - containerPort: 8080 
  31.               name: http 
  32.               protocol: TCP 
  33.           readinessProbe: 
  34.             httpGet: 
  35.               path: /healthz/ready 
  36.               port: http 
  37.           livenessProbe: 
  38.             httpGet: 
  39.               path: /healthz/live 
  40.               port: http 
  41.           resources: 
  42.             limits: 
  43.               cpu: 220m 
  44.               memory: 254Mi 
  45.             requests: 
  46.               cpu: 120m 
  47.               memory: 128Mi 

(3)创建service

  1. apiVersion: v1 
  2. kind: Service 
  3. metadata: 
  4.   name: service-level-operator 
  5.   namespace: monitoring 
  6.   labels: 
  7.     app: service-level-operator 
  8.     component: app 
  9. spec: 
  10.   ports: 
  11.     - port: 80 
  12.       protocol: TCP 
  13.       name: http 
  14.       targetPort: http 
  15.   selector: 
  16.     app: service-level-operator 
  17.     component: app 

(4)创建prometheus serviceMonitor

  1. apiVersion: monitoring.coreos.com/v1 
  2. kind: ServiceMonitor 
  3. metadata: 
  4.   name: service-level-operator 
  5.   namespace: monitoring 
  6.   labels: 
  7.     app: service-level-operator 
  8.     component: app 
  9.     prometheus: myprometheus 
  10. spec: 
  11.   selector: 
  12.     matchLabels: 
  13.       app: service-level-operator 
  14.       component: app 
  15.   namespaceSelector: 
  16.     matchNames: 
  17.       - monitoring  
  18.   endpoints: 
  19.     - port: http 
  20.       interval: 10s 

到这里,Service Level Operator部署完成了,可以在prometheus上查看到对应的Target,如下:

通过Prometheus来做SLI/SLO监控展示

然后就需要创建对应的服务指标了,如下所示创建一个示例。

  1. apiVersion: monitoring.spotahome.com/v1alpha1 
  2. kind: ServiceLevel 
  3. metadata: 
  4.   name: prometheus-grafana-service 
  5.   namespace: monitoring 
  6. spec: 
  7.   serviceLevelObjectives: 
  8.     - name"9999_http_request_lt_500" 
  9.       description: 99.99% of requests must be served with <500 status code. 
  10.       disable: false 
  11.       availabilityObjectivePercent: 99.99 
  12.       serviceLevelIndicator: 
  13.         prometheus: 
  14.           address: http://prometheus-k8s.monitoring.svc:9090 
  15.           totalQuery: sum(increase(http_request_total{service="grafana"}[2m])) 
  16.           errorQuery: sum(increase(http_request_total{service="grafana", code=~"5.."}[2m])) 
  17.       output
  18.         prometheus: 
  19.           labels: 
  20.             team: prometheus-grafana  
  21.             iteration: "3" 

上面定义了grafana应用"4个9"的SLO。

然后可以在Prometheus上看到具体的指标,如下。

通过Prometheus来做SLI/SLO监控展示

接下来在Grafana上导入ID为8793的Dashboard,即可生成如下图表。

通过Prometheus来做SLI/SLO监控展示

上面是SLI,下面是错误总预算和已消耗的错误。

下面可以定义告警规则,当SLO下降时可以第一时间收到,比如:

  1. groups: 
  2.   - nameslo.rules 
  3.     rules: 
  4.       - alert: SLOErrorRateTooFast1h 
  5.         expr: | 
  6.           ( 
  7.             increase(service_level_sli_result_error_ratio_total[1h]) 
  8.             / 
  9.             increase(service_level_sli_result_count_total[1h]) 
  10.           ) > (1 - service_level_slo_objective_ratio) * 14.6 
  11.         labels: 
  12.           severity: critical 
  13.           team: a-team 
  14.         annotations: 
  15.           summary: The monthly SLO error budget consumed for 1h is greater than 2% 
  16.           description: The error rate for 1h in the {{$labels.service_level}}/{{$labels.slo}} SLO error budget is being consumed too fast, is greater than 2% monthly budget. 
  17.       - alert: SLOErrorRateTooFast6h 
  18.         expr: | 
  19.           ( 
  20.             increase(service_level_sli_result_error_ratio_total[6h]) 
  21.             / 
  22.             increase(service_level_sli_result_count_total[6h]) 
  23.           ) > (1 - service_level_slo_objective_ratio) * 6 
  24.         labels: 
  25.           severity: critical 
  26.           team: a-team 
  27.         annotations: 
  28.           summary: The monthly SLO error budget consumed for 6h is greater than 5% 
  29.           description: The error rate for 6h in the {{$labels.service_level}}/{{$labels.slo}} SLO error budget is being consumed too fast, is greater than 5% monthly budget. 

第一条规则表示在1h内消耗的错误率大于30天内的2%,应该告警。第二条规则是在6h内的错误率大于30天的5%,应该告警。

下面是谷歌的的基准。

通过Prometheus来做SLI/SLO监控展示

最后

 

说到系统稳定性,这里不得不提到系统可用性,SRE提高系统的稳定性,最终还是为了提升系统的可用时间,减少故障时间。那如何来衡量系统的可用性呢?

目前业界有两种衡量系统可用性的方式,一个是时间维度,一个是请求维度。时间维度就是从故障出发对系统的稳定性进行评估。请求维度是从成功请求占比的角度出发,对系统稳定性进行评估。

时间维度:可用性 = 服务时间 / (服务时间 + 故障时间)

请求维度:可用性 = 成功请求数 / 总请求数

在SRE实践中,通常会选择请求维度来衡量系统的稳定性,就如上面的例子。不过,如果仅仅通过一个维度来判断系统的稳定性也有点太武断,还应该结合更多的指标,比如延迟,错误率等,而且对核心应用,核心链路的SLI应该更细致。

参考

 

[1] 《SRE实践手册》- 赵成

[2] 《SRE:Google运维解密》

[3] https://github.com/spotahome/service-level-operator

 

原文地址:https://mp.weixin.qq.com/s/KAQLFqlZsPR0wHDjO_ymig