kubernetes监控之prometheus

  • 一、TSDB数据库简介:

TSDB(Time Series Database)时序列数据库,我们可以简单的理解为一个优化后用来处理时间序列数据的软件,并且数据中的数组是由时间进行索引的。

1、时间序列数据库的特点

  • 大部分时间都是写入操作。

  • 写入操作几乎是顺序添加,大多数时候数据到达后都以时间排序。

  • 写操作很少写入很久之前的数据,也很少更新数据。大多数情况在数据被采集到数秒或者数分钟后就会被写入数据库。

  • 删除操作一般为区块删除,选定开始的历史时间并指定后续的区块。很少单独删除某个时间或者分开的随机时间的数据。

  • 基本数据大,一般超过内存大小。一般选取的只是其一小部分且没有规律,缓存几乎不起任何作用。

  • 读操作是十分典型的升序或者降序的顺序读。

  • 高并发的读操作十分常见。

2、常见的时间序列数据库

  • TSDB项目    官网
    influxDB      RRDtool      Graphite      OpenTSDB      Kdb+      Druid      KairosDB      Prometheus    https://prometheus.io/
  • 二、prometheus简介:

 

            Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB)。Prometheus使用Go语言开发,是Google BorgMon监控系统的开源版本。

2016年由Google发起Linux基金会旗下的原生云基金会(Cloud Native Computing Foundation), 将Prometheus纳入其下第二大开源项目。Prometheus目前在开源社区相当活跃。

Prometheus和Heapster(Heapster是K8S的一个子项目,用于获取集群的性能数据。)相比功能更完善、更全面。Prometheus性能也足够支撑上万台规模的集群。

2.1、Prometheus的特点

  • 多维度数据模型。

  • 灵活的查询语言。

  • 不依赖分布式存储,单个服务器节点是自主的。

  • 通过基于HTTP的pull方式采集时序数据。

  • 可以通过中间网关进行时序列数据推送。

  • 通过服务发现或者静态配置来发现目标服务对象。

  • 支持多种多样的图表和界面展示,比如Grafana等

2.2、Prometheus相关组件

  • Prometheus Server

主要负责数据采集和存储,提供PromQL查询语言的支持。

  • 客户端SDK

官方提供的客户端类库有go、java、scala、python、ruby,其他还有很多第三方开发的类库,支持nodejs、php、erlang等。

  • Push Gateway

支持临时性Job主动推送指标的中间网关。

  • PromDash

使用Rails开发可视化的Dashboard,用于可视化指标数据。

  • Exporter

Exporter是Prometheus的一类数据采集组件的总称。它负责从目标处搜集数据,并将其转化为Prometheus支持的格式。与传统的数据采集组件不同的是,它并不向中央服务器发送数据,而是等待中央服务器主动前来抓取。

Prometheus提供多种类型的Exporter用于采集各种不同服务的运行状态。目前支持的有数据库、硬件、消息中间件、存储系统、HTTP服务器、JMX等。

  • alertmanager

警告管理器,用来进行报警。

  • prometheus_cli

命令行工具。

  • 其他辅助性工具

prometheus架构

Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控。不需要任何SDK或者其他的集成过程。这样做非常适合做虚拟化环境监控系统,比如VM、Docker、Kubernetes等。输出被监控组件信息的HTTP接口被叫做exporter 。目前互联网公司常用的组件大部分都有exporter可以直接使用,比如Varnish、Haproxy、Nginx、MySQL、Linux系统信息(包括磁盘、内存、CPU、网络等等)。

 

