暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

在k8s中安装prometheus

IT那活儿 2023-11-29
479
点击上方“IT那活儿”公众号--专注于企业全栈运维技术分享,不管IT什么活儿,干就完了!!!

实验环境

主机名

主机IP

master

k8s1

10.0.0.3

node

k8s2

10.0.0.4

node

k8s3

10.0.0.5



prometheus概述与架构

2.1 概述

Prometheus是一个开源系统监控和警报工具包,最初由 SoundCloud构建。自 2012 年启动以来,许多公司和组织都采用了 Prometheus,该项目拥有非常活跃的开发者和用户社区。它现在是一个独立的开源项目,独立于任何公司进行维护。为了强调这一点,并明确项目的治理结构,Prometheus 于 2016 年作为继Kubernetes之后的第二个托管项目加入了云原生计算基金会

2.2 架构

2.3 特征

  • 具有由指标名称和键/值对标识的时间序列数据的多维数据模型
  • PromQL,一种灵活的查询语言 来利用这个维度;
  • 不依赖分布式存储;单个服务器节点是自治的;
  • 时间序列收集通过 HTTP 上的拉模型进行;
  • 通过中间网关支持推送时间序列
  • 通过服务发现或静态配置发现目标;
  • 多种图形和仪表板支持模式。


安装exporter
exporter是什么?
采集机器(物理机、虚拟机、云主机等)的监控指标数据,能够采集到的指标包括CPU, 内存,磁盘,网络,文件数等信息。
3.1 安装node-exporter插件
注:此操作在所有节点执行。
首先创建命名空间,再根据自己的k8s版本选择合适容器进行时进行镜像的解压,这里我的k8s是1.25版本。
[root@k8s1 ~]# kubectl create ns monitor-sa
[root@k8s1 ~]# ctr -n=k8s.io images import node-exporter.tar.gz
[root@k8s2 ~]# ctr -n=k8s.io images import node-exporter.tar.gz
[root@k8s3 ~]# ctr -n=k8s.io images import node-exporter.tar.gz
[root@k8s1 ~]#cat node-export.yaml
apiVersion: apps/v1
kind: DaemonSet #此种部署方式保证该pod在集群每个节点上运行
metadata:
 name: node-exporter
 namespace: monitor-sa
 labels:
   name: node-exporter
spec:
 selector:
   matchLabels:
     name: node-exporter
 template:
   metadata:
     labels:
       name: node-exporter
   spec:
     hostPID: true
     hostIPC: true
     hostNetwork: true

hostNetwork、hostIPC、hostPID都为True时,表示这个Pod里的所有容器,会直接使用宿主机的网络,直接与宿主机进行IPC(进程间通信)通信,可以看到宿主机里正在运行的所有进程。
加入了hostNetwork:true会直接将我们的宿主机的9100端口映射出来,从而不需要创建service 在我们的宿主机上就会有一个9100的端口。
containers:
     - name: node-exporter
       image: prom/node-exporter:v0.16.0
       imagePullPolicy: IfNotPresent
       ports:
       - containerPort: 9100
       resources:
          requests:
            cpu: 0.15 #该容器至少需要0.15核cpu
       securityContext:
         privileged: true #开启特权模式
       args:
       - --path.procfs #配置挂载宿主机(node)节点的路径
       - host/proc
       - --path.sysfs #配置挂载宿主机(node)节点的路径
       - 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
#将主机/dev、/proc、/sys这些目录挂在到容器中,这是因为我们采集的很多节点数据都是通过这些文件来获取系统信息的。
     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: /

通过kubectl apply更新node-exporter.yaml文件:
[root@k8s1]# kubectl apply -f node-export.yaml
查看node-exporter是否部署成功。
[root@k8s1]# kubectl get pods -n monitor-sa
如下图所示:
3.2 通过node-exporter采集数据
curl http://主机ip:9100/metrics
#node-export默认的监听端口是9100,可以看到当前主机获取到的所有监控数据。
curl http://10.0.0.3:9100/metrics | grep node_cpu_seconds
显示10.0.0.3主机cpu的使用情况。
[root@k8s1 prometheus]# curl http://10.0.0.3:9100/metrics |grep node_cpu_seconds
 % Total % Received % Xferd Average Speed Time Time Time Current
                                Dload Upload Total Spent Left Speed
