云原生实践之Monitoring(一)

正文共: 2602字
预计阅读时间:7分钟

之前小白有讲到线上服务的可观察性在当下无论是运维还是研发的同学都是必须要掌握和了解的特性。对于当前服务可观察所要承担的功能,各大公司或社区也已基本形成共识,其主要也是围绕三个方向来提出要求:

  • monitoring (监控)

  • logging (日志)

  • tracing (追踪)

当我们翻开CNCF的生态地图,发现最右边的Observability and Analysis正是给大家绘出了各类型服务观测的指导方案。

image.png

更多详情的地址 https://landscape.cncf.io/

在这里小白以日常工作中常使用到的应用来跟大家简单介绍CNCF里面的一些云原生

1. Monitoring 监控


Prometheus |--> Thanos --> Grafana

          |--> AlertManager

  • Prometheus

CNCF已毕业的一个主要面向度量监控的时序数据库,和Kubernetes、Consul等能深度结合为监控服务发现带来极大的便利性

  • Thanos

CNCF沙箱内的一个面向Prometheus分布式架构的应用

  • Grafana

数据可视化展示的前端,以其丰富的数据源和酷炫插件捕获了大批用户

2.Logging 日志


            |--> Loki --> Grafana

Fluentd --> |--> Kafka --> Flume

            |--> ElasticSearch --> Kibana

  • Fluentd

CNCF已毕业的一个由Ruby开发的日志采集客户端,具备良好的采集效率、灵活简单的配置和丰富的插件等特性,更以其与Kubernetes的紧密结合而获得市场快速的验证

  • Loki

GrafanaLab开源的一个类似Prometheus的日志聚合系统,以其轻量的设计和水平扩展,具备很高的成本收益而闻名

3.Tracing 追踪


Collector --> Jaeger --> Grafana

  • Jaeger

CNCF已毕业的一个分布式追踪系统,由Uber推出,因其简单友好的UI和与kubernetes、istio的结合,当下也聚集着大量的使用者

从今天开始,小白会按照上述的结构,并以云原生服务可观察性的这个区块内带大家初尝和体验,那么我们就由Prometheus开始吧

Prometheus架构

首先小白在正式使用前先看下Prometheus的组件及其大概架构

image.png

在图中小白可以了解到,Prometheus的监控数据来源主要分两种,直接从目标exporter中主动抓取数据,或者短期job上传给Pushgateway再由Prometheus主动抓取。其次Prometheus的数据以TSDB方式存储在本地磁盘,同时它也通过一些服务发现方式找到被监控的目标。最终Prometheus的呈现是以内置的UI或者集成Grafana以PromQL方式将数据可视化展示出来,当然用户也可以通过API方式自行绘图展示。

Prometheus部署

关于部署小白不想展开篇幅细说,这里小白仅简单分析下当下主流的两种部署方式以及建议

  • 方式一 :Prometheus-Operator

优点:利用Kubernetes的CRD将Prometheus的部署和配置抽象得更直观和理解,普通用户在K8S里面只需像声明Service一样定义监控即可,不用再过多去关心和维护Prometheus服务

缺点:运维难度比较高,普通用户难以理解真实配置,比较适合熟悉Prometheus的高阶玩家

  • 方式二:Yaml

优点:可以根据自己环境灵活选择部署的服务,更能了解模块之间的协作关系

缺点:部署和配置略复杂,新手们需要一定的学习成本

小白建议新手们还是需要花一段时间从Yaml部署开始熟悉,虽然过程比较复杂,不过现在关于Prometheus部署的资料很多,不会有太大的问题。

Prometheus实践 服务发现 Pod

小白以当前认为最实用的基于Kubernetes Pod为服务发现的案例来和大家一起分析,首先我们先来看下配置


