Kubernetes集群监控Promethues+Grafana

x33g5p2x  于2021-12-25 转载在 其他  
字(11.6k)|赞(0)|评价(0)|浏览(523)

我们选择Prometheus作为监控系统主要在以下各层面实现监控:

  • 基础设施层:监控各个主机服务器资源(包括Kubernetes的Node和非Kubernetes的Node),如CPU,内存,网络吞吐和带宽占用,磁盘I/O和磁盘使用等指标。
  • 中间件层:监控独立部署于Kubernetes集群之外的中间件,例如:MySQL、Redis、RabbitMQ、ElasticSearch、Nginx等。
  • Kubernetes集群:监控Kubernetes集群本身的关键指标
  • Kubernetes集群上部署的应用:监控部署在Kubernetes集群上的应用

1.基础设施层和中间件层的监控

其中基础设施层监控指标的拉取肯定是来在Prometheus的node_exporter,因为我们要监控的服务器节点既包含Kubernetes节点又包含其他部署独立中间件的节点, 所以我们并没有将node_exporter以daemonset的形式部署到k8s上,而是使用ansible将node_exporter以二进制的形式部署到所有要监控的服务器上。 而负责从node_exporter拉取指标的Prometheus也是用ansible独立部署在Kubernetes集群外部的。Prometheus的配置文件prometheus.yml使用ansible的j2模板生成。

中间层的监控和基础设施层监控类似,使用ansible在各个中间件所在的主机上部署各个中间件的exporter,仍然使用上面在Kubernetes集群外部的这个Prometheus从这些exporter拉取指标,Prometheus的配置文件prometheus.yml使用ansible的j2模板生成。

2.Kubernetes集群的监控

要实现对Kubernetes集群的监控,因为Kubernetes的rbac机制以及证书认证,当然是把Prometheus部署在Kubernetes集群上最方便。可是我们目前的监控系统是以k8s集群外部的Prometheus为主的,grafana和告警都是使用这个外部的Prometheus,如果还需要在Kubernetes集群内部部署一个Prometheus的话一定要把它桶外部的Prometheus联合起来,好在Prometheus支持Federation。

2.1 Prometheus的Federation简介

Federation允许一个Prometheus从另一个Prometheus中拉取某些指定的时序数据。Federation是Prometheus提供的扩展机制,允许Prometheus从一个节点扩展到多个节点,实际使用中一般会扩展成树状的层级结构。下面是Prometheus官方文档中对federation的配置示例:

  1. - job_name: 'federate'
  2. scrape_interval: 15s
  3. honor_labels: true
  4. metrics_path: '/federate'
  5. params:
  6. 'match[]':
  7. - '{job="prometheus"}'
  8. - '{__name__=~"job:.*"}'
  9. static_configs:
  10. - targets:
  11. - 'source-prometheus-1:9090'
  12. - 'source-prometheus-2:9090'
  13. - 'source-prometheus-3:9090'

这段配置所属的Prometheus将从source-prometheus-1 ~ 3这3个Prometheus的/federate端点拉取监控数据。 match[]参数指定了只拉取带有job=”prometheus标签的指标,或者名称以job开头的指标。

2.2 在Kubernetes上部署Prometheus

前面已经介绍了将使用Prometheus federation的形式,k8s集群外部的Prometheus从k8s集群中Prometheus拉取监控数据,外部的Prometheus才是监控数据的存储。 k8s集群中部署Prometheus的数据存储层可以简单的使用emptyDir,数据只保留24小时(或更短时间)即可,部署在k8s集群上的这个Prometheus实例即使发生故障也可以放心的让它在集群节点中漂移。

在k8s上部署Prometheus十分简单,只需要下面4个文件:prometheus.rbac.yml, prometheus.config.yml, prometheus.deploy.yml, prometheus.svc.yml。 下面给的例子中将Prometheus部署到kube-system命名空间。

prometheus.rbac.yml定义了Prometheus容器访问k8s apiserver所需的ServiceAccount和ClusterRole及ClusterRoleBinding,参考Prometheus源码中库中的例子:

  1. apiVersion: rbac.authorization.k8s.io/v1
  2. kind: ClusterRole
  3. metadata:
  4. name: prometheus
  5. rules:
  6. - apiGroups: [""]
  7. resources:
  8. - nodes
  9. - nodes/proxy
  10. - services
  11. - endpoints
  12. - pods
  13. verbs: ["get", "list", "watch"]
  14. - apiGroups:
  15. - extensions
  16. resources:
  17. - ingresses
  18. verbs: ["get", "list", "watch"]
  19. - nonResourceURLs: ["/metrics"]
  20. verbs: ["get"]
  21. ---
  22. apiVersion: v1
  23. kind: ServiceAccount
  24. metadata:
  25. name: prometheus
  26. namespace: kube-system
  27. ---
  28. apiVersion: rbac.authorization.k8s.io/v1
  29. kind: ClusterRoleBinding
  30. metadata:
  31. name: prometheus
  32. roleRef:
  33. apiGroup: rbac.authorization.k8s.io
  34. kind: ClusterRole
  35. name: prometheus
  36. subjects:
  37. - kind: ServiceAccount
  38. name: prometheus
  39. namespace: kube-system

prometheus.config.yml configmap中的prometheus的配置文件,参考Prometheus源码中库中的例子:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: prometheus-config
  5. namespace: kube-system
  6. data:
  7. prometheus.yml: |
  8. global:
  9. scrape_interval: 15s
  10. evaluation_interval: 15s
  11. scrape_configs:
  12. - job_name: 'kubernetes-apiservers'
  13. kubernetes_sd_configs:
  14. - role: endpoints
  15. scheme: https
  16. tls_config:
  17. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  18. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  19. relabel_configs:
  20. - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
  21. action: keep
  22. regex: default;kubernetes;https
  23. - job_name: 'kubernetes-nodes'
  24. kubernetes_sd_configs:
  25. - role: node
  26. scheme: https
  27. tls_config:
  28. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  29. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  30. relabel_configs:
  31. - action: labelmap
  32. regex: __meta_kubernetes_node_label_(.+)
  33. - target_label: __address__
  34. replacement: kubernetes.default.svc:443
  35. - source_labels: [__meta_kubernetes_node_name]
  36. regex: (.+)
  37. target_label: __metrics_path__
  38. replacement: /api/v1/nodes/${1}/proxy/metrics
  39. - job_name: 'kubernetes-cadvisor'
  40. kubernetes_sd_configs:
  41. - role: node
  42. scheme: https
  43. tls_config:
  44. ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  45. bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  46. relabel_configs:
  47. - action: labelmap
  48. regex: __meta_kubernetes_node_label_(.+)
  49. - target_label: __address__
  50. replacement: kubernetes.default.svc:443
  51. - source_labels: [__meta_kubernetes_node_name]
  52. regex: (.+)
  53. target_label: __metrics_path__
  54. replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
  55. - job_name: 'kubernetes-service-endpoints'
  56. kubernetes_sd_configs:
  57. - role: endpoints
  58. relabel_configs:
  59. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
  60. action: keep
  61. regex: true
  62. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
  63. action: replace
  64. target_label: __scheme__
  65. regex: (https?)
  66. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
  67. action: replace
  68. target_label: __metrics_path__
  69. regex: (.+)
  70. - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
  71. action: replace
  72. target_label: __address__
  73. regex: ([^:]+)(?::\d+)?;(\d+)
  74. replacement: $1:$2
  75. - action: labelmap
  76. regex: __meta_kubernetes_service_label_(.+)
  77. - source_labels: [__meta_kubernetes_namespace]
  78. action: replace
  79. target_label: kubernetes_namespace
  80. - source_labels: [__meta_kubernetes_service_name]
  81. action: replace
  82. target_label: kubernetes_name
  83. - job_name: 'kubernetes-services'
  84. kubernetes_sd_configs:
  85. - role: service
  86. metrics_path: /probe
  87. params:
  88. module: [http_2xx]
  89. relabel_configs:
  90. - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
  91. action: keep
  92. regex: true
  93. - source_labels: [__address__]
  94. target_label: __param_target
  95. - target_label: __address__
  96. replacement: blackbox-exporter.example.com:9115
  97. - source_labels: [__param_target]
  98. target_label: instance
  99. - action: labelmap
  100. regex: __meta_kubernetes_service_label_(.+)
  101. - source_labels: [__meta_kubernetes_namespace]
  102. target_label: kubernetes_namespace
  103. - source_labels: [__meta_kubernetes_service_name]
  104. target_label: kubernetes_name
  105. - job_name: 'kubernetes-ingresses'
  106. kubernetes_sd_configs:
  107. - role: ingress
  108. relabel_configs:
  109. - source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe]
  110. action: keep
  111. regex: true
  112. - source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path]
  113. regex: (.+);(.+);(.+)
  114. replacement: ${1}://${2}${3}
  115. target_label: __param_target
  116. - target_label: __address__
  117. replacement: blackbox-exporter.example.com:9115
  118. - source_labels: [__param_target]
  119. target_label: instance
  120. - action: labelmap
  121. regex: __meta_kubernetes_ingress_label_(.+)
  122. - source_labels: [__meta_kubernetes_namespace]
  123. target_label: kubernetes_namespace
  124. - source_labels: [__meta_kubernetes_ingress_name]
  125. target_label: kubernetes_name
  126. - job_name: 'kubernetes-pods'
  127. kubernetes_sd_configs:
  128. - role: pod
  129. relabel_configs:
  130. - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
  131. action: keep
  132. regex: true
  133. - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
  134. action: replace
  135. target_label: __metrics_path__
  136. regex: (.+)
  137. - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
  138. action: replace
  139. regex: ([^:]+)(?::\d+)?;(\d+)
  140. replacement: $1:$2
  141. target_label: __address__
  142. - action: labelmap
  143. regex: __meta_kubernetes_pod_label_(.+)
  144. - source_labels: [__meta_kubernetes_namespace]
  145. action: replace
  146. target_label: kubernetes_namespace
  147. - source_labels: [__meta_kubernetes_pod_name]
  148. action: replace
  149. target_label: kubernetes_pod_name

