大家好,我是Linux运维工程师 Linke 。技术过硬,从不挖坑~

这篇文档来记录一下我新部署的监控软件Prometheus ,grafana 和 alatermanager 放在下一篇文章中~~

记得刚刚上了 k8s 时,我还是用的老套筒式监控,当时不知道有prometheus这个东西,2017年的时候,prometheus大概还不为业内所用,所以不知道。。。好吧,这是我不知道的理由~
当时pod状态、副本数等都是python写的监控插件,因为当时主监控服务用的小米监控——open-falcon 。 open-falcon 总体还是不错的,用的也可以,我个人感觉比zabbix 、 nagios 强多了,但是监控 k8s 就有些吃力了,大部分监控都要自己再开发。我也就这么一直晃悠的用,维护起来很操蛋的。而且容器中跑java应用的话,jvm用小米的那套重量太大,所以干脆我就不监控 jvm 了,pod 因为 OOM 挂了我就加内存。直到有一天,有个应用不管怎么加都挂,于是就和同桌研究怎么监控 JVM ,然后他看到有人用 prometheus 监控 k8s ,而且能拿到 jvm ,然后我们就研究使用这个。上线后,k8s 各指标监控完美抓取,妈妈再也不用担心我的学习了。
下面开始进入部署环节,还是老样子,不扯原理,无非就是数据从哪里来,到哪里去,没啥好说的,用两把就都知道了。
不监控 k8s 的话,感觉还是 open-falcon 使的方便,因为我到现在还没时间看如何回调接口。也没找到。自定义监控倒是研究明白了,因为 prometheus没有端口监控,草不操蛋,然后我自己写了个,看这个文档:

https://blog.csdn.net/qq_31547771/article/details/103263288


本文介绍在 k8s 上部署 prometheus ,源码安装的俺也没试过。
前提先要有个 kubernates 集群,当然能撸到这篇文档的同行们我相信早已拥有了自己的 k8s 集群。没有也没关系,兄弟我提供一条龙服务,请看文档:

https://blog.csdn.net/qq_31547771/article/details/100699573

服务器划分
k8s集群角色ip调度
master101192.168.7.101不跑业务应用
master102192.168.7.102不跑业务应用
master103192.168.7.103不跑业务应用
node104192.168.7.104调度 prometheus 到此节点,不跑其他应用
node105192.168.7.105跑其他业务应用

其余节点都如 node105 ,跑业务应用

另外本例中还加入了一组 es 的监控
192.168.7.41
192.168.7.42
192.168.7.43

k8s操作节点配置prometheus的yaml文件

我把用来操作 k8s 的系统叫做 k8s 操作节点,这里我用的是 192.168.7.101 ,生产环境不建议使用 master 节点做操作节点,建议单独弄一个系统,装了 kubelet ,使用 k8s 的秘钥文件连接 k8s 。
下面所有的文件都放在 /home/scripts/prometheus 路径下

先编辑第一个主要文件: configmap.yaml
这个文件是 prometheus 主服务要使用的,监控规则、监控分组等都写在这个文件中了。
如果闲报警规则和监控组写到一个文件太多,可以把 rules.yaml 文件移出去,加一个 rule_files: - “/etc/prometheus/prometheus.rules.yml” ,指定到一个文件。但要记得挂载进去。本例中,我是写到一起的、

cat > configmap.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
  namespace: monitor