- job_name: kubernetes-pods-discovery

  honor_timestamps: true

  scrape_interval: 15s

  scrape_timeout: 10s

  metrics_path: /metrics

  scheme: http

  kubernetes_sd_configs:

  - role: pod

  relabel_configs:

  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]

    separator: ;

    regex: "true"

    replacement: $1

    action: keep

  - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]

    separator: ;

    regex: (.+)

    target_label: __metrics_path__

    replacement: $1

    action: replace

  - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]

    separator: ;

    regex: ([^:]+)(?::\d+)?;(\d+)

    target_label: __address__

    replacement: $1:$2

    action: replace

  - separator: ;

    regex: __meta_kubernetes_pod_label_(.+)

    replacement: $1

    action: labelmap

  - source_labels: [__meta_kubernetes_namespace]

    separator: ;

    regex: (.*)

    target_label: kubernetes_namespace

    replacement: $1

    action: replace

  - source_labels: [__meta_kubernetes_pod_name]

    separator: ;

    regex: (.*)

    target_label: kubernetes_pod_name

    replacement: $1

    action: replace

这段配置的解释如下:

  • 匹配POD元数据中的pod_annotation字段,找到key为prometheus_io_scrape的label,利用正则表达式匹配true字段,成功则通过服务发现

  • 匹配POD元数据中的pod_annotation字段,找到key为peomerheus_io_path的label,然后把目标label变更为metrics_path

  • 匹配POD元数据中的pod_annotation和address字段,利用正则表达式获取 : 前半部分,也就是Pod的IP地址,然后将pod_annotation_prometheus_io_port的端口添加到Pod IP后面,组合成新的address ,然后替换原Label

  • 匹配POD元数据中的所有以_meta_kubernetes_pod_label开头的标签,然后全部重定向到新的Label当中

  • 匹配POD元数据中的__meta_kubernetes_namespace标签,然后重定向成新的kubernetes_namespace标签

  • 匹配POD元数据中的__meta_kubernetes_pod_name标签,然后重定向成新的kubernetes_pod_name标签

如上规则我们大体就可以看出来,小白想要实现在Prometheus发现目标为容器的服务大体要满足spec.template.metadata.annotations里面的三个要素:

  • scrape:定义是否需要采集监控指标

  • port:定义监控指标的采集端口

  • path:定义监控指标的采集路径


spec:

  template:

    metadata:

      annotations:

        prometheus.io/path: /metrics

        prometheus.io/port: "9104"

        prometheus.io/scrape: "true"

Prometheus实践 服务发现 Consul

有的同学可能会问小白:"Prometheus能不能监控非K8S里面的服务呢?",当然是可以的,小白认为如果是少量的服务,我们可以直接通过Prometheus静态配置目标地址。如果我们的环境处于一个动态的,或者有大量的外部服务的话,小白建议采用一些外部的服务中心来做目标监控节点的服务发现,比如Consul。关于Consul里的Service注册,小白也分享我们自身机房服务器上的node-exporter注册到Consul来做服务发现的实践:

node.json主要解释了node注册到Consul中的一些基本的元数据,这部分可以由你的cmdb生成,或者也可以通过其它工具渲染生成


{

    "Datacenter": "",

    "Node": "x.x.x.x",

    "Address": "x.x.x.x",

    "Service": {

        "ID": "node-exporter",

        "Service": "node-exporter",

        "Port": 9100,

        "Tags": [

            ""

        ]

    }

}

在prometheus中的consul服务发现就可以按照如下配置:


  - job_name: consul-node-exporter

    consul_sd_configs:

      - server: 

        datacenter: 

        scheme: https

        username: ""

        password: ""

        services: ["node-exporter"]

    relabel_configs:

      - source_labels: ["__meta_consul_service"]

        regex: "(.*)"

        target_label: "job"

        replacement: "$1"

      - source_labels: ["__meta_consul_node"]

        regex: "(.*)"

        target_label: "instance"

        replacement: "$1"

      - source_labels: ["__meta_consul_tags"]

        regex: ".*,(.*),.*"

        target_label: "host_group"

        replacement: "$1"

这段配置的解释如下:

  • 匹配Consul中service字段,并将其值赋值给label为job的目标

  • 匹配Consul中node字段,并将其值赋值给label为instance的目标

  • 匹配Consul中tag字段,以逗号分隔,并将其值赋值给label为host_group的目标

