1.1 深度解读Prometheus
1.1.1 什么是Prometheus?
Prometheus是一个开源的系统监控和报警系统,现在已经加入到CNCF基金会,成为继k8s之后第二个在CNCF托管的项目,在kubernetes容器管理系统中,通常会搭配prometheus进行监控,同时也支持多种exporter采集数据,还支持pushgateway进行数据上报,Prometheus性能足够支撑上万台规模的集群。
1.1.2 prometheus特点
1.多维度数据模型
时间序列数据由metrics名称和键值对来组成
可以对数据进行聚合,切割等操作
所有的metrics都可以设置任意的多维标签。
2.灵活的查询语言(PromQL)
可以对采集的metrics指标进行加法,乘法,连接等操作;
3.可以直接在本地部署,不依赖其他分布式存储;
4.通过基于HTTP的pull方式采集时序数据;
5.可以通过中间网关pushgateway的方式把时间序列数据推送到prometheus server端;
6.可通过服务发现或者静态配置来发现目标服务对象(targets)。
7.有多种可视化图像界面,如Grafana等。
8.高效的存储,每个采样数据占3.5 bytes左右,300万的时间序列,30s间隔,保留60天,消耗磁盘大概200G。
9.做高可用,可以对数据做异地备份,联邦集群,部署多套prometheus,pushgateway上报数据
1.1.3 prometheus组件
从上图可发现,Prometheus整个生态圈组成主要包括prometheus server,Exporter,pushgateway,alertmanager,grafana,Web ui界面,Prometheusserver由三个部分组成,Retrieval,Storage,PromQL
1.Retrieval负责在活跃的target主机上抓取监控指标数据
2.Storage存储主要是把采集到的数据存储到磁盘中
3.PromQL是Prometheus提供的查询语言模块。
1.PrometheusServer:
用于收集和存储时间序列数据。
2.ClientLibrary:
客户端库,检测应用程序代码,当Prometheus抓取实例的HTTP端点时,客户端库会将所有跟踪的metrics指标的当前状态发送到prometheus server端。
3.Exporters:
prometheus支持多种exporter,通过exporter可以采集metrics数据,然后发送到prometheus server端,所有向promtheus server提供监控数据的程序都可以被称为exporter
4.Alertmanager:
从 Prometheusserver 端接收到 alerts 后,会进行去重,分组,并路由到相应的接收方,发出报警,常见的接收方式有:电子邮件,微信,钉钉, slack等。
5.Grafana:
监控仪表盘,可视化监控数据
6.pushgateway:
各个目标主机可上报数据到pushgatewy,然后prometheus server统一从pushgateway拉取数据。
1.1.4 prometheus几种部署模式
基本HA模式
基本的HA模式只能确保Promthues服务的可用性问题,但是不解决Prometheus Server之间的数据一致性问题以及持久化问题(数据丢失后无法恢复),也无法进行动态的扩展。因此这种部署方式适合监控规模不大,Promthues Server也不会频繁发生迁移的情况,并且只需要保存短周期监控数据的场景。
基本HA + 远程存储方案
在解决了Promthues服务可用性的基础上,同时确保了数据的持久化,当Promthues Server发生宕机或者数据丢失的情况下,可以快速的恢复。同时PromthuesServer可能很好的进行迁移。因此,该方案适用于用户监控规模不大,但是希望能够将监控数据持久化,同时能够确保PromthuesServer的可迁移性的场景。
基本HA + 远程存储 + 联邦集群方案
Promthues的性能瓶颈主要在于大量的采集任务,因此用户需要利用Prometheus联邦集群的特性,将不同类型的采集任务划分到不同的Promthues子服务中,从而实现功能分区。例如一个Promthues Server负责采集基础设施相关的监控指标,另外一个Prometheus Server负责采集应用监控指标。再有上层Prometheus Server实现对数据的汇聚。 1.1.5 prometheus工作流程 1. Prometheus server可定期从活跃的(up)目标主机上(target)拉取监控指标数据,目标主机的监控数据可通过配置静态job或者服务发现的方式被prometheus server采集到,这种方式默认的pull方式拉取指标;也可通过pushgateway把采集的数据上报到prometheus server中;还可通过一些组件自带的exporter采集相应组件的数据; 2.Prometheus server把采集到的监控指标数据保存到本地磁盘或者数据库; 3.Prometheus采集的监控指标数据按时间序列存储,通过配置报警规则,把触发的报警发送到alertmanager 4.Alertmanager通过配置报警接收方,发送报警到邮件,微信或者钉钉等 5.Prometheus 自带的web ui界面提供PromQL查询语言,可查询监控数据 6.Grafana可接入prometheus数据源,把监控数据以图形化形式展示出 1.1.6 prometheus如何更好的监控k8s? 对于Kubernetes而言,我们可以把当中所有的资源分为几类: 1、基础设施层(Node):集群节点,为整个集群和应用提供运行时资源 2、容器基础设施(Container):为应用提供运行时环境 3、用户应用(Pod):Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能 4、内部服务负载均衡(Service):在集群内,通过Service在集群暴露应用功能,集群内应用和应用之间访问时提供内部的负载均衡 5、外部访问入口(Ingress):通过Ingress提供集群外的访问入口,从而可以使外部客户端能够访问到部署在Kubernetes集群内的服务 因此,在不考虑Kubernetes自身组件的情况下,如果要构建一个完整的监控体系,我们应该考虑,以下5个方面: 1、集群节点状态监控:从集群中各节点的kubelet服务获取节点的基本运行状态; 2、集群节点资源用量监控:通过Daemonset的形式在集群中各个节点部署Node Exporter采集节点的资源使用情况; 3、节点中运行的容器监控:通过各个节点中kubelet内置的cAdvisor中获取个节点中所有容器的运行状态和资源使用情况; 4、从黑盒监控的角度在集群中部署Blackbox Exporter探针服务,检测Service和Ingress的可用性; 5、如果在集群中部署的应用程序本身内置了对Prometheus的监控支持,那么我们还应该找到相应的Pod实例,并从该Pod实例中获取其内部运行状态的监控指标。
1.2 安装采集节点资源指标组件node-exporter node-exporter是什么? 采集机器(物理机、虚拟机、云主机等)的监控指标数据,能够采集到的指标包括CPU, 内存,磁盘,网络,文件数等信息。 安装node-exporter组件,在k8s集群的控制节点操作 [root@master1 ~]# kubectl create ns monitor-sa namespace/monitor-sa created 把课件里的node-exporter.tar.gz镜像压缩包上传到k8s的各个节点,手动解压: docker load -i node-exporter.tar.gz node-export.yaml文件在课件,可自行上传到自己k8s的控制节点,内容如下: [root@master1 ~]# cat node-export.yaml #通过kubectl apply更新node-exporter [root@master1 ~]# kubectl apply -f node-export.yaml daemonset.apps/node-exporter created #查看node-exporter是否部署成功 [root@master1 ~]# kubectl get pods -n monitor-sa NAME READY STATUS RESTARTS AGE node-exporter-7cjhw 1/1 Running 0 22s node-exporter-8m2fp 1/1 Running 0 22s node-exporter-c6sdq 1/1 Running 0 22s 通过node-exporter采集数据 curl http://主机ip:9100/metrics #node-export默认的监听端口是9100,可以看到当前主机获取到的所有监控数据 curl http://192.168.40.130:9100/metrics | grep node_cpu_seconds 显示192.168.40.130主机cpu的使用情况 # HELP node_cpu_seconds_total Seconds the cpus spent in each mode. # TYPE node_cpu_seconds_total counter node_cpu_seconds_total{cpu="0",mode="idle"} 72963.37 node_cpu_seconds_total{cpu="0",mode="iowait"} 9.35 node_cpu_seconds_total{cpu="0",mode="irq"} 0 node_cpu_seconds_total{cpu="0",mode="nice"} 0 node_cpu_seconds_total{cpu="0",mode="softirq"} 151.4 node_cpu_seconds_total{cpu="0",mode="steal"} 0 node_cpu_seconds_total{cpu="0",mode="system"} 656.12 node_cpu_seconds_total{cpu="0",mode="user"} 267.1 #HELP:解释当前指标的含义,上面表示在每种模式下node节点的cpu花费的时间,以s为单位 #TYPE:说明当前指标的数据类型,上面是counter类型 node_cpu_seconds_total{cpu="0",mode="idle"} : cpu0上idle进程占用CPU的总时间,CPU占用时间是一个只增不减的度量指标,从类型中也可以看出node_cpu的数据类型是counter(计数器) counter计数器:只是采集递增的指标 curl http://192.168.40.130:9100/metrics | grep node_load # HELP node_load1 1m load average. # TYPE node_load1 gauge node_load1 0.1 node_load1该指标反映了当前主机在最近一分钟以内的负载情况,系统的负载情况会随系统资源的使用而变化,因此node_load1反映的是当前状态,数据可能增加也可能减少,从注释中可以看出当前指标类型为gauge(标准尺寸) gauge标准尺寸:统计的指标可增加可减少 1.3 在k8s集群中安装Prometheus server服务 1.3.1 创建sa账号 #在k8s集群的控制节点操作,创建一个sa账号 [root@master1 ~]# kubectl create serviceaccount monitor -n monitor-sa serviceaccount/monitor created #把sa账号monitor通过clusterrolebing绑定到clusterrole上 [root@master1 ~]# kubectl create clusterrolebinding monitor-clusterrolebinding -n monitor-sa --clusterrole=cluster-admin --serviceaccount=monitor-sa:monitor 1.3.2 创建数据目录 #在node1作节点创建存储数据的目录: [root@node1 ~]# mkdir /data [root@node1 ~]# chmod 777 /data/ 1.3.3 安装prometheus服务 以下步骤均在k8s集群的控制节点操作: 创建一个configmap存储卷,用来存放prometheus配置信息 prometheus-cfg.yaml文件在课件,可自行上传到自己k8s的控制节点,内容如下: [root@master1 ~]# cat prometheus-cfg.yaml #通过kubectl apply更新configmap [root@master1 ~]# kubectl apply -f prometheus-cfg.yaml configmap/prometheus-config created 通过deployment部署prometheus 安装prometheus server需要的镜像prometheus-2-2-1.tar.gz在课件,上传到k8s的工作节点node1上,手动解压: docker load -i prometheus-2-2-1.tar.gz prometheus-deploy.yaml文件在课件,上传到自己的k8s的控制节点,内容如下: [root@master1 ~]# cat prometheus-deploy.yaml 注意:在上面的prometheus-deploy.yaml文件有个nodeName字段,这个就是用来指定创建的这个prometheus的pod调度到哪个节点上,我们这里让nodeName=node1,也即是让pod调度到node1节点上,因为node1节点我们创建了数据目录/data,所以大家记住:你在k8s集群的哪个节点创建/data,就让pod调度到哪个节点。 #通过kubectl apply更新prometheus [root@master1 ~]# kubectl apply -f prometheus-deploy.yaml deployment.apps/prometheus-server created #查看prometheus是否部署成功 [root@master1 ~]# kubectl get pods -n monitor-sa NAME READY STATUS RESTARTS AGE node-exporter-7cjhw 1/1 Running 0 6m33s node-exporter-8m2fp 1/1 Running 0 6m33s node-exporter-c6sdq 1/1 Running 0 6m33s prometheus-server-6fffccc6c9-bhbpz 1/1 Running 0 26s 给prometheus pod创建一个service prometheus-svc.yaml文件在课件,可上传到k8s的控制节点,内容如下: cat prometheus-svc.yaml --- apiVersion: v1 kind: Service metadata: name: prometheus namespace: monitor-sa labels: app: prometheus spec: type: NodePort ports: - port: 9090 targetPort: 9090 protocol: TCP selector: app: prometheus component: server #通过kubectl apply 更新service [root@master1 ~]# kubectl apply -f prometheus-svc.yaml service/prometheus created #查看service在物理机映射的端口 [root@master1 ~]# kubectl get svc -n monitor-sa NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE prometheus NodePort 10.103.98.225 <none> 9090:30009/TCP 27s 通过上面可以看到service在宿主机上映射的端口是30009,这样我们访问k8s集群的控制节点的ip:30009,就可以访问到prometheus的web ui界面了 #访问prometheus web ui界面 火狐浏览器输入如下地址: http://192.168.40.130:30009/graph 可看到如下页面:
1.4 安装和配置可视化UI界面Grafana 安装Grafana需要的镜像heapster-grafana-amd64_v5_0_4.tar.gz在课件里,把镜像上传到k8s的各个控制节点和k8s的各个工作节点,然后在各个节点手动解压: docker load -i heapster-grafana-amd64_v5_0_4.tar.gz grafana.yaml文件在课件里,可上传到k8s的控制节点,内容如下: [root@master1 ~]# cat grafana.yaml apiVersion: apps/v1 kind: Deployment metadata: name: monitoring-grafana namespace: kube-system spec: replicas: 1 selector: matchLabels: task: monitoring k8s-app: grafana template: metadata: labels: task: monitoring k8s-app: grafana spec: containers: - name: grafana image: k8s.gcr.io/heapster-grafana-amd64:v5.0.4 ports: - containerPort: 3000 protocol: TCP volumeMounts: - mountPath: /etc/ssl/certs name: ca-certificates readOnly: true - mountPath: /var name: grafana-storage env: - name: INFLUXDB_HOST value: monitoring-influxdb - name: GF_SERVER_HTTP_PORT value: "3000" # The following env variables are required to make Grafana accessible via # the kubernetes api-server proxy. On production clusters, we recommend # removing these env variables, setup auth for grafana, and expose the grafana # service using a LoadBalancer or a public IP. - name: GF_AUTH_BASIC_ENABLED value: "false" - name: GF_AUTH_ANONYMOUS_ENABLED value: "true" - name: GF_AUTH_ANONYMOUS_ORG_ROLE value: Admin - name: GF_SERVER_ROOT_URL # If you're only using the API Server proxy, set this value instead: # value: /api/v1/namespaces/kube-system/services/monitoring-grafana/proxy value: / volumes: - name: ca-certificates hostPath: path: /etc/ssl/certs - name: grafana-storage emptyDir: {} --- apiVersion: v1 kind: Service metadata: labels: # For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons) # If you are NOT using this as an addon, you should comment out this line. kubernetes.io/cluster-service: 'true' kubernetes.io/name: monitoring-grafana name: monitoring-grafana namespace: kube-system spec: # In a production setup, we recommend accessing Grafana through an external Loadbalancer # or through a public IP. # type: LoadBalancer # You could also use NodePort to expose the service at a randomly-generated port # type: NodePort ports: - port: 80 targetPort: 3000 selector: k8s-app: grafana type: NodePort #更新yaml文件 [root@master1 ~]# kubectl apply -f grafana.yaml deployment.apps/monitoring-grafana created service/monitoring-grafana created #验证是否安装成功 [root@master1 ~]# kubectl get pods -n kube-system| grep monitor monitoring-grafana-675798bf47-4rp2b 1/1 Running 0 #查看grafana前端的service [root@master1 ~]# kubectl get svc -n kube-system | grep grafana monitoring-grafana NodePort 10.100.56.76 <none> 80:30989/TCP #登陆grafana,在浏览器访问 192.168.40.130:30989 可看到如下界面:
#配置grafana界面
开始配置grafana的web界面:
选择Create your first data source
出现如下
Name:Prometheus
Type:Prometheus
HTTP 处的URL如下:
http://prometheus.monitor-sa.svc:9090
配置好的整体页面如下:
点击左下角Save& Test,出现如下Data source is working,说明prometheus数据源成功的被grafana接入了:
导入监控模板,可在如下链接搜索
https://grafana.com/dashboards?dataSource=prometheus&search=kubernetes
可直接导入node_exporter.json监控模板,这个可以把node节点指标显示出来
node_exporter.json在课件里,也可直接导入docker_rev1.json,这个可以把容器资源指标显示出来,node_exporter.json和docker_rev1.json都在课件里
怎么导入监控模板,按如下步骤
上面Save& Test测试没问题之后,就可以返回Grafana主页面
点击左侧+号下面的Import
出现如下界面:
选择Upload json file,出现如下
选择一个本地的json文件,我们选择的是上面让大家下载的node_exporter.json这个文件,选择之后出现如下:
注:箭头标注的地方Name后面的名字是node_exporter.json定义的
Prometheus后面需要变成Prometheus,然后再点击Import,就可以出现如下界面:
导入docker_rev1.json监控模板,步骤和上面导入node_exporter.json步骤一样,导入之后显示如下:
1.5 kube-state-metrics组件解读 1.5.1 什么是kube-state-metrics? kube-state-metrics通过监听API Server生成有关资源对象的状态指标,比如Deployment、Node、Pod,需要注意的是kube-state-metrics只是简单的提供一个metrics数据,并不会存储这些指标数据,所以我们可以使用Prometheus来抓取这些数据然后存储,主要关注的是业务相关的一些元数据,比如Deployment、Pod、副本状态等;调度了多少个replicas?现在可用的有几个?多少个Pod是running/stopped/terminated状态?Pod重启了多少次?我有多少job在运行中。 1.5.2 安装和配置kube-state-metrics 创建sa,并对sa授权 在k8s的控制节点生成一个kube-state-metrics-rbac.yaml文件,kube-state-metrics-rbac.yaml文件在课件,大家自行下载到k8s的控制节点即可,内容如下: [root@master1 ~]# cat kube-state-metrics-rbac.yaml --- apiVersion: v1 kind: ServiceAccount metadata: name: kube-state-metrics namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: kube-state-metrics rules: - apiGroups: [""] resources: ["nodes", "pods", "services", "resourcequotas", "replicationcontrollers", "limitranges", "persistentvolumeclaims", "persistentvolumes", "namespaces", "endpoints"] verbs: ["list", "watch"] - apiGroups: ["extensions"] resources: ["daemonsets", "deployments", "replicasets"] verbs: ["list", "watch"] - apiGroups: ["apps"] resources: ["statefulsets"] verbs: ["list", "watch"] - apiGroups: ["batch"] resources: ["cronjobs", "jobs"] verbs: ["list", "watch"] - apiGroups: ["autoscaling"] resources: ["horizontalpodautoscalers"] verbs: ["list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kube-state-metrics roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: kube-state-metrics subjects: - kind: ServiceAccount name: kube-state-metrics namespace: kube-system 通过kubectl apply更新yaml文件 [root@master1 ~]# kubectl apply -f kube-state-metrics-rbac.yaml serviceaccount/kube-state-metrics created clusterrole.rbac.authorization.k8s.io/kube-state-metrics created clusterrolebinding.rbac.authorization.k8s.io/kube-state-metrics created 安装kube-state-metrics组件 安装kube-state-metrics组件需要的镜像在课件,可上传到k8s各个工作节点,手动解压: docker load -i kube-state-metrics_1_9_0.tar.gz 在k8s的master1节点生成一个kube-state-metrics-deploy.yaml文件,kube-state-metrics-deploy.yaml在课件,可自行下载,内容如下: [root@master1 ~]# cat kube-state-metrics-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: kube-state-metrics namespace: kube-system spec: replicas: 1 selector: matchLabels: app: kube-state-metrics template: metadata: labels: app: kube-state-metrics spec: serviceAccountName: kube-state-metrics containers: - name: kube-state-metrics image: quay.io/coreos/kube-state-metrics:v1.9.0 ports: - containerPort: 8080 通过kubectl apply更新yaml文件 [root@master1 ~]# kubectl apply -f kube-state-metrics-deploy.yaml deployment.apps/kube-state-metrics created 查看kube-state-metrics是否部署成功 [root@master1 ~]# kubectl get pods -n kube-system -l app=kube-state-metrics NAME READY STATUS RESTARTS AGE kube-state-metrics-58d4957bc5-9thsw 1/1 Running 0 30s 创建service 在k8s的控制节点生成一个kube-state-metrics-svc.yaml文件,kube-state-metrics-svc.yaml文件在课件,可上传到k8s的控制节点,内容如下: [root@master1 ~]# cat kube-state-metrics-svc.yaml apiVersion: v1 kind: Service metadata: annotations: prometheus.io/scrape: 'true' name: kube-state-metrics namespace: kube-system labels: app: kube-state-metrics spec: ports: - name: kube-state-metrics port: 8080 protocol: TCP selector: app: kube-state-metrics 通过kubectl apply更新yaml [root@master1 ~]# kubectl apply -f kube-state-metrics-svc.yaml service/kube-state-metrics created 查看service是否创建成功 [root@master1 ~]# kubectl get svc -n kube-system | grep kube-state-metrics kube-state-metrics ClusterIP 10.105.160.224 <none> 8080/TCP 在grafana web界面导入Kubernetes Cluster (Prometheus)-1577674936972.json和Kubernetes cluster monitoring (via Prometheus) (k8s 1.16)-1577691996738.json,Kubernetes Cluster (Prometheus)-1577674936972.json和Kubernetes cluster monitoring (via Prometheus) (k8s 1.16)-1577691996738.json文件在课件 导入Kubernetes Cluster (Prometheus)-1577674936972.json之后出现如下页面
在grafana web界面导入Kubernetes cluster monitoring(via Prometheus) (k8s 1.16)-1577691996738.json,出现如下页面