3、Prometheus服务过程

  • Prometheus Daemon负责定时去目标上抓取metrics(指标)数据,每个抓取目标需要暴露一个http服务的接口给它定时抓取。Prometheus支持通过配置文件、文本文件、Zookeeper、Consul、DNS SRV Lookup等方式指定抓取目标。Prometheus采用PULL的方式进行监控,即服务器可以直接通过目标PULL数据或者间接地通过中间网关来Push数据。

  • Prometheus在本地存储抓取的所有数据,并通过一定规则进行清理和整理数据,并把得到的结果存储到新的时间序列中。

  • Prometheus通过PromQL和其他API可视化地展示收集的数据。Prometheus支持很多方式的图表可视化,例如Grafana、自带的Promdash以及自身提供的模版引擎等等。Prometheus还提供HTTP API的查询方式,自定义所需要的输出。

  • PushGateway支持Client主动推送metrics到PushGateway,而Prometheus只是定时去Gateway上抓取数据。

  • Alertmanager是独立于Prometheus的一个组件,可以支持Prometheus的查询语句,提供十分灵活的报警方式。

4、Prometheus适用的场景

Prometheus在记录纯数字时间序列方面表现非常好。它既适用于面向服务器等硬件指标的监控,也适用于高动态的面向服务架构的监控。对于现在流行的微服务,Prometheus的多维度数据收集和数据筛选查询语言也是非常的强大。Prometheus是为服务的可靠性而设计的,当服务出现故障时,它可以使你快速定位和诊断问题。它的搭建过程对硬件和服务没有很强的依赖关系

5、Prometheus不适用的场景

Prometheus它的价值在于可靠性,甚至在很恶劣的环境下,你都可以随时访问它和查看系统服务各种指标的统计信息。 如果你对统计数据需要100%的精确,它并不适用,例如:它不适用于实时计费系统。

Prometheus官网:https://prometheus.io/

 

  • 三、在kubernetes集群部署prometheus

3.1  配置prometheus的configmap

apiVersion: v1

kind: ConfigMap

metadata:

      name: prometheus-config

      namespace: kube-ops

data:

    prometheus.yml: |

       global:

           scrape_interval: 15s

           scrape_timeout: 15s

       scrape_configs:

       -  job_name: 'prometheus'

          static_configs:

          - targets: ['localhost:9090']

 

在创建configmap之前,先需要创建一个namespace kube-ops

kubectl create ns kube-ops

[root@kubemaster prometheus]# kubectl get ns  查看kube-ops的namespace已经创建了
NAME          STATUS   AGE
default       Active   9d
kube-ops      Active   4s
kube-public   Active   9d
kube-system   Active   9d

[root@kubemaster prometheus]# kubectl apply -f prometheus-cm.yaml   创建一个configmap成功,现在prometheus已经具备了配置文件,配置文件的内容是暴露自身的metrics
configmap/prometheus-config created
[root@kubemaster prometheus]#

[root@kubemaster prometheus]# kubectl get cm -n kube-ops  #查看configmap是否创建成功
NAME                DATA   AGE
prometheus-config   1      44m
[root@kubemaster prometheus]#