data:
  #被引用到/etc/prometheus/prometheus.yml
  prometheus.yml: |
    global:
      #每15s采集一次数据和15s做一次告警检测
      scrape_interval:     15s
      evaluation_interval: 15s
    #指定加载的告警规则文件
    rule_files:
    - /etc/prometheus/rules.yml
    #将报警送至何地进行报警
    alerting:
      alertmanagers:
        - static_configs:
          - targets: ["192.168.7.107:9093"]
    #指定prometheus要监控的目标
    scrape_configs:
    - job_name: 'k8s-node'
      scrape_interval: 10s
      static_configs:
      - targets: 
        - '192.168.7.101:31672'
        - '192.168.7.102:31672'     
        - '192.168.7.103:31672'     
        - '192.168.7.104:31672'     
        - '192.168.7.105:31672'     
    - job_name: 'es-node'
      scrape_interval: 10s
      static_configs:
      - targets: 
        - '192.168.7.41:31672'
        - '192.168.7.42:31672'     
        - '192.168.7.43:31672'
    #自定义获取监控数据,每个 job_name 都是独立的,以下的语法难的一逼,可能只有老天爷知道
    - job_name: 'tomcat-pods'
      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: endpoints
      relabel_configs:
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape, __meta_kubernetes_service_annotation_prometheus_io_jvm_scrape]
        regex: true;true
        action: keep
      - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_app_metrics_patn]
        action: replace
        target_label: __metrics_path__
        regex: (.+)
      - source_labels: [__meta_kubernetes_pod_ip, __meta_kubernetes_service_annotation_prometheus_io_app_metrics_port]
        action: replace
        target_label: __address__
        regex: (.+);(.+)
      - source_labels: [__meta_kubernetes_namespace]
        action: replace
        target_label: kubernetes_namespace
      - source_labels: [__meta_kubernetes_pod_name]
        action: replace
        target_label: kubernetes_pod_name
      - action: labelmap
        regex: __meta_kubernetes_pod_label_(.+)
      - source_labels: [__meta_kubernetes_pod_host_ip]
        action: replace
        target_label: kubernetes_host_ip
    - 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
  # 监控规则文件,被引用到/etc/prometheus/rules.yml
  rules.yml: |
    groups:
    - name: test-rule
      rules:

      ############# k8s-Node监控 #############
      - alert: k8s-node状态异常
        expr: up{job="k8s-node"} != 1
        for: 3m
        labels:
          severity: 非常严重
        annotations:
          summary: "k8s节点可能宕了"
          description: "{{$labels.instance}}: Node节点状态异常"
      - alert: k8s-node节点CPU使用率
        expr: (1 - avg(irate(node_cpu_seconds_total{job="k8s-node",mode="idle"}[1m])) by (instance)) * 100  > 95
        for: 3m
        labels:
          severity: 一般
        annotations:
          summary: "Node节点CPU使用率超过95%"
          description: "{{$labels.instance}}: Node节点当前CPU使用率为: {{ $value }}"
      - alert: k8s-node节点根磁盘使用率
        expr: (node_filesystem_size_bytes{mountpoint="/",job="k8s-node"} - node_filesystem_avail_bytes{mountpoint="/",job="k8s-node"}) / node_filesystem_size_bytes{mountpoint="/",job="k8s-node"} * 100 > 70
        for: 3m
        labels:
          team: k8s-node
        annotations:
          summary: "根磁盘使用率为: {{ $value }}"
          description: "Node服务器[[ {{$labels.instance}} ]] 的 {{$labels.mountpoint}} 磁盘空间使用率超过70%,超过85%后pod将迁移,请尽快处理"
      - alert: k8s-node节点内存使用率
        expr: (node_memory_MemTotal_bytes{job="k8s-node"} - (node_memory_Buffers_bytes{job="k8s-node"} + node_memory_Cached_bytes{job="k8s-node"} + node_memory_MemFree_bytes{job="k8s-node"})) / node_memory_MemTotal_bytes{job="k8s-node"} * 100 > 95
        for: 3m
        labels:
          team: k8s-node
        annotations:
          summary: "当前内存使用率超过95%"
          description: "Node服务器[[ {{$labels.instance}} ]]  内存使用率为: {{ $value }}"
          
      ############# es-Node监控 #############
      - alert: es-node状态异常
        expr: up{job="es-node"} != 1
        for: 3m
        labels:
          severity: 非常严重
        annotations:
          summary: "elasticsearch节点可能宕了"
          description: "{{$labels.instance}}: elasticsearch节点状态异常"
      - alert: es-node节点数据磁盘使用率
        expr: (node_filesystem_size_bytes{mountpoint="/data",job="es-node"} - node_filesystem_avail_bytes{mountpoint="/data",job="es-node"}) / node_filesystem_size_bytes{mountpoint="/data",job="es-node"} * 100 > 70
        for: 3m
        labels:
          severity: 严重
        annotations:
          summary: "/data 磁盘使用率为: {{ $value }}"
          description: "Node服务器[[ {{$labels.instance}} ]] 的 {{$labels.mountpoint}} 磁盘空间使用率超过70%,超过85%后pod将迁移,请尽快处理"
EOF

我这么负责,这里要说一下某些没加注释的地方

  • alert: 报警组
    expr: 报警规则设置,这里的数据源在 prometheus 的 UI 界面都能搜索到,并且在 UI 界面都可以用语法取到想要的值,监控规则必须得在 UI 界面能一样运行取值,否则无法监控。例如 up{job=“es-node”} 直接在 UI 界面输入是可以拿到值的。
    for:触发报警后等待时间
    labels: 设置报警级别,此处还有别的功能,没研究
    annotations: 报警信息的描述,这里可以从报警信息中过滤想要的内容,使报警内容更加易读
    summary: 翻译一下,总结; 概括; 概要; 如我上面所写,你懂得。
    description: 翻译一下,描述,描写,说明,你懂得。这两个随便怎么用都行。
    建议报警规则按照各个类型分开,以服务种类划分,本人跟监控打了三年交道,我觉得越细越好、因为各种服务有各种自己的阈值,它可以让磁盘到 90% 再报警,但另一个80%就得报警,因此越细越好。跑题了。。。

rbac 文件
这个文件不得了,有了他,就可以连接到 k8s master ,获取到 k8s 的集群信息,即获得 k8s api ,这个文件不用改,直接拿去用。

cat > rbac-setup.yaml << EOF
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: monitor
---
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: monitor
EOF