100 95278  100 95278    0     0  1931k 0 --:--:-- --:--:-- --:--:-- 2022k

# 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"} 156289.74
node_cpu_seconds_total{cpu="0",mode="iowait"} 114.96
node_cpu_seconds_total{cpu="0",mode="irq"} 0
node_cpu_seconds_total{cpu="0",mode="nice"} 0.14
node_cpu_seconds_total{cpu="0",mode="softirq"} 840.71
node_cpu_seconds_total{cpu="0",mode="steal"} 0
node_cpu_seconds_total{cpu="0",mode="system"} 14851.83
node_cpu_seconds_total{cpu="0",mode="user"} 17358.11
node_cpu_seconds_total{cpu="1",mode="idle"} 158361.55
node_cpu_seconds_total{cpu="1",mode="iowait"} 157.29
node_cpu_seconds_total{cpu="1",mode="irq"} 0
node_cpu_seconds_total{cpu="1",mode="nice"} 0.25

  • #HELP:解释当前指标的含义,上面表示在每种模式下node节点的cpu花费的时间,以s为单位。
  • #TYPE:说明当前指标的数据类型,上面是counter类型。
node_cpu_seconds_total{cpu="0",mode="idle"} :
  • cpu0上idle进程占用CPU的总时间,CPU占用时间是一个只增不减的度量指标,从类型中也可以看出node_cpu的数据类型是counter(计数器)。
  • counter计数器:只是采集递增的指标。
[root@k8s1 prometheus]# curl http://10.0.0.3:9100/metrics |grep node_load
 % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                Dload  Upload   Total   Spent    Left  Speed
 4 95299    4  3961    0     0  67337      0  0:00:01 --:--:--  0:00:01 68293# HELP node_load1 1m load average.
# TYPE node_load1 gauge

node_load1 1.34
  • node_load1该指标反映了当前主机在最近一分钟以内的负载情况,系统的负载情况会随系统资源的使用而变化,因此node_load1反映的是当前状态,数据可能增加也可能减少,从注释中可以看出当前指标类型为gauge(标准尺寸)。
  • gauge标准尺寸:统计的指标可增加可减少。


Prometheus server安装和配置

4.1 创建sa账号对sa做RBAC授权

1)创建一个sa账号在monitor命名空间
[root@k8s1 ~]# kubectl create serviceaccount monitor -n monitor-sa
把sa账号monitor通过clusterrolebing绑定到clusterrole上。
[root@k8s1 ~]# kubectl create clusterrolebinding monitor-
clusterrolebinding -n monitor-sa --clusterrole=cluster-admin --serviceaccount=monitor-sa:monitor

注意:如果上面命令执行报错,那就需要下面的授权命令:
[root@k8s1~]# kubectl create clusterrolebinding monitor-
clusterrolebinding-1  -n monitor-sa --clusterrole=cluster-admin --user=system:serviceaccount:monitor:monitor-sa

2)创建Prometheus数据存储目录
在k8s集群的k8s2和k8s3节点上创建数据存储目录:
[root@k8s2 ~]#mkdir /data
[root@k8s2 ~]#chmod 777 /data/

4.2 安装Prometheus server服务

创建一个configMap存储卷,用来存放Prometheus配置信息。
#通过kubectl apply更新configmap:
[root@k8s1 prometheus]# kubectl apply -f prometheus-cfg.yaml
prometheus-cfg.yaml文件内容如下:
---
kind: ConfigMap
apiVersion: v1
metadata:
 labels:
   app: prometheus
 name: prometheus-config
 namespace: monitor-sa
data:
 prometheus.yml: |
   global:
     scrape_interval: 15s #采集目标主机监控据的时间间隔
     scrape_timeout: 10s # 数据采集超时时间,默认10s
     evaluation_interval: 1m #触发告警检测的时间,默认是1m
   scrape_configs:
   #配置数据源,称为target,每个target用job_name命名。又分为静态配置和服务发现
   - job_name: 'kubernetes-node'
     kubernetes_sd_configs:
     # 使用的是k8s的服务发现
     - role: node #Prometheus监控规则node模式
     # 使用node角色,它使用默认的kubelet提供的http端口来发现集群中每个node节点。
     relabel_configs:
     #重新标记
     - source_labels: [__address__] #配置的原始标签,匹配地址
       regex: '(.*):10250' #匹配带有10250端口的url
       replacement: '${1}:9100' #把匹配到的ip:10250的ip保留,端口替换为9100
       target_label: __address__ #新生成的url是${1}获取到的ip:9100
       action: replace
     - action: labelmap
     #匹配到下面正则表达式的标签会被保留,如果不做regex正则的话,默认只是会显示instance标签
       regex: __meta_kubernetes_node_label_(.+)
   - job_name: 'kubernetes-node-cadvisor'
    # 抓取cAdvisor数据,是获取kubelet上/metrics/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_(.+) #保留匹配到的具有__meta_kubernetes_node_label的标签
     - target_label: __address__ #获取到的地址:__address__="10.0.0.3:10250"
       replacement: kubernetes.default.svc:443  #把获取到的地址替换成新的地址kubernetes.default.svc:443
     - source_labels: [__meta_kubernetes_node_name] #把原始标签中__meta_kubernetes_node_name值匹配到
       regex: (.+)
       target_label: __metrics_path__ #获取__metrics_path__对应的值
       replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor #把metrics替换成新的值api/v1/nodes/k8s1/proxy/metrics/cadvisor,${1}是__meta_kubernetes_node_name获取到的值,新的url就是https://kubernetes.default.svc:443/api/v1/nodes/k8s1/proxy/metrics/cadvisor
   - job_name: 'kubernetes-apiserver'
     kubernetes_sd_configs:
     - role: endpoints #使用k8s中的endpoint服务发现,采集apiserver 6443端口获取到的数据
     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] #endpoint这个对象的名称空间、服务名、端口名称
       action: keep #采集满足条件的实例,其他实例不采集
       regex: default;kubernetes;https #正则匹配到的默认空间下的service名字是kubernetes,协议是https的endpoint类型保留下来
   - 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 #重新打标仅抓取到的具有 "prometheus.io/scrape: true" 的annotation的端点,意思是说如果某个service具有prometheus.io/scrape = true annotation声明则抓取,annotation本身也是键值结构,所以这里的源标签设置为键,而regex设置值true,当值匹配到regex设定的内容时则执行keep动作也就是保留,其余则丢弃。
     - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
       action: replace
       target_label: __scheme__
       regex: (https?) #重新设置scheme,匹配源标签__meta_kubernetes_service_annotation_prometheus_io_scheme也就是prometheus.io/scheme annotation,如果源标签的值匹配到regex,则把值替换为__scheme__对应的值。
     - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
       action: replace
       target_label: __metrics_path__
       regex: (.+) # 应用中自定义暴露的指标,也许你暴露的API接口不是/metrics这个路径,那么你可以在这个POD对应的service中做一个"prometheus.io/path = /mymetrics" 声明,上面的意思就是把你声明的这个路径赋值给__metrics_path__,其实就是让prometheus来获取自定义应用暴露的metrices的具体路径,不过这里写的要和service中做好约定,如果service中这样写 prometheus.io/app-metrics-path: '/metrics' 那么你这里就要
     - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
       action: replace
       target_label: __address__
       regex: ([^:]+)(?::\d+)?;(\d+)
       replacement: $1:$2 # 暴露自定义的应用的端口,就是把地址和你在service中定义的 "prometheus.io/port = <port>" 声明做一个拼接,然后赋值给__address__,这样prometheus就能获取自定义应用的端口,然后通过这个端口再结合__metrics_path__来获取指标,如果__metrics_path__值不是默认的/metrics那么就要使用上面的标签替换来获取真正暴露的具体路径。
     - action: labelmap #把匹配到的标签保留
       regex: __meta_kubernetes_service_label_(.+)
     - source_labels: [__meta_kubernetes_namespace]
       action: replace #替换__meta_kubernetes_namespace变成kubernetes_namespace
       target_label: kubernetes_namespace
     - source_labels: [__meta_kubernetes_service_name]
       action: replace
       target_label: kubernetes_name