[root@kubemaster prometheus]# kubectl describe configmaps -n kube-ops prometheus-config   #查看prometheus configmap的配置文件内容
Name:         prometheus-config
Namespace:    kube-ops
Labels:       <none>
Annotations:  kubectl.kubernetes.io/last-applied-configuration:
                {"apiVersion":"v1","data":{"prometheus.yml":"global:\n  scrape_interval: 15s\n  scrape_timeout: 15s\nscrape_configs:\n- job_name: 'prometh...

Data
====
prometheus.yml:
----
global:
  scrape_interval: 15s
  scrape_timeout: 15s
scrape_configs:
- job_name: 'prometheus'
  static_configs:
  - targets: ['localhost:9090']

Events:  <none>
[root@kubemaster prometheus]#


 

3.2  配置prometheus的deployment资源  vim prometheus-deployment.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
      name: prometheus 
      namespace: kube-ops 
      labels:
         app: prometheus
spec:
     template:
          metadata:
                  labels:
                      app: prometheus   
    spec:
         serviceAccountName: prometheus #此处的SA账户权限需要提前创建,并且要配置好ClusterRole和ClusterRoleBinding    
         containers:
          -  image: prom/prometheus:v2.4.3       
              name: prometheus
              args:
             - "--config.file=/etc/prometheus/prometheus.yml" #这里的配置文件就是第一步创建的configmap挂载到容器里面的文件
             - "--storage.tsdb.path=/prometheus"
             - "--storage.tsdb.retention=24h"
             - "--web.enable-admin-api"  # 控制对admin HTTP API的访问,其中包括删除时间序列等功能
             - "--web.enable-lifecycle"  # 支持热更新,直接执行localhost:9090/-/reload立即生效
             ports:
             -  containerPort: 9090
                protocol: TCP         
                name: http       
            volumeMounts:
            - mountPath: "/prometheus"
              subPath: prometheus         
               name: data       
           - mountPath: "/etc/prometheus"
              name: config-volume       
            resources:
               requests:
                    cpu: 100m           
                   memory: 512Mi         
             limits:
                 cpu: 100m           
                 memory: 512Mi     
             securityContext:
                  runAsUser: 0
      volumes:
      - name: data       
        persistentVolumeClaim:
          claimName: prometheus #这里的persistenVolumeClaim 需要提前创建PVC
      - configMap:
          name: prometheus-config #这里的就是configmap配置文件 
        name: config-volume

#我们在启动程序的时候,除了指定了 prometheus.yml 文件之外,还通过参数storage.tsdb.path指定了 TSDB 数据的存储路径

#通过storage.tsdb.retention设置了保留多长时间的数据,还有下面的web.enable-admin-api参数可以用来开启对 admin api 的访问权限

#参数web.enable-lifecycle非常重要,用来开启支持热更新的,有了这个参数之后,prometheus.yml 配置文件只要更新了,通过执行localhost:9090/-/reload就会立即生效,所以一定要加上这个参数。

#我们这里将 prometheus.yml 文件对应的 ConfigMap 对象通过 volume 的形式挂载进了 Pod,这样 ConfigMap 更新后,对应的 Pod 里面的文件也会热更新的,然后我们再执行上面的 reload 请求,

Prometheus 配置就生效了,除此之外,为了将时间序列数据进行持久化,我们将数据目录和一个 pvc 对象进行了绑定,所以我们需要提前创建好这个 pvc 对象:

#还有一个要注意的地方是我们这里必须要添加一个securityContext的属性,将其中的runAsUser设置为0,这是因为现在的 prometheus 运行过程中使用的用户是 nobody,否则会出现下面的permission denied之类的权限错误:

3.3  创建prometheus需要的持久化存储对象PVC

      vim prometheus-volume.yaml

 

apiVersion: v1
kind: PersistentVolume
metadata:
       name: prometheus
spec:
      capacity:
           storage: 10Gi 
      accessModes:
      -   ReadWriteOnce 
       persistentVolumeReclaimPolicy: Recycle 
       nfs:
            server: 10.83.32.146
            path: /data/k8s

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
       name: prometheus 
       namespace: kube-ops
spec:
     accessModes:
      - ReadWriteOnce 
     resources:
         requests:
              storage: 10Gi

需要提前在10.83.32.146这台机器上面创建一个共享的NFS存储

mkdir –p /data/k8s && chmod –R 777 /data/k8s

vim /etc/exports

/data/k8s *(rw,sync,no_root_squash,no_subtree_check)

systemctl start nfs

showmount  –e 10.83.32.146

Export list for 10.83.32.146:
/data/k8s

其他的k8s node节点都需要安装nfs-utils工具,不然无法挂载NFS共享存储 yum –y install nfs-utils

kubectl  apply  –f  prometheus-volume.yaml

kubectl get pvc –n kube-ops

NAME         STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS   AGE
prometheus   Bound    prometheus   10Gi       RWO                           8s


4、创建prometheus启动需要的SA账户,只有具体有特殊的权限,prometheus应用才可以读取API Sever和POD的相关数据

vim prometheus-rbac.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
       name: prometheus 
       namespace: kube-ops

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
      name: prometheus
rules:
-   apiGroups: [""]
     resources:
     - nodes 
     - services 
     - endpoints 
     - pods 
      - nodes/proxy 
     verbs: ["get", "list", "watch"]
-  apiGroups: [""]
    resources:
     - configmaps 
       verbs: ["get"]
    - nonResourceURLs:  ["/metics"]  # 对非资源型 endpoint metrics 进行 get 操作
       verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind:  ClusterRoleBinding
metadata:
      name: prometheus
roleRef:
      apiGroup: rbac.authorization.k8s.io 
      kind: ClusterRole 
      name: prometheus
subjects:
-   kind: ServiceAccount 
    name: prometheus 
    namespace: kube-ops

kubectl apply -f prometheus-rbac.yaml

serviceaccount/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created

[root@kubemaster prometheus]# kubectl get sa -n kube-ops
NAME         SECRETS   AGE
default      1         35m
prometheus   1         9s

[root@kubemaster prometheus]# kubectl get ClusterRole -n kube-ops|grep prometheus
prometheus

[root@kubemaster prometheus]# kubectl get ClusterRoleBinding -n kube-ops|grep prometheus
prometheus

#由于我们要获取的资源信息,在每一个 namespace 下面都有可能存在,所以我们这里使用的是 ClusterRole 的资源对象,值得一提的是我们这里的权限规则声明中有一个nonResourceURLs的属性,是用来对非资源型 metrics 进行操作的权限声明,这个在以前我们很少遇到过,然后直接创建上面的资源对象即可:

5、配置prometheus的svc,用于访问prometheus。我们这里使用NodePort类型

vim prometheus-svc.yaml

 

apiVersion: v1
kind:  Service
metadata:
       name: prometheus
       namespace: kube-ops
       labels:
           app: prometheus
spec:
     selector:
          app: prometheus
     type: NodePort
     ports:
      - name: web
         port: 9090
         targetPort: http   #这里的targetPort用的是名称http,因为http的名称在prometheus-deployment.yaml里面已经定义过了

现在已经创建好了prometheus的configmap  pvc  sa  svc  deployment五个资源了。启动的顺序是

configmap--->pvc--->sa--->deployment--->svc 

目前我们已经成功启动了prometheus的configmap、pvc、sa账户,现在开始启动deployment和svc

kubectl apply –f prometheus-deployment.yaml

[root@kubemaster prometheus]# kubectl get pods -n kube-ops
NAME                          READY   STATUS    RESTARTS   AGE
prometheus-848d44c7bc-54cpr   1/1     Running   0          3m32s
[root@kubemaster prometheus]#

[root@kubemaster prometheus]# kubectl get svc -n kube-ops
NAME         TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
prometheus   NodePort   10.109.108.37   <none>        9090:31312/TCP   5s
[root@kubemaster prometheus]#

kubectl get pods –n kube-ops –o wide

[root@kubemaster prometheus]# kubectl get pods -n kube-ops -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
prometheus-848d44c7bc-54cpr   1/1     Running   0          6m17s   10.244.2.23   kubenode2   <none>           <none>
[root@kubemaster prometheus]#

这个时候我们就可以通过访问 kubenode2这台主机的31312端口来访问prometheus呢

可以先使用命令  curl http://kubenode2:31312/metrics  测试prometheus是否有metrics数据

image

prometheus已经成功运行起来了

  • 四、通过prometheus监控redis应用

 

4.1  首先在kubernetes里面部署一个redis的应用

vim prome-redis.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
      name: redis 
      namespace: kube-ops
spec:
     template:
          metadata:
                 labels:
                     app: redis   
    spec:
          containers:
          -  name: redis       
              image: redis:4
              resources:
                  requests:
                      cpu: 100m           
                     memory: 100Mi       
              ports:
              -  containerPort: 6379
          -  name: redis-exporter       
             image: oliver006/redis_exporter:latest       
             resources:
                 requests:
                     cpu: 100m           
                    memory: 100Mi       
            ports:
            -  containerPort: 9121

---
kind: Service
apiVersion: v1
metadata:
      name:  redis 
      namespace:  kube-ops
spec:
    selector:
        app: redis 
   ports:
   -   name: redis   
        port:  6379
        targetPort: 6379
  -   name: prom   
       port: 9121
       targetPort: 9121

 

kubectl apply –f prometheus-redis.yaml

kubectl get pods –n kube-ops

[root@kubemaster prometheus]# kubectl get svc -n kube-ops
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
prometheus   NodePort    10.109.108.37    <none>        9090:31312/TCP      24m
redis        ClusterIP   10.100.225.179   <none>        6379/TCP,9121/TCP   11m
[root@kubemaster prometheus]# kubectl get pods -n kube-ops -o wide
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
prometheus-848d44c7bc-54cpr   1/1     Running   0          28m   10.244.2.23   kubenode2    <none>           <none>
redis-58c6c94968-qcq6p        2/2     Running   0          11m   10.244.0.9    kubemaster   <none>           <none>
[root@kubemaster prometheus]#

测试 curl http://10.244.0.9:9121/metrics    查看边角容器redis-exporter暴露的metrics数据

4.2  配置prometheus-cm.yaml  增加redis的监控配置

apiVersion: v1
kind: ConfigMap
metadata:
      name: prometheus-config
      namespace: kube-ops
data:
     prometheus.yml: |
         global:
             scrape_interval: 15s
             scrape_timeout: 15s
        scrape_configs:
        -  job_name: 'prometheus'
           static_configs:
           -   targets: ['localhost:9090']
        -  job_name: 'redis'
           static_configs:
           -   targets: ['redis:9121']    #这里的监控对象是redis服务,端口是9121

kubectl delete -f prometheus-cm.yaml  #重新删除configmap

kubectl apply -f prometheus-cm.yaml    #重新应用configmap

curl -X POST "http://10.109.108.37:9090/-/reload"  #热更新configmap配置

image

  • 五、使用prometheus监控kubernetes node:

 

5.1  部署一个DaemonSet类型的资源,将node exporter部署在每一台k8s node节点上面

      vim prome-node-exporter.yaml

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
       name: node-exporter 
       namespace: kube-ops
       labels:
           name: node-exporter
spec:
     template:
         metadata:
          labels:
               name: node-exporter   
    spec:
         hostPID: true
         hostIPC: true
         hostNetwork: true
         containers:
         -    name: node-exporter       
              image: prom/node-exporter:v0.16.0       
              ports:
             -   containerPort: 9100
              resources:
                requests:
                      cpu: 0.15
             securityContext:
                   privileged: true
             args:
             - --path.procfs       
             - /host/proc       
             - --path.sysfs       
             - /host/sys       
              - --collector.filesystem.ignored-mount-points       
              - '"^/(sys|proc|dev|host|etc)($|/)"'
              volumeMounts:
               -  name: dev         
                   mountPath: /host/dev       
              -  name: proc         
                   mountPath: /host/proc       
              -  name: sys         
                   mountPath: /host/sys       
             -  name: rootfs         
                 mountPath: /rootfs     
        tolerations:
        -  key: "node-role.kubernetes.io/master"
           operator: "Exists"
           effect: "NoSchedule"
      volumes:
      -  name: proc         
          hostPath:
               path: /proc       
      -   name: dev         
           hostPath:
                path: /dev       
      -   name: sys         
          hostPath:
                 path: /sys       
      -   name: rootfs         
           hostPath:
                 path: /

由于我们要获取到的数据是主机的监控指标数据,而我们的 node-exporter 是运行在容器中的,所以我们在 Pod 中需要配置一些 Pod 的安全策略,这里我们就添加了hostPID: true、hostIPC: true、hostNetwork: true3个策略,用来使用主机的 PID namespace、IPC namespace 以及主机网络,这些 namespace 就是用于容器隔离的关键技术,要注意这里的 namespace 和集群中的 namespace 是两个完全不相同的概念。

另外我们还将主机的/dev、/proc、/sys这些目录挂载到容器中,这些因为我们采集的很多节点数据都是通过这些文件夹下面的文件来获取到的,比如我们在使用top命令可以查看当前cpu使用情况,数据就来源于文件/proc/stat,使用free命令可以查看当前内存使用情况,其数据来源是来自/proc/meminfo文件。

[root@kubemaster prometheus]# kubectl get ds -n kube-ops
NAME            DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
node-exporter   3         3         3       3            3           <none>          4m30s
[root@kubemaster prometheus]#

[root@kubemaster prometheus]# kubectl get pods -n kube-ops -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP             NODE         NOMINATED NODE   READINESS GATES
node-exporter-788bd           1/1     Running   0          4m56s   10.83.32.133   kubenode2    <none>           <none>
node-exporter-7vfs7           1/1     Running   0          4m56s   10.83.32.138   kubenode1    <none>           <none>
node-exporter-xkj2b           1/1     Running   0          4m56s   10.83.32.146   kubemaster   <none>           <none>
prometheus-848d44c7bc-54cpr   1/1     Running   0          69m     10.244.2.23    kubenode2    <none>           <none>
redis-58c6c94968-qcq6p        2/2     Running   0          52m     10.244.0.9     kubemaster   <none>           <none>
[root@kubemaster prometheus]#

可以发现每一个node节点上面都有运行一个pod,这个就是DaemonSet资源的作用

由于我们这里3个节点上面都运行了 node-exporter 程序,如果我们通过一个 Service 来将数据收集到一起用静态配置的方式配置到 Prometheus 去中,就只会显示一条数据,我们得自己在指标数据中去过滤每个节点的数据,那么有没有一种方式可以让 Prometheus 去自动发现我们节点的 node-exporter 程序,并且按节点进行分组呢?是有的,就是我们前面和大家提到过的服务发现

 

重新配置prometheus-cm.yaml,增加k8s node节点的自动发现

 

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: kube-ops
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
      scrape_timeout: 15s
    scrape_configs:
    - job_name: 'prometheus'
      static_configs:
      - targets: ['localhost:9090']
    - job_name: 'redis'
      static_configs:
      - targets: ['redis:9121'] #这里的监控对象是redis服务,端口是9121
    - job_name: 'kubernetes-nodes'
      tls_config:
        ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
      kubernetes_sd_configs:
      - role: node
      relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):10250'
        replacement: '${1}:9100'
        target_label: __address__   
        action: replace
      - action: labelmap   
        regex: __meta_kubernetes_node_label_(.+)


kubectl delete -f prometheus-cm.yaml

kubectl apply -f prometheus-cm.yaml

curl -X POST http://10.109.108.37:9090/-/reload

image

通过指定kubernetes_sd_configs的模式为node,Prometheus 就会自动从 Kubernetes 中发现所有的 node 节点并作为当前 job 监控的目标实例,发现的节点/metrics接口是默认的 kubelet 的 HTTP 接口,另外这里还需要指定用于访问 Kubernetes API 的 ca 以及 token 文件路径,ca 证书和 token 文件都是 Pod 启动后集群自动注入到 Pod 中的文件。

prometheus 的 ConfigMap 更新完成后,同样的我们执行 reload 操作,让配置生效:

这个是因为 prometheus 去发现 Node 模式的服务的时候,访问的端口默认是10250,而现在该端口下面已经没有了/metrics指标数据了,现在 kubelet 只读的数据接口统一通过10255端口进行暴露了,所以我们应该去替换掉这里的端口,但是我们是要替换成10255端口吗?不是的,因为我们是要去配置上面通过node-exporter抓取到的节点指标数据,而我们上面是不是指定了hostNetwork=true,所以在每个节点上就会绑定一个端口9100,所以我们应该将这里的10250替换成9100,但是应该怎样替换呢?

这里我们就需要使用到 Prometheus 提供的relabel_configs中的replace能力了,relabel 可以在 Prometheus 采集数据之前,通过Target 实例的 Metadata 信息,动态重新写入 Label 的值。除此之外,我们还能根据 Target 实例的 Metadata 信息选择是否采集或者忽略该 Target 实例。比如我们这里就可以去匹配__address__这个 Label 标签,然后替换掉其中的端口

这里就是一个正则表达式,去匹配__address__,然后将 host 部分保留下来,port 替换成了9100,现在我们重新更新配置文件,执行 reload 操作,然后再去看 Prometheus 的 Dashboard 的 Targets 路径下面 kubernetes-nodes 这个 job 任务是否正常了:

我们可以看到现在已经正常了,但是还有一个问题就是我们采集的指标数据 Label 标签就只有一个节点的 hostname,这对于我们在进行监控分组分类查询的时候带来了很多不方便的地方,要是我们能够将集群中 Node 节点的 Label 标签也能获取到就很好了。

  • 六、使用prometheus监控cAdvisor和kubelet

容器监控:

说到容器监控我们自然会想到cAdvisor,我们前面也说过cAdvisor已经内置在了 kubelet 组件之中,所以我们不需要单独去安装,cAdvisor的数据路径为/api/v1/nodes/<node>/proxy/metrics,同样我们这里使用 node 的服务发现模式,因为每一个节点下面都有 kubelet,自然都有cAdvisor采集到的数据指标。

目前cAdvisor集成到了kubelet组件内,可以在kubernetes集群中每个启动了kubelet的节点使用cAdvisor提供的metrics接口获取该节点所有容器相关的性能指标数据。1.7.3版本以前,cadvisor的metrics数据集成在kubelet的metrics中,在1.7.3以后版本中cadvisor的metrics被从kubelet的metrics独立出来了,在prometheus采集的时候变成两个scrape的job。

按新版本的标准配置,kubelet中的cadvisor是没有对外开放4194端口的。所以,我们只能通过apiserver提供的api做代理获取监控指标。

重要知识点来了。

cAdvisor的metrics地址: /api/v1/nodes/[节点名称]/proxy/metrics/cadvisor

kubelnet的metrics地址:/api/v1/nodes/[节点名称]/proxy/metrics

所以,prometheus配置cadvisor时,内容如下:

 

- job_name: 'cadvisor'
  scheme: https
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  kubernetes_sd_configs:
  - role: node
  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-kubelet'
  scheme: https
  tls_config:
    ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
  bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
  kubernetes_sd_configs:
  - role: node 
  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

上面的配置和我们之前配置 node-exporter 的时候几乎是一样的,区别是我们这里使用了 https 的协议,另外需要注意的是配置了 ca.cart 和 token 这两个文件,这两个文件是 Pod 启动后自动注入进来的,通过这两个文件我们可以在 Pod 中访问 apiserver,比如我们这里的__address__不在是 nodeip 了,而是 kubernetes 在集群中的服务地址,然后加上__metrics_path__的访问路径:/api/v1/nodes/${1}/proxy/metrics/cadvisor,现在同样更新下配置,然后查看 Targets 路径:

kubectl delete -f prometheus-cm.yaml

kubectl apply -f prometheus-cm.yaml

curl -X POST http://10.109.108.37:9090/-/reload

image

image

image

 
通过这个promQL语句

sum by (pod_name)(rate(container_cpu_usage_seconds_total{image!="", pod_name!=""}[1m] ))

查询情况是所有POD的CPU使用情况

image

image

image

现在可以看到我们上面添加的kubernetes-kubeletkubernetes-nodes这两个 job 任务都已经配置成功了,而且二者的 Labels 标签都和集群的 node 节点标签保持一致了。

[root@kubemaster prometheus]# kubectl get nodes --show-labels
NAME         STATUS   ROLES    AGE   VERSION   LABELS
kubemaster   Ready    master   9d    v1.13.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=kubemaster,node-role.kubernetes.io/master=
kubenode1    Ready    <none>   8d    v1.13.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=kubenode1
kubenode2    Ready    <none>   8d    v1.13.3   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=kubenode2

image

image

我们可以看到将3个 node 节点对应的 node_load1 指标数据都查询出来了,同样的,我们还可以使用 PromQL 语句来进行更复杂的一些聚合查询操作,还可以根据我们的 Labels 标签对指标数据进行聚合,比如我们这里只查询 node03 节点的数据,可以使用表达式node_load1{instance="node03"}来进行查询:

猜你喜欢

转载自blog.51cto.com/zgui2000/2358606