这样的话,小白就能通过Consul控制Prometheus内的目标采集节点了。这时候如果需要再进一步推进的话,我们就可以考虑打通公司自身的CMDB了,大概的思路也比较简单。有条件的同学可以在CMDB系统内直接与Consul交互来维护资产,没有条件的同学也可以通过脚本的方式定时同步CMDB数据到Consul,其基本的逻辑如下:


CMDB --------------> |

    |--> Script --> | Consul -->  Prometheus

总之我们终极的目标是任何资产的变更都能同步到Prometheus

node-exporter实践

node-exporter是Prome社区开源一个用于采集主机性能指标的服务,想必大家比较熟悉,小白这里就主要分别提一下关于node-exporter设置启动参数文本收集器

node-exporter的systemd配置如下:


[Unit]

Description=Node Exporter

After=network-online.target

[Service]

User=root

ExecStart=/usr/local/bin/node_exporter \

--collector.textfile.directory /var/lib/node_exporter/textfile_collector \

--collector.tcpstat \

--collector.processes  \

--collector.netclass.ignored-devices="^(cali.*|veth.*|cni.*|docker.*|flannel.*)$" \

--collector.netdev.ignored-devices="^(cali.*|veth.*|cni.*|docker.*|flannel.*)$" \

--collector.filesystem.ignored-fs-types="^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs|tmpfs)$" \

--collector.vmstat.fields="^(oom_kill|pgpg|pswp|pg.*fault).*" \

--web.disable-exporter-metrics

Restart=always

[Install]

WantedBy=multi-user.target

这里面可以看到小白在启动时分别打开了TCP连接状态、进程状态和系统OOM的采集,同时过滤掉了容器相关的网卡信息,以及过滤一些不重要的文件系统数据的采集。

另外关于文本收集器,小白将它理解为是一个文件版的PushGateway,它允许用户自定义一些文件后缀为.prom且满足metrics格式的文本,这样我们就能在http请求里面找到自定义的指标。对于普通用户,我们不用对于一些特定的小功能去开发一个exporter,而是通过crontab定时执行脚本的方式产生一些文本让node-exporter来帮助我们暴露指标。

小白举个实用的脚本例子,可以让大家更直观的看到文本收集器的作用

下面这个脚本用户监控磁盘的Uitl值,并通过node-exporter最终通过Prometheus采集


#!/bin/bash

iostat -x -k 1 2 -d |grep -E 'sd[a-z]' | sed "/(sd[a-z])/N;n;d;" | grep -E "sd[a-z]" | awk '{print $1 "\t" $NF}' \

    | while read dev utils; do

          echo "cloud_storage_disk_uitls{device=\"$dev\"} $utils";

      done  > /tmp/cloud_storage_disk_utils_info.prom

mv /tmp/cloud_storage_disk_utils_info.prom /var/lib/node_exporter/textfile_collector/cloud_storage_disk_utils_info.prom

最终我们就得到这样的数据

image.png

PushGateway实践

PushGateway主要是为了满足允许临时任务或者批处理任务需要将指标让Prometheus来采集的场景。这一块比较简单,小白只推荐一个比较好用,并且带ttl功能的镜像给大家


dmathai/prom-pushgateway-ttl:latest

我们在启动的时候通过参数--metric.timetolive=60s来指定metrics在pushgateway里的保留时间。这里有同学可能会问:"为什么要用ttl",这里小白就卖个关子,有兴趣的同学可以在自己的环境内对比两者的区别


下期实践预告

  • PromQL实践

  • Rules实践

  • Prometheus常见架构

  • Thanos实践

关于云原生小白

云原生小白的创号目的是将平日里离大家较远云原生应用以实用的角度展现出来,站在小白的角度来看待和使用云原生,并以每篇文章解决一个实际问题的出发点带领大家走进云原生世界。

你可能感兴趣的:(云原生实践之Monitoring(一))