#更新configmap资源:
[root@k8s1 prometheus]# kubectl apply -f prometheus-cfg.yaml
问题案例:
我们写了超过80%的告警,结果收到多条告警,但是真实超过80%的只有一个时间点。
这是另外一个参数影响的"evaluation_interval"
这个是触发告警检测的时间,默认为1m。
假如我们的指标是5m被拉取一次。
检测根据evaluation_interval 1m一次,所以在值被更新前,我们一直用的旧值来进行多次判断,造成了1m一次,同一个指标被告警了4次。

4.3 通过Deployment方式部署Prometheus

安装prometheus需要的镜像prometheus-2-2-1.tar.gz在课件,上传到k8s的工作节点上,手动解压:
[root@k8s2 ~]# ctr -n=k8s.io images import prometheus_2.33.5.tar.gz
#通过kubectl apply更新prometheus:
[root@k8s1]# kubectl apply -f prometheus-deploy.yaml
#查看prometheus是否部署成功。
[root@k8s1]# kubectl get pods -n monitor-sa
显示如下,可看到pod状态是running,说明prometheus部署成功
[root@k8s1 /]# kubectl get pod -n monitor-sa
NAME READY STATUS RESTARTS AGE
node-exporter-5w6x6 1/1     Running 0          42d
node-exporter-hzbc5 1/1     Running 0          42d
node-exporter-zz97b 1/1     Running 0          42d
prometheus-server-6cf9c94f76-c5xrj 1/1     Running 0          4d18h

#prometheus-deploy.yaml文件内容如下:
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: prometheus-server
 namespace: monitor-sa
 labels:
   app: prometheus
spec:
 replicas: 1
 selector:
   matchLabels:
     app: prometheus
     component: server
   #matchExpressions:
   #- {key: app, operator: In, values: [prometheus]}
   #- {key: component, operator: In, values: [server]}
 template:
   metadata:
     labels:
       app: prometheus
       component: server
     annotations:
       prometheus.io/scrape: 'false'
   spec:
     serviceAccountName: monitor
     containers:
     - name: prometheus
       image: prom/prometheus:v2.2.1
       imagePullPolicy: IfNotPresent
       command:
         - prometheus
         - --config.file=/etc/prometheus/prometheus.yml
         - --storage.tsdb.path=/prometheus
         - --storage.tsdb.retention=360h
         - --web.enable-lifecycle
       ports:
       - containerPort: 9090
         protocol: TCP
       volumeMounts:
       - mountPath: /etc/prometheus
         name: prometheus-config
       - mountPath: /prometheus/
         name: prometheus-storage-volume
     volumes:
       - name: prometheus-config
         configMap:
           name: prometheus-config
       - name: prometheus-storage-volume
         hostPath:
          path: /data
          type: Directory

4.4 创建Prometheus service

#通过kubectl apply 更新service:
[root@k8s1]# kubectl apply -f prometheus-svc.yaml
#prometheus-svc.yaml文件内容如下:
---
apiVersion: v1
kind: Service
metadata:
 name: prometheus
 namespace: monitor-sa
 labels:
   app: prometheus
 annotations:
   prometheus.io/scrape: "true"
   prometheus.io/port: "9090"
spec:
 type: NodePort
 ports:
   - port: 9090
     targetPort: 9090
     protocol: TCP
 selector:
   app: prometheus
   component: server

#查看service在物理机映射的端口。
[root@k8s1 prometheus]# kubectl get svc -n monitor-sa
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
prometheus NodePort 10.XX.XX.247   <none>        9090:32463/TCP 4d19h

注意:k8s新建的service规则会写入ipvs防火墙,如下图所示:



访问Prometheus
通过上面可以看到service在宿主机上映射的端口是32732,这样我们访问k8s集群的master1节点的ip:32732,就可以访问到prometheus的web ui界面了
#点击页面的Status->Targets,可看到如下,说明我们配置的服务发现可以正常采集数据


END



本文作者:王文权(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论