k8s-Prometheus监控

root
233
文章
0
评论
2021年8月23日17:57:36 评论 12805字阅读42分41秒

k8s-Prometheus监控

对于Kubernetes而言,我们可以把当中所有的资源分为几类:

  • 基础设施层(Node):集群节点,为整个集群和应用提供运行时资源
  • 容器基础设施(Container):为应用提供运行时环境
  • 用户应用(Pod):Pod中会包含一组容器,它们一起工作,并且对外提供一个(或者一组)功能
  • 内部服务负载均衡(Service):在集群内,通过Service在集群暴露应用功能,集群内应用和应用之间访问时提供内部的负载均衡
  • 外部访问入口(Ingress):通过Ingress提供集群外的访问入口,从而可以使外部客户端能够访问到部署在Kubernetes集群内的服务

因此,如果要构建一个完整的监控体系,我们应该考虑,以下5个方面:

  • 集群节点状态监控:从集群中各节点的kubelet服务获取节点的基本运行状态;
  • 集群节点资源用量监控:通过Daemonset的形式在集群中各个节点部署Node Exporter采集节点的资源使用情况;
  • 节点中运行的容器监控:通过各个节点中kubelet内置的cAdvisor中获取个节点中所有容器的运行状态和资源使用情况;
  • 如果在集群中部署的应用程序本身内置了对Prometheus的监控支持,那么我们还应该找到相应的Pod实例,并从该Pod实例中获取其内部运行状态的监控指标。
  • 对k8s本身的组件做监控:apiserver、scheduler、controller-manager、kubelet、kube-proxy

node-exporter组件安装和配置

机器规划:

我的实验环境使用的k8s集群是2个master节点和1个node节点

master节点的机器ip是192.168.1.180/181,主机名是master01/02

node节点的机器ip是192.168.1.182,主机名是onode01

node-exporter介绍?

node-exporter可以采集机器(物理机、虚拟机、云主机等)的监控指标数据,能够采集到的指标包括CPU, 内存,磁盘,网络,文件数等信息。

安装node-exporter

#node/master节点都安装

[root@node01 ~]# docker pull prom/node-exporter
[root@master01 Prometheus]# kubectl create ns monitor-sa
namespace/monitor-sa created
[root@master01 Prometheus]# kubectl apply -f node-export.yaml 
daemonset.apps/node-exporter created
[root@master01 Prometheus]# kubectl get pod -n monitor-sa -o wide
NAME                  READY   STATUS    RESTARTS   AGE     IP              NODE       NOMINATED NODE   READINESS GATES
node-exporter-c9hgh   1/1     Running   0          7m48s   192.168.1.180   master01   <none>           <none>
node-exporter-kbwjj   1/1     Running   0          7m48s   192.168.1.182   node01     <none>           <none>
node-exporter-vtnc6   1/1     Running   0          7m48s   192.168.1.181   master02   <none>           <none>

 

node-exporter的文件

[root@master01 Prometheus]# cat node-export.yaml 
apiVersion: apps/v1
kind: DaemonSet  #可以保证k8s集群的每个节点都运行完全一样的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:v1.2.2
        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: /

 

通过node-exporter采集数据

[root@master01 Prometheus]# curl 192.168.1.180:9100/metrics

 

#node-export默认的监听端口是9100,可以看到当前主机获取到的所有监控数据

[root@master01 Prometheus]# curl 192.168.1.180:9100/metrics | | grep node_cpu_seconds
#HELP:解释当前指标的含义,上面表示在每种模式下node节点的cpu花费的时间,以s为单位
#TYPE:说明当前指标的数据类型,上面是counter类型
node_cpu_seconds_total{cpu="0",mode="idle"} 453223.39
node_cpu_seconds_total{cpu="0",mode="iowait"} 58.95
node_cpu_seconds_total{cpu="0",mode="irq"} 0
node_cpu_seconds_total{cpu="0",mode="nice"} 14.97
node_cpu_seconds_total{cpu="0",mode="softirq"} 771.84
node_cpu_seconds_total{cpu="0",mode="steal"} 0
node_cpu_seconds_total{cpu="0",mode="system"} 9545.91
node_cpu_seconds_total{cpu="0",mode="user"} 3167.3

node_cpu_seconds_total{cpu="0",mode="idle"} :

cpu0上idle进程占用CPU的总时间,CPU占用时间是一个只增不减的度量指标,从类型中也可以看出node_cpu的数据类型是counter(计数器)

counter计数器:只是采集递增的指标