prometheus.deploy.yml定义Prometheus的部署:

  1. ---
  2. apiVersion: apps/v1beta2
  3. kind: Deployment
  4. metadata:
  5. labels:
  6. name: prometheus-deployment
  7. name: prometheus
  8. namespace: kube-system
  9. spec:
  10. replicas: 1
  11. selector:
  12. matchLabels:
  13. app: prometheus
  14. template:
  15. metadata:
  16. labels:
  17. app: prometheus
  18. spec:
  19. containers:
  20. - image: harbor.frognew.com/prom/prometheus:2.0.0
  21. name: prometheus
  22. command:
  23. - "/bin/prometheus"
  24. args:
  25. - "--config.file=/etc/prometheus/prometheus.yml"
  26. - "--storage.tsdb.path=/prometheus"
  27. - "--storage.tsdb.retention=24h"
  28. ports:
  29. - containerPort: 9090
  30. protocol: TCP
  31. volumeMounts:
  32. - mountPath: "/prometheus"
  33. name: data
  34. - mountPath: "/etc/prometheus"
  35. name: config-volume
  36. resources:
  37. requests:
  38. cpu: 100m
  39. memory: 100Mi
  40. limits:
  41. cpu: 500m
  42. memory: 2500Mi
  43. serviceAccountName: prometheus
  44. imagePullSecrets:
  45. - name: regsecret
  46. volumes:
  47. - name: data
  48. emptyDir: {}
  49. - name: config-volume
  50. configMap:
  51. name: prometheus-config

prometheus.svc.yml定义Prometheus的Servic,需要将Prometheus以NodePort, LoadBalancer或使用Ingress暴露到集群外部,这样外部的Prometheus才能访问它:

  1. ---
  2. kind: Service
  3. apiVersion: v1
  4. metadata:
  5. labels:
  6. app: prometheus
  7. name: prometheus
  8. namespace: kube-system
  9. spec:
  10. type: NodePort
  11. ports:
  12. - port: 9090
  13. targetPort: 9090
  14. nodePort: 30005
  15. selector:
  16. app: prometheus

2.3 配置Prometheus Federation

完成Kubernetes集群上的Prometheus的部署之后,下面将配置集群外部的Prometheus使其从集群内部的Prometheus拉取数据。 实际上只需以静态配置的形式添加一个job就可以:

  1. - job_name: 'federate'
  2. scrape_interval: 15s
  3. honor_labels: true
  4. metrics_path: '/federate'
  5. params:
  6. 'match[]':
  7. - '{job=~"kubernetes-.*"}'
  8. static_configs:
  9. - targets:
  10. - '<nodeip>:30005'

注意上面的配置是外部Prometheus拉取k8s集群上面所有名称以kubernetes-的job的监控数据。

2.4 Kubernetes集群Grafana Dashboard

部署grafana

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: grafana
  5. namespace: kube-system
  6. spec:
  7. type: NodePort
  8. ports:
  9. - port: 3000
  10. targetPort: 3000
  11. nodePort: 30006
  12. selector:
  13. app: grafana
  14. ---
  15. apiVersion: extensions/v1beta1
  16. kind: Deployment
  17. metadata:
  18. labels:
  19. app: grafana
  20. name: grafana
  21. namespace: kube-system
  22. spec:
  23. replicas: 1
  24. revisionHistoryLimit: 2
  25. selector:
  26. matchLabels:
  27. app: grafana
  28. template:
  29. metadata:
  30. labels:
  31. app: grafana
  32. spec:
  33. containers:
  34. - image: grafana/grafana:latest
  35. name: grafana
  36. imagePullPolicy: Always
  37. ports:
  38. - containerPort: 3000
  39. env:
  40. - name: GF_AUTH_BASIC_ENABLED
  41. value: "true"
  42. - name: GF_AUTH_ANONYMOUS_ENABLED
  43. value: "false"
  44. #- name: GF_AUTH_ANONYMOUS_ORG_ROLE
  45. # value: Admin

登录默认账号密码:admin/admin

添加prometheus数据

监控Dashboard使用Kubernetes cluster monitoring (via Prometheus)或315即可。 另外关于Pod和Deployment还有这两个Dashboard:Kubernetes Pod MetricsKubernetes Deployment metrics

2.5 Kubernetes集群告警规则

可以对apiserver和kubelet两个关键组件的存活状态进行监控,规则如下:

  1. up{job=~"kubernetes-apiservers|kubernetes-nodes|kubernetes-cadvisor"} == 0

更多的告警规则可以通过查看上面2.4中的grafana dashboard中监控的关键指标,选择和合适的指标进行设置,实际上一套好的监控系统的监控指标和告警规则并不是越多越好。

3.Kubernetes集群上部署应用的监控

Kubernetes集群上部署应用的监控需要从两个方面:

  • Kubernetes集群上Pod, DaemonSet, Deployment, Job, CronJob等各种资源对象的状态需要监控,这也反映了使用这些资源部署的应用的状态。但通过查看前面Prometheus从k8s集群拉取的指标(这些指标主要来自apiserver和kubelet中集成的cAdvisor),并没有具体的各种资源对象的状态指标。对于Prometheus来说,当然是需要引入新的exporter来暴露这些指标,Kubernetes提供了一个kube-state-metrics正式我们需要。
  • Kubernetes集群上应用内部的监控,这个与具体应用的开发语言,开发框架和具体技术紧密相关,比如Java应用的JVM监控,Go应用的GC监控等等,这个需要应用自身作为Exporter暴露这些指标或在应用的Pod中起一个exporter的sidecar容器。

这里将主要介绍kube-state-metrics,而对于应用内部的监控实践后边有时间再单独总结。kube-state-metrics使用kubernetes的go语言客户端client-go可以从Kubernetes集群中获取各种资源对象的指标。

3.1 在Kubernetes上部署kube-state-metrics

kube-state-metrics已经给出了在Kubernetes部署的manifest定义文件,具体的文件定义都在这里

将kube-state-metrics部署到Kubernetes上之后,就会发现Kubernetes集群中的Prometheus会在kubernetes-service-endpoints这个job下自动服务发现kube-state-metrics,并开始拉取metrics,当然集群外部的Prometheus也能从集群中的Prometheus拉取到这些数据了。这是因为上2.2中prometheus.config.yml中Prometheus的配置文件job kubernetes-service-endpoints的配置。而部署kube-state-metrics的manifest定义文件kube-state-metrics-service.yaml对kube-state-metricsService的定义包含annotation prometheus.io/scrape: ‘true’,因此kube-state-metrics的endpoint可以被Prometheus自动服务发现。

关于kube-state-metrics暴露的所有监控指标可以参考kube-state-metrics的文档kube-state-metrics Documentation

3.2 告警规则

目前我们根据从kube-state-metrics获取的监控指标,制定了以下告警规则:

  • 存在执行失败的Job: kube_job_status_failed{job=”kubernetes-service-endpoints”,k8s_app=”kube-state-metrics”}==1
  • 集群节点状态错误: kube_node_status_condition{condition=”Ready”,status!=”true”}==1
  • 集群节点内存或磁盘资源短缺: kube_node_status_condition{condition=~”OutOfDisk|MemoryPressure|DiskPressure”,status!=”false”}==1
  • 集群中存在失败的PVC:kube_persistentvolumeclaim_status_phase{phase=”Failed”}==1
  • 集群中存在启动失败的Pod:kube_pod_status_phase{phase=~”Failed|Unknown”}==1
  • 最近30分钟内有Pod容器重启: changes(kube_pod_container_status_restarts[30m])>0

其中关于Pod状态的的告警尤为重要,可以在Jenkins完成CI/CD自动发布后,不用守在Kubernetes Dashboard旁边确认这个Deployment关联的Pod已经全部启动,因为如果出现问题是会收到Prometheus的告警的。

参考

相关文章