pod 的配置文件 prometheus-deploy.yaml
来吧,下面让我们一鼓作气创建完,然后是启动 pod 的配置文件 prometheus-deploy.yaml ,有两点需要注意:
1、修改一下数据目录的挂在点为自己的路径,宿主机此数据路径给 777 权限。
2、我给 prometheus 的 pod 加了调度方式,只能在有 prometheus 标签的节点上启动,即下面的这个配置

  nodeSelector:
    nodetype: prometheus

具体怎么做,请看这篇文档:

https://blog.csdn.net/qq_31547771/article/details/100742202

这个文件。。。能撸到此文的,相信对 k8s 的 yaml 文件已经相当熟悉了。不熟悉的话,Linke 在这儿有详解:

https://blog.csdn.net/qq_31547771/article/details/102526403

cat > prometheus-deploy.yaml << EOF
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    name: prometheus-deployment
  name: prometheus
  namespace: monitor
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prometheus
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - image: prom/prometheus:v2.6.0
        name: prometheus
        command:
        - "/bin/prometheus"
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/home/prometheus"
        - "--storage.tsdb.retention=15d"
        - "--web.enable-lifecycle"
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: "/home/prometheus"
          name: data
        - mountPath: "/etc/prometheus"
          name: config-volume
        - mountPath: "/etc/localtime"
          readOnly: false
          name: localtime
        resources:
          requests:
            cpu: 500m
            memory: 3180Mi
          limits:
            cpu: 1000m
            memory: 4180Mi
      serviceAccountName: prometheus    
      nodeSelector:
        nodetype: prometheus
      volumes:
      - name: data
        hostPath:
          path: "/opt/prometheus/data"
      - name: config-volume
        configMap:
          name: prometheus-config
      - name: localtime
        hostPath:
          path: "/etc/localtime"
          type: File
EOF

然后是对外(集群外部访问)用的 service 配置文件
prometheus-service.yaml ,即使用 nodeport 将端口映射到集群外,然后用浏览器访问。

cat > prometheus-service.yaml << EOF
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: prometheus
  name: prometheus
  namespace: monitor
spec:
  type: NodePort
  ports:
  - port: 9090
    targetPort: 9090
    nodePort: 30003
  selector:
    app: prometheus
EOF

最后是创建 namespace 的配置文件 monitor_namespace.yaml
以上 service 和 pod 都规划到 monitor 命名空间中

cat > monitor_namespace.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
   name: monitor
   labels:
     name: monitor
EOF

然后是。然后prometheus就启动了。。顺序, 先创建命名空间——> 创建 confimap ——> 创建 rbac ——> 启动 prometheus pod ——> 创建 prometheus service

kubectk create -f monitor_namespace.yaml
kubectk create -f configmap.yaml
kubectk create -f rbac-setup.yaml
kubectk create -f prometheus-deploy.yaml
kubectk create -f prometheus-service.yaml
kubectl get po -n monitor

一顿操作下去,查看prometheus pod 是否启动正常。然后浏览器输入 192.168.7.104:30003 ,就可以访问 prometheus 的 UI 界面了。在这里可以搜索关键字,如输入 pod ,会自动补充,但是下面还要启动一个 kube-state-metrics 才能抓到 pod 的数据。 因此,接的往下看。
在这里插入图片描述

下面这两个图是 我现在的,上面的 confimap.yaml 我把多余的都删了,否则太多。箭头指出来的,是这个文档例子中 confimap 会显示的
点击 Alerts ,就可以看到自己设置的报警规则,可以尝试触发一个报警,看看这页的状态。
在这里插入图片描述
在这里插入图片描述

现在已经有了cadvisor、heapster、metric-server,几乎容器运行的所有指标都能拿到,但是下面这种情况却无能为力抓不到, k8s 的 pod 数据,还需要启动一个从k8s中掏数据的组件,即 kube-state-metrics ,这个插件其实就是将 k8s api 中的 pod 数据取出来,然后处理成了 prometheus 监控数据的格式。
直接从 github 把这个项目下载下来:

https://github.com/kubernetes/kube-state-metrics

将一个版本的下载下来,如果有的数据抓不到,或者有问题,就换个版本。我这里用的是 kube-state-metrics:v1.3.1 ,去年装的,一直没时间升级。
将项目下载来了后,解压开 tar 包后,我们用 k8s 启动,所以只需要项目中的 kubernetes 目录和下面的所以 yaml 文件就可以了,然后将各个文件中的 namespace: 的值改成 monitor ,不改也可以 。然后挨个创建一下:

cd kubernetes
for i in *;do kubectk create -f $i ;done
kubectl get po -n monitor

等待一分钟,此时再刷新一下浏览器,然后在Graph 那一页搜索: pod ,会补出抓到的pod 数据。如图,我们选择 kube_pod_info
在这里插入图片描述
在这里插入图片描述
然后可以使用 prometheus 的语法将数据缩小范围,监控也是这个意思,自己多测几遍就懂了:
在这里插入图片描述

未完,请见下面两篇文章。
Prometheus监控之Grafana——部署篇

https://blog.csdn.net/qq_31547771/article/details/103433097

Prometheus监控之altermanager——部署篇

https://blog.csdn.net/qq_31547771/article/details/103433737

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