Prometheus server安装和配置

1.创建sa账号,对sa做rbac授权

#创建一个sa账号monitor

[root@master01 Prometheus]# kubectl create serviceaccount monitor -n monitor-sa

#把sa账号monitor通过clusterrolebing绑定到clusterrole上

[root@master01 Prometheus]# kubectl create clusterrolebinding monitor-clusterrolebinding -n monitor-sa --clusterrole=cluster-admin  --serviceaccount=monitor-sa:monitor

2.创建prometheus数据存储目录

#在k8s集群的xianchaonode1节点上创建数据存储目录

[root@node01 ~]# mkdir /data/prometheus

安装Prometheus server服务

3.#创建一个configmap存储卷,用来存放prometheus配置信息

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:
#scrape_configs:配置数据源,称为target,每个target用job_name命名。又分为静态配置和服务发现
    - job_name: 'kubernetes-node'
      kubernetes_sd_configs:
#使用的是k8s的服务发现
      - role: node
# 使用node角色,它使用默认的kubelet提供的http端口来发现集群中每个node节点。
      relabel_configs:
#重新标记
      - source_labels: [__address__] #配置的原始标签,匹配地址
        regex: '(.*):10250'   #匹配带有10250端口的url

 replacement: ':9100'  #把匹配到的ip:10250的ip保留
        target_label: __address__ #新生成的url是获取到的ip:9100
        action: replace
      - action: labelmap 
#匹配到下面正则表达式的标签会被保留,如果不做regex正则的话,默认只是会显示instance标签
        regex: __meta_kubernetes_node_label_(.+)

注意:Before relabeling表示匹配到的所有标签
instance="xianchaomaster1" 
Before relabeling:  
__address__="192.168.40.180:10250"
__meta_kubernetes_node_address_Hostname="xianchaomaster1"
__meta_kubernetes_node_address_InternalIP="192.168.40.180"
__meta_kubernetes_node_annotation_kubeadm_alpha_kubernetes_io_cri_socket="/var/run/dockershim.sock"
__meta_kubernetes_node_annotation_node_alpha_kubernetes_io_ttl="0"
__meta_kubernetes_node_annotation_projectcalico_org_IPv4Address="192.168.40.180/24"
__meta_kubernetes_node_annotation_projectcalico_org_IPv4IPIPTunnelAddr="10.244.123.64"
__meta_kubernetes_node_annotation_volumes_kubernetes_io_controller_managed_attach_detach="true"
__meta_kubernetes_node_label_beta_kubernetes_io_arch="amd64"
__meta_kubernetes_node_label_beta_kubernetes_io_os="linux"
__meta_kubernetes_node_label_kubernetes_io_arch="amd64"
__meta_kubernetes_node_label_kubernetes_io_hostname="xianchaomaster1"
__meta_kubernetes_node_label_kubernetes_io_os="linux"
__meta_kubernetes_node_label_node_role_kubernetes_io_control_plane=""
__meta_kubernetes_node_label_node_role_kubernetes_io_master=""
__meta_kubernetes_node_name="xianchaomaster1"
__metrics_path__="/metrics"
__scheme__="http"
instance="xianchaomaster1"
job="kubernetes-node"


- 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__="192.168.40.180:10250"
        replacement: kubernetes.default.svc:443 
#把获取到的地址替换成新的地址kubernetes.default.svc:443
      - source_labels: [__meta_kubernetes_node_name]
        regex: (.+)
#把原始标签中__meta_kubernetes_node_name值匹配到
        target_label: __metrics_path__
#获取__metrics_path__对应的值
        replacement: /api/v1/nodes//proxy/metrics/cadvisor
#把metrics替换成新的值api/v1/nodes/xianchaomaster1/proxy/metrics/cadvisor
是__meta_kubernetes_node_name获取到的值

新的url就是https://kubernetes.default.svc:443/api/v1/nodes/xianchaomaster1/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
#endpoint这个对象的名称空间
,__meta_kubernetes_service_name  
#endpoint对象的服务名
, __meta_kubernetes_endpoint_port_name
#exnpoint的端口名称]
        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' 那么你这里就要
__meta_kubernetes_service_annotation_prometheus_io_app_metrics_path这样写。

      - 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@master01 ~]# kubectl apply -f prometheus-cfg.yaml 
configmap/prometheus-config created

 

4.通过deployment部署prometheus

node01工作节点上传镜像

[root@node01 ~]# docker pull prom/prometheus:v2.29.1

