Prometheus监控实践:Kubernetes集群监控
本文将总结一下我们目前使用Prometheus对Kubernetes集群监控的实践。 我们选择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的配置示例:
- job_name: 'federate' scrape_interval: 15s honor_labels: true metrics_path: '/federate' params: 'match[]': - '{job="prometheus"}' - '{__name__=~"job:.*"}' static_configs: - targets: - 'source-prometheus-1:9090' - 'source-prometheus-2:9090' - '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源码中库中的例子:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: prometheus rules: - apiGroups: [""] resources: - nodes - nodes/proxy - services - endpoints - pods verbs: ["get", "list", "watch"] - apiGroups: - extensions resources: - ingresses verbs: ["get", "list", "watch"] - nonResourceURLs: ["/metrics"] verbs: ["get"] --- apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: prometheus roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: prometheus subjects: - kind: ServiceAccount name: prometheus namespace: kube-system
prometheus.config.yml configmap中的prometheus的配置文件,参考Prometheus源码中库中的例子:
apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: kube-system data: prometheus.yml: | global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'kubernetes-apiservers' kubernetes_sd_configs: - role: endpoints scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] action: keep regex: default;kubernetes;https - job_name: 'kubernetes-nodes' kubernetes_sd_configs: - role: node scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics - job_name: 'kubernetes-cadvisor' kubernetes_sd_configs: - role: node scheme: https tls_config: ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token relabel_configs: - action: labelmap regex: __meta_kubernetes_node_label_(.+) - target_label: __address__ replacement: kubernetes.default.svc:443 - source_labels: [__meta_kubernetes_node_name] regex: (.+) target_label: __metrics_path__ replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor - job_name: 'kubernetes-service-endpoints' kubernetes_sd_configs: - role: endpoints relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme] action: replace target_label: __scheme__ regex: (https?) - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] action: replace target_label: __address__ regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] action: replace target_label: kubernetes_name - job_name: 'kubernetes-services' kubernetes_sd_configs: - role: service metrics_path: /probe params: module: [http_2xx] relabel_configs: - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe] action: keep regex: true - source_labels: [__address__] target_label: __param_target - target_label: __address__ replacement: blackbox-exporter.example.com:9115 - source_labels: [__param_target] target_label: instance - action: labelmap regex: __meta_kubernetes_service_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_service_name] target_label: kubernetes_name - job_name: 'kubernetes-ingresses' kubernetes_sd_configs: - role: ingress relabel_configs: - source_labels: [__meta_kubernetes_ingress_annotation_prometheus_io_probe] action: keep regex: true - source_labels: [__meta_kubernetes_ingress_scheme,__address__,__meta_kubernetes_ingress_path] regex: (.+);(.+);(.+) replacement: ${1}://${2}${3} target_label: __param_target - target_label: __address__ replacement: blackbox-exporter.example.com:9115 - source_labels: [__param_target] target_label: instance - action: labelmap regex: __meta_kubernetes_ingress_label_(.+) - source_labels: [__meta_kubernetes_namespace] target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_ingress_name] target_label: kubernetes_name - job_name: 'kubernetes-pods' kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] action: keep regex: true - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] action: replace target_label: __metrics_path__ regex: (.+) - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] action: replace regex: ([^:]+)(?::\d+)?;(\d+) replacement: $1:$2 target_label: __address__ - action: labelmap regex: __meta_kubernetes_pod_label_(.+) - source_labels: [__meta_kubernetes_namespace] action: replace target_label: kubernetes_namespace - source_labels: [__meta_kubernetes_pod_name] action: replace target_label: kubernetes_pod_name
prometheus.deploy.yml定义Prometheus的部署:
--- apiVersion: apps/v1beta2 kind: Deployment metadata: labels: name: prometheus-deployment name: prometheus namespace: kube-system spec: replicas: 1 selector: matchLabels: app: prometheus template: metadata: labels: app: prometheus spec: containers: - image: harbor.frognew.com/prom/prometheus:2.0.0 name: prometheus command: - "/bin/prometheus" args: - "--config.file=/etc/prometheus/prometheus.yml" - "--storage.tsdb.path=/prometheus" - "--storage.tsdb.retention=24h" ports: - containerPort: 9090 protocol: TCP volumeMounts: - mountPath: "/prometheus" name: data - mountPath: "/etc/prometheus" name: config-volume resources: requests: cpu: 100m memory: 100Mi limits: cpu: 500m memory: 2500Mi serviceAccountName: prometheus imagePullSecrets: - name: regsecret volumes: - name: data emptyDir: {} - name: config-volume configMap: name: prometheus-config
prometheus.svc.yml定义Prometheus的Servic,需要将Prometheus以NodePort, LoadBalancer或使用Ingress暴露到集群外部,这样外部的Prometheus才能访问它:
--- kind: Service apiVersion: v1 metadata: labels: app: prometheus name: prometheus namespace: kube-system spec: type: NodePort ports: - port: 9090 targetPort: 9090 nodePort: 30003 selector: app: prometheus
2.3 配置Prometheus Federation
完成Kubernetes集群上的Prometheus的部署之后,下面将配置集群外部的Prometheus使其从集群内部的Prometheus拉取数据。 实际上只需以静态配置的形式添加一个job就可以:
- job_name: 'federate' scrape_interval: 15s honor_labels: true metrics_path: '/federate' params: 'match[]': - '{job=~"kubernetes-.*"}' static_configs: - targets: - '<nodeip>:30003'
注意上面的配置是外部Prometheus拉取k8s集群上面所有名称以kubernetes-的job的监控数据。
2.4 Kubernetes集群Grafana Dashboard
监控Dashboard使用Kubernetes cluster monitoring (via Prometheus)这个即可。 另外关于Pod和Deployment还有这两个Dashboard:Kubernetes Pod Metrics和Kubernetes Deployment metrics。
2.5 Kubernetes集群告警规则
可以对apiserver和kubelet两个关键组件的存活状态进行监控,规则如下:
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的告警的。
本文转自kubernetes中文社区-Prometheus监控实践:Kubernetes集群监控
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
从美图容器优化实践谈Kubernetes网络方案设计
本文通过介绍美图线上容器化的实践经验,包括线上遇到的实际问题,来探讨 Kubernetes 环境下的网络方案设计。值得正在转型 K8S 的架构师学习和借鉴。 李连荣,美图高级系统研发工程师,曾建立支持千万的长连接服务,从零开始在建立美图的容器化服务,并主导完成美图容器化的网络方案。在网络、存储方面有非常深厚的造诣。 目前,我们的 Kubernetes 集群选择使用 Calico 作为基础网络方案。 选择 Calico 网络方案的挑战 Calico 是一套基于路由(BGP)的 SDN,它通过路由转发的方式实现容器的跨主机通信。Calico 将每个节点虚拟为一个“路由器”并为之分配独立的虚拟网段,该路由器为当前节点上的容器提供路由服务。 更多 Calico 项目介绍可参阅 https://www.projectcalico.org/ 下面以具体网络为例介绍其中的设计与难点。 以上图为例,如果节点 192.168.1.2 分配的虚拟网段是 10.233.1.0/24,其上运行了一个容器 10.233.1.2,其路由信息如下: 10.233.1.2 0.0.0.0 255.255.255.25...
- 下一篇
kubernetes 中的 ConfigMap 和 Secret
为什么要有这俩玩意儿? 我们在kubernetes上部署应用的时候,经常会需要传一些配置给我们的应用,比如数据库地址啊,用户名密码啊之类的。我们要做到这个,有好多种方案,比如: 我们可以直接在打包镜像的时候写在应用配置文件里面,但是这种方式的坏处显而易见而且非常明显。 我们可以在配置文件里面通过env环境变量传入,但是这样的话我们要修改env就必须去修改yaml文件,而且需要重启所有的container才行。 我们可以在应用启动的时候去数据库或者某个特定的地方拿,没问题!但是第一,实现起来麻烦;第二,如果配置的地方变了怎么办? 当然还有别的方案,但是各种方案都有各自的问题。 而且,还有一个问题就是,如果说我的一个配置,是要多个应用一起使用的,以上除了第三种方案,都没办法进行配置的共享,就是说我如果要改配置的话,那得一个一个手动改。假如我们有100个应用,就得改100份配置,以此类推…… kubernetes对这个问题提供了一个很好的解决方案,就是用ConfigMap和Secret。 创建ConfigMap ConfigMap让我们能够从容器镜像中把配置的详细信息给解耦出来。通过Conf...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS8编译安装MySQL8.0.19
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS关闭SELinux安全模块
- Hadoop3单机部署,实现最简伪集群
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2更换Tomcat为Jetty,小型站点的福音