#通过kubectl apply更新prometheus

[root@master01 ~]# kubectl apply -f prometheus-deploy.yaml 

#显示如下,可看到pod状态是running,说明prometheus部署成功

[root@master01 ~]# kubectl get pod -n monitor-sa 
NAME                                 READY   STATUS    RESTARTS   AGE
node-exporter-cmnfv                  1/1     Running   0          3h6m
node-exporter-fsrk6                  1/1     Running   0          3h6m
node-exporter-ksgsr                  1/1     Running   0          3h6m
prometheus-server-78b7bc76b4-zbd62   1/1     Running   0          9s

prometheus-deploy.yaml文件内容如下:

[root@master01 ~]# cat 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:
      nodeName: node01
      serviceAccountName: monitor
      initContainers:
      - name: fix-permissions
        image: busybox:1.28
        imagePullPolicy: IfNotPresent
        command: ["/bin/chown","-R","65534:65534","/prometheus"]
        volumeMounts:
        - mountPath: /prometheus/
          name: prometheus-storage-volume
      containers:
      - name: prometheus
        image: prom/prometheus:v2.29.1
        imagePullPolicy: IfNotPresent
        command:
          - prometheus
          - --config.file=/etc/prometheus/prometheus.yml
          - --storage.tsdb.path=/prometheus  #旧数据存储目录
          - --storage.tsdb.retention=720h       #何时删除旧数据,默认为15天
          - --web.enable-lifecycle                     #开启热加载
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: /etc/prometheus/prometheus.yml
          name: prometheus-config
          subPath: prometheus.yml
        - mountPath: /prometheus/
          name: prometheus-storage-volume
      volumes:
        - name: prometheus-config
          configMap:
            name: prometheus-config
            items:
              - key: prometheus.yml
                path: prometheus.yml
                mode: 0644
        - name: prometheus-storage-volume
          hostPath:
           path: /data/prometheus
           type: Directory

 

5.给prometheus pod创建一个SVC

prometheus-svc.yaml文件内容如下:

[root@master01 ~]# 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
      nodePort: 30002
  selector:
    app: prometheus
    component: server

#查看service在物理机映射的端口

[root@master01 ~]# kubectl get svc -n monitor-sa
NAME         TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
prometheus   NodePort   10.1.239.41   <none>        9090:30002/TCP   9s

通过上面可以看到service在宿主机上映射的端口是30002,这样我们访问k8s集群的master1节点的ip:30002,就可以访问到prometheus的web ui界面了

#访问prometheus web ui界面

浏览器输入如下地址:

http://192.168.40.180:32732/graph

#点击页面的Status->Targets,可看到如下,说明我们配置的服务发现可以正常采集数据

Prometheus热加载

#为了每次修改配置文件可以热加载prometheus,也就是不停止prometheus,就可以使配置生效,想要使配置生效可用如下热加载命令:

[root@master01 ~]#  kubectl get pods -n monitor-sa -o wide -l app=prometheus
NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE     NOMINATED NODE   READINESS GATES
prometheus-server-78b7bc76b4-j67wj   1/1     Running   0          31m   172.16.196.133   node01   <none>           <none>

172.16.196.133是prometheus的pod的ip地址

想要使配置生效可用如下命令热加载:

[root@master01 ~]# curl -X POST http://172.16.196.133:9090/-/reload

#日志里能看到更新信息

[root@master01 ~]# kubectl logs -f prometheus-server-78b7bc76b4-j67wj -n monitor-sa 
level=info ts=2021-08-23T09:51:42.207Z caller=main.go:969 msg="Loading configuration file" filename=/etc/prometheus/prometheus.yml
level=info ts=2021-08-23T09:51:42.209Z caller=kubernetes.go:282 component="discovery manager scrape" discovery=kubernetes msg="Using pod service account via in-cluster config"

#热加载速度比较慢,可以暴力重启prometheus,如修改上面的prometheus-cfg.yaml文件之后,可执行如下强制删除:

kubectl delete -f prometheus-cfg.yaml
kubectl delete -f prometheus-deploy.yaml

然后再通过apply更新:

kubectl apply -f prometheus-cfg.yaml
kubectl apply -f prometheus-deploy.yaml

注意:

线上最好热加载,暴力删除可能造成监控数据的丢失

 

 

继续阅读
weinxin
我的微信
这是我的微信扫一扫
  • 文本由 发表于 2021年8月23日17:57:36
  • 除非特殊声明,本站文章均为原创,转载请务必保留本文